6

I'm trying to create something like file explorer through connected usb devices(via OTG or usb ports on android TV). All I need for this is a path something like "/storage/sda4" and device identifier, and then I can work with device through simle android class File. Is sounds simple but I can't find any info about this, but all file explorers can do it (for example ESExplorer). Ok, I find a simple way to get all connected usb devices with identifier

UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
usbManager.getDeviceList();

but how can I get an info about path? deviceName contains something like this "/dev/bus/usb/00x" but it can't help me, I need simple emulated android path ("/storage/sda4"). This page https://developer.android.com/guide/topics/connectivity/usb/host.html tells that I need to get UsbInterfaces and make UsbConnection to bulk transfer and other bullshit, I done it all but didn't find path to device or any other info about usb file list.

Ok, I find another way to get (that don't requires permission!) to get path to all connected devices

StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Method getVolumeListMethod = StorageManager.class.getDeclaredMethod("getVolumeList");
Object[] storageVolumeList = (Object[]) getVolumeListMethod.invoke(storageManager);

and it works but I need to identify a device(because I want to cache files of different usb storages) but all that I can get from volume object is mStorageId, mDescriptionId, mPrimary, mRemovable, mEmulated, mMtpReserveSpace, mAllowMassStorage, mMaxFileSize, mOwner, mUuid, mUserLabel, mState, mSubSystem. None of this can not identify the device: mDescriptionId and mStorageId are unique fot usb port, mUuid is null, mUserLabel is not unique.

Environment.getExternalFilesDirs() won't help, it don't provide any device id and works only with one device.

I find a similar question here, but it has no right answer Android list files from USB Drive.

Well, is a simple way to get list of usb devices with path and identifier exists?

Community
  • 1
  • 1
LamaUltramarine
  • 115
  • 1
  • 1
  • 7

1 Answers1

6

All I need for this is a path something like "/storage/sda4" and device identifier, and then I can work with device through simle android class File

No, because you do not have arbitrary access to removable storage, including USB OTG drives, on Android 4.4+.

all file explorers can do it (for example ESExplorer)

Pre-installed "file explorer" apps may have additional rights granted to them by the device manufacturer or custom ROM developer. Otherwise, they too do not have arbitrary access to removable storage.

is a simple way to get list of usb devices with path and identifier exists?

Not with a filesystem path, no. getStorageVolumes() on StorageManager will give you a list of storage volumes, which includes external storage and removable storage. You can then use createAccessIntent() on StorageVolume to ask the user for permission to work with the volume. If they grant permission, you get a Uri back that:

  • Serves as a temporary identifier for the volume (i.e., will no longer be usable as an identifier if the user ejects the media, but until then, can distinguish one volume from another), and

  • Lets you work with a portion of the contents of that volume, though using Uri values, not filesystem paths

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Many thanks for the detailed answer. I try getStorageVolumes, but it requires 24 API and higher, but for now it spreads out not so much. After your answer I understand that only way I can do it is the second second way that I described, it provide me the path of all devices, and I can work with simple class File(I tested it on android 5 and 5.1:) Maybe it is defect of android but it truth. I will use mUserLabel as an id, that unique in most cases. – LamaUltramarine Jan 21 '17 at 14:14
  • StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); Method getVolumeListMethod = StorageManager.class.getDeclaredMethod("getVolumeList"); Object[] storageVolumeList = (Object[]) getVolumeListMethod.invoke(storageManager); I use these lines to get list of storage volumes but I get only /storage/emulated/0 , while my OTG was connected with a pendrive. Why I am not getting path for OTG connected device? – Anupriya Jan 23 '17 at 07:23
  • @Anupriya: Possibly because you are using reflection to get at something that is not supported on the version of Android that you are running. – CommonsWare Jan 23 '17 at 12:32
  • @Anupriya are you make it for every object? I tested it on android 4.4.+ and it works everywhere: Field pathField = object.getClass().getDeclaredField("mPath"); pathField.setAccessible(true); Object pathObject = pathField.get(object); – LamaUltramarine Jan 25 '17 at 16:05
  • @Vladislav I have tried everything but its not giving the expected result, maybe the manufacturer hasn't provided the permissions to access removable media. – Anupriya Jan 27 '17 at 06:01
  • @CommonsWare Sorry to bring this up 3 years later. But I am trying to access the storage volumes using `getStorageVolumes()` for a device that has USB OTG capability. But getStorageVolumes() is only returning the internal/shared volume. I am sure the connected usb device (which is an Honor phone) is mounted because the default file explorer app is showing all the files in the connected phone via MTP. I am on android 8.0/8.1 AOSP & the default file manager app is com.android.documentsui – kb_14 Feb 14 '20 at 11:06
  • 1
    @kb_14: Off the cuff, the manufacturer might have gone their own way on handling USB storage. Does this device have an SD card slot? If so, if you put in a card, does it show up in `getStorageVolumes()`? – CommonsWare Feb 14 '20 at 11:58
  • This device does not have an SD Card slot unfortunately. Only internal storage and USB OTG capability – kb_14 Feb 15 '20 at 06:44