5

I know how to do following:

  • listen to attach and detach events of usb devices
  • getting all attached devices
  • getting permissions for a device

So in the end I have an UsbDevice and I have permissions to read/write it. How to go on from here?

I can open the device and get a FileDescriptor like following:

 UsbManager manager = (UsbManager) activity.getSystemService(Context.USB_SERVICE);
 UsbInterface intf = device.getInterface(0);
 UsbEndpoint endpoint = intf.getEndpoint(0);
 UsbDeviceConnection connection = manager.openDevice(device);
 boolean interfaceClaimed = connection.claimInterface(intf, true);
 int fileDescriptor = connection.getFileDescriptor();

How can I work with this FileDescriptor now? Or how else can I access the files on the USB device?

EDIT

  • Solution for android < 6: Don't open a UsbDeviceConnection and just try to find the usb devices path. Still, then you have the problem to distinguish between multiple usb devices and don't know which path belongs to which device...

  • Solution for android >= 6: Use the Storage Access Framework, actually I don't know how this works yet...

prom85
  • 16,896
  • 17
  • 122
  • 242
  • Mostly the stick will be mounted on a file system folder like /storage/usbdrive or so. Under Marshmellow that path is not there and you can use the Storage Access Framework. – greenapps Jan 29 '16 at 17:25
  • I edited my question and added some things. Actually do you know how to distinguish between the usb devices? I can find all available paths to the usb storages, but I don't know which path belongs to which device – prom85 Jan 29 '16 at 18:46
  • Never saw more then one usbdrive path. Where do you see more? – greenapps Jan 29 '16 at 19:19
  • via usb otg you can mount anything, usb drive pen, external hard disc or even an external card reader with eventually many cards in it... – prom85 Jan 29 '16 at 19:20
  • Yes. And what paths do you see when there are many cards in it? Which device is showing that? – greenapps Jan 29 '16 at 19:22
  • I haven't tried it myself yet (I don't have a card reader) but I've read already from mounts like "UsbDriveA", "UsbDriveB" or similar names that let me assume, that it would work... – prom85 Jan 29 '16 at 19:24
  • Just tried to list the files on the usb device => it does not work. `file.listFiles()` return null... According to the documentation, this happens if an IO exception occurs... So it seems like that way is not working at all... – prom85 Jan 29 '16 at 20:55
  • What is file.getAbsolutePath() when you do the listFiles()? listFiles would return null if there are no files. Or if you did not request the READ_EXTERNAL_STORAGE permission. – greenapps Jan 29 '16 at 20:57
  • Path is `/mnt/media_rw/UsbDriveA` and there are files on the usb drive... – prom85 Jan 29 '16 at 20:59
  • Another question: with the `storage access provider` you mean following solution: start an intent with `ACTION_OPEN_DOCUMENT_TREE` and let the user select the usb device and then use `DocumentFile`s to access data on the usb storage... This means, I have to check if the user really selected the usb storage (or at least a folder on the usb device) and not the internal storage and then I get access to the folder the user selected + all data underneath it... I got this working, but telling the user to select the root directory of the usb device is a challenging thing for many... – prom85 Jan 29 '16 at 21:28
  • Indeed. The usb drive is clearly marked as such. So trust the users of your app. – greenapps Jan 29 '16 at 21:34
  • Actually I do trust in that. But not, that they select the root folder... But thanks for the hints and tipps... – prom85 Jan 29 '16 at 21:36
  • @prom85 Are you still seeking help for this question? I noticed I was the only poster, I added a lot of info on my "alternate" method, which may be useful for 6.0 Marshmallow compatibility. – Aaron Gillion Apr 01 '16 at 07:05

1 Answers1

2

Because I am as stumped as you are, I would go the route of using the ls command.

Code example:

try {
    Process process = Runtime.getRuntime().exec("ls /storage/UsbDriveA");
    BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String listOfFiles = "";
    String line;
    while ((line = buffer.readLine()) != null) {
      listOfFiles += line;
    }
} catch (InterruptedException e) {
    e.printStackTrace();
}

ls will return no such file or directory if the mount point is incorrect.

Here is a list of many of the mount points manufacturers use:

/storage/UsbDriveA     (all Samsung devices)
/storage/USBstorage1   (LG G4, V10, G3, G2, other LG devices)
/storage/usbdisk       (Moto Maxx, Turbo 2, Moto X Pure, other Motorola devices)
/storage/usbotg        (Sony Xperia devices, Lenovo Tabs)
/storage/UDiskA        (Oppo devices)
/storage/usb-storage   (Acer Iconia Tabs)
/storage/usbcard       (Dell Venue -- Vanilla Android 4.3 tablet)
/storage/usb           (HTC One M7, and some Vanilla Android devices)

(Based on my collection of devices and 3 other people's, and a quick trip to Bestbuy for testing the latest flagships. The only popular devices I know I'm missing are Hawuei/Xioami devices based in China, which are becoming popular in English countries, but likely they use one of the above.)

To find the right mount point, you would listen for no such file or directory and loop/re-execute the exec() statement with the next mount point.

Once all that is done, you can easily read files by using cat /storage/.../file.txt and write by using redirection: echo test > /storage/.../file.txt

Hope this helps

Aaron Gillion
  • 2,227
  • 3
  • 19
  • 31