通过Android USB主机模式从U盘读取数据

3
我需要从U盘中读取文件,我的代码如下:

我需要从U盘中读取文件,我的代码如下:

private static final String ACTION_USB_PERMISSION = "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (ACTION_USB_PERMISSION.equals(action)) {
            synchronized (this) {
                UsbDevice device = (UsbDevice) intent
                        .getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (intent.getBooleanExtra(
                        UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    if (device != null) {
                        // call method to set up device communication
                    }
                } else {
                    Log.d(TAG, "permission denied for device " + device);
                }
            }
        }
    }
};

为了检测设备,我使用:

mgr = (UsbManager) getSystemService(Context.USB_SERVICE);
devs = new HashMap<String, UsbDevice>();
devs = mgr.getDeviceList();

获取设备和接口之后,我将以下列方式获取端点:
public void getEndpointCount(View v) {
    itf = value.getInterface(0);
    endPointCount = itf.getEndpointCount();

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("No. of Endpoints: " + endPointCount)
            .setTitle("Endpoint Count").setCancelable(true)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
    AlertDialog alert = builder.create();
    alert.show();
    ((Button) findViewById(R.id.button4)).setEnabled(true);
}

public void getEndpointDirections(View v) {
    endPoint = null;


    UsbDeviceConnection conn = null;

    if (mgr.hasPermission(value)) {
        conn = mgr.openDevice(value);
        conn.claimInterface(itf, true);
    }

    String str = null;
    for (int i = 0; i < endPointCount; i++) {
        ((TextView) findViewById(R.id.tvLoopVal)).setText("" + i);
        endPoint = itf.getEndpoint(i);
        str = str + " Endpoint: " + i + " - " + endPoint.getDirection()
                + "\n";

if (endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
            ((TextView) findViewById(R.id.tvLoopVal)).setText("" + (i - 1));
            if (endPoint.getDirection() == UsbConstants.USB_DIR_IN) {
                Toast.makeText(this, "epin", Toast.LENGTH_SHORT).show();
                epIn = endPoint;
            } else {
                epOut = endPoint;
                Toast.makeText(this, "epout", Toast.LENGTH_SHORT).show();
            }
        }

    }

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage(
            str + " Mac packet Size = " + endPointUsed.getMaxPacketSize())
            .setTitle("Endpoints Directions").setCancelable(true)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
    AlertDialog alert = builder.create();
    alert.show();

}

在最后,我已获得了终端节点,但现在我卡住了,不知道下一步是读取还是写入数据到U盘。我没有头绪,请指导我该去哪里寻找答案。
此外,即使我没有将任何USB设备连接到我的平板电脑上,它仍然显示发现了1个设备,并且当我通过OTG线连接U盘时,它会显示发现了2个设备!这也很奇怪。
编辑:
我还使用USB请求方法初始化请求,但我仍然不知道它是如何工作的。
public void initializeRequest(View v) {
    UsbRequest uReq = new UsbRequest();
    Toast.makeText(this, "" + uReq.initialize(conn, epIn),
            Toast.LENGTH_SHORT).show();
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage(
            " Is Request Initialized: = " + uReq.initialize(conn, epIn))
            .setTitle("Request Initialization").setCancelable(true)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
    AlertDialog alert = builder.create();
    alert.show();
    byte[] bb = new String("Hello").getBytes();
    ByteBuffer bBuffer = ByteBuffer.allocate(5);
    // bBuffer.put(bb);
    uReq.queue(bBuffer, 5);

    UsbRequest request = conn.requestWait();
    // Object obj = uReq.getClientData();
    // Log.v("Client Data", "" + obj.toString());
    if (request != null) {
        Toast.makeText(this, "Not null request", Toast.LENGTH_SHORT).show();
        Log.v("Response of request wait", ""
                + request.getClientData().toString());
        request.close();
    }
    uReq.close();

    // Log.v("Response of request wait", "" + conn.requestWait());
    // uReq.close();
}

我验证了端点是否被分配,但当执行此方法时,应用程序只是等待,什么也不做。过一段时间,Android要求关闭该应用程序。是因为requestWait()函数导致应用程序等待某种事件吗?
编辑
好的,如果我们忘记从闪存驱动器进行读取,仅需要从USB设备获取音频流,例如麦克风,我不会读取任何内容,只会捕获麦克风提供的任何内容,那么我仍然需要做别的事情吗?
2个回答

1

看起来你并没有真正读取任何数据。如果你有一个从设备到主机的EndPoint,你应该能够使用bulkTransfer方法从中读取数据。

我对低级USB通信并不是很熟悉,但我认为你需要自己处理文件系统解析。如果你读取驱动器上的第一个扇区(512字节),并且该扇区的最后两个字节为0x55,0xAA,则该驱动器可能采用FAT文件系统格式,你需要从那里开始工作。


我想做的是将USB网络摄像头连接到Android手机并从摄像头获取视频。我尝试读取U盘是为了了解USB设备如何与Android设备通信。除了Android的usbhost类之外,我不知道从哪里开始。目前我看不到任何前进的方法。 - Calvin
你尝试过枚举端点并使用UsbDeviceConnection从合适的端点读取数据吗? - Michael
是的,实际数据在这段代码中没有被读取,我发现我必须写一些低级别(类似于驱动程序)的代码才能访问来自闪存驱动器的数据。 - Calvin
@Calvin,你有找到任何方法吗?请分享一下将文件移动到OTG的代码。 - Ravi Mehta
1
@RaviMehta 不,我的项目后来被移动到BT设备上了,所以没有进一步研究。 - Calvin

0

由于没有被接受的答案,我将发布我的答案。

有一个名为libaums的开源库,它实现了Android的USB大容量存储模式(UMS)以及Fat32文件系统。您可以在Android应用程序中使用此库来读取/写入USB设备中的文件。该库处理与USB设备的低级通信。

https://github.com/magnusja/libaums

基本示例:

UsbMassStorageDevice[] devices = UsbMassStorageDevice.getMassStorageDevices(this /* Context or Activity */);

for(UsbMassStorageDevice device: devices) {

   // before interacting with a device you need to call init()!
   device.init();

   // Only uses the first partition on the device
   FileSystem currentFs = device.getPartitions().get(0).getFileSystem();
   Log.d(TAG, "Capacity: " + currentFs.getCapacity());
   Log.d(TAG, "Occupied Space: " + currentFs.getOccupiedSpace());
   Log.d(TAG, "Free Space: " + currentFs.getFreeSpace());
   Log.d(TAG, "Chunk size: " + currentFs.getChunkSize());
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接