How can I read files from usb device on android? - android

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?

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

Related

How to access single USB devices of a Composite USB device?

I would like to send data from my Windows computer to my Android Mobile.
For this, I need to activate the Accessory mode of the Android device and the USB Host mode on the Windows device.
On my Windows computer, I have a USB Composite device for the Android Mobile. This Composite USB device bundles several interfaces: Enumeration of USB Composite Devices.
Unfortunately, I can't find information how I can access the single devices of a Composite device.
I want to get a device id / path, which I can open with CreateFile to use the created HANDLE for opening a WinUsb handle with WinUsb_Initialize.
But if I try to open a Composite USB device with CreateFile, I get a ERROR_NOT_ENOUGH_MEMORY result.
I'm using this code:
_deviceHandle = CreateFile(
deviceId, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_NONE, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
... with the filename "\?\USB#VID_04E8&PID_6864#RF8NB0NMT0X#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"
It's a GUID_DEVINTERFACE_USB_DEVICE device id for a Samsung Galaxy mobile with enabled USB debugging.
As the driver Windows uses ssudbus2.sys, Version 2.17.16.0 (2021-09-14) from Samsung Electronics Co. Ltd.
The app MyPhoneExplorer can access to my mobile. So it a solution without a special driver must be possible.
How can I get this device id / path of the single USB devices inside a Composite USB device?
The filename you are using represents the overall USB device; it doesn't represent any particular instance. A filename that represents interface will have something like &mi_01 right after the product name, where 1 is the 0-based interface number.
You might be able to just insert the appropriate &mi_xx string into your filename at the appropriate place and get it work. I think you'd also need to modify the GUID at the end of the string, which is the device interface GUID.
The more standard way to find the filename in code is to use the SetupAPI and the configuration manager (CM) API to iterate through all the child devices of your USB device. Look for a child whose device instance ID (retrieved with CM_Get_Device_ID) contains MI_xx where xx is the two-digit interface number you are looking for.
It takes a lot of effort to write up this code in standalone form, and test it, and debug it, so I will not be presenting you with a working code example. Instead, I encourage you to look at the working code in the get_interface_composite function of libusbp which does what you need to do:
https://github.com/pololu/libusbp/blob/759f48d/src/windows/interface_windows.c#L86
There are some more steps to get the path of that device node. And then the code that actually calls CreateFile and WinUsb_Initialize is here:
https://github.com/pololu/libusbp/blob/759f48d/src/windows/generic_handle_windows.c#L56-L77

Get USB Storage Volume Android 11

I am working on an app that reads/writes a USB drive using Storage Access Framework. When requesting permission to the USB drive, the app needs to show the permission dialog in the root of the USB drive, so the user can just press one button to grant access instead of navigating to the USB root.
When running the app on a Galaxy S10e running Android 11, I cannot find a way to get the app to display the permission dialog in the USB root. As far as I know there are two ways to do this - either setting the Uri when creating the OPEN_DOCUMEMENT_TREE intent, or calling createOpenDocumentTreeIntent() on a StorageVolume instance. I can see that a USB drive is connected using the UsbDevice class, but no matter what I try, I cannot find the USB drive as a StorageVolume and I cannot get the Uri.
I have tried StorageManager getStorageVolumes() and MediaStore getExternalVolumeNames. I also tried getting a Uri using UsbDrive getDeviceName(), and creating Uris from "/mnt/sdcard/usb_storage" and "/mnt/sdcard/usbStorage". I have a BroadcastReceiver that listens for android.intent.action.MEDIA_MOUNTED, where I can usually get the Uri from the intent data, but this is not being broadcasted. So far I've had zero luck getting this to work.
Does anyone know why this is or if there is a way to make this work?

How can I retrieve an SD card's serial number in Android 7.0+?

N.B.: This question about the serial number of the physical SD card, not the UUID of the mounted volume. These are two independent pieces of data.
In some versions of Android, and other variants of Linux, it's possible to get the serial number of a mounted SD card, e.g. by reading the contents of /sys/class/mmc_host/mmc0/mmc0:0001/serial or /sys/block/mmcblk0/device/serial (specific numbers may vary). In my testing this has worked pretty reliably, as long as the SD card is inserted in a built-in SD card slot (not mounted via USB adapter).
But as of Android 7.0 Nougat, the OS is said to be blocking access to this information, at least on some devices. I tested this by running a test app on a new Alcatel A30 GSM (Android 7.0), and in fact the above approach fails with a permission error:
java.io.FileNotFoundException: /sys/block/mmcblk0/device/serial (Permission denied)
at java.io.FileInputStream.open(Native Method)
For future reference, we (testing from an adb shell) have permissions to ls -ld the following:
/sys/class/mmc_host but not /sys/class/mmc_host/mmc0
/sys/block but not /sys/block/mmcblk0
Since the above approach no longer works,
Is there another way to obtain the serial number of a mounted SD card in Android 7.0 or later?
Failing that, is there any documentation or other statement from Google on plans for providing or not providing this function? I haven't found anything in the Android issue tracker, but maybe I'm not searching right.
To make sure the question is clear, I'm talking about what an ordinary (non-system) app running on a non-rooted device can do, with any permissions that an app can normally request and receive.
FYI, the /sbin directory doesn't seem to be readable, so commands like /sbin/udevadm aren't an option.
In Android N access to /sys nad /proc was significantly restricted, this was done to provide stricter sandboxes where applications run. This is explained in https://issuetracker.google.com/issues/37091475 as intentional. Actually its not said that all the data in /sys is not accessible, and Google is open to allow access to other files from this location:
If there are specific files in /sys you believe should be available to applications, but are not, please file a new bug where the request can be evaluated. For instance, /sys/devices/system/cpu is available to all processes, so it's inaccurate to say all of /sys is restricted.
I have a bad feeling that google is making changes similar to Apple where it is not allowed to gain hardware id-s. If that is not resolved then the solution is to use google account IDs instead. But I am aware it is not always possible, and will require major changes in business logic (licensing etc.).
Hopefully your bug report will be considered positively.
another related SO I found : File system changes in Android Nougat
Use StorageVolume.getUuid() on StorageVolume which you get from StorageManager.
The value is volume ID assigned during formatting of the card, and its length/format differs depending on file system type. For FAT32 it is XXXX-XXXX, for NTFS it's longer hex string, for Internal mass storage it returns null.
public String getSDCARDiD()
{
String sd_cid = null;
try {
File file = new File("/sys/block/mmcblk1");
String memBlk;
if (file.exists() && file.isDirectory()) {
memBlk = "mmcblk1";
} else {
//System.out.println("not a directory");
memBlk = "mmcblk0";
}
Process cmd = Runtime.getRuntime().exec("cat /sys/block/"+memBlk+"/device/cid");
BufferedReader br = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
sd_cid = br.readLine();
//System.out.println(sd_cid);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return sd_cid;
}
try this: reference original link :Android get id of SD Card programmatically
adb shell cat /sys/class/mmc_host/mmc1/mmc1:*/cid
You can also try
sudo hwinfo --disk
to get information on your disks, including SD Cards.
Also try
sudo hdparm -I /dev/sdb | more
As an FYI to those looking into UUID or volume serial numbers of FAT type volumes under Android: Some Fujifilm cameras, including the X-T30 (Firmware 1.10) do not write a volume serial number into the FAT volume when formatting.
Under Windows, CHKDSK displays no volume serial number at all.
On Android, calling StorageVolume.getUuid() returns "0000-0000".
This is all fine and dandy, until you on Android mount two Fujifilm-formatted cards via a hub. Then there seems to be identity collision, where the Android OS prompts the user to format one of the cards. Separately they are accessible.
I'm guessing there are two combined problems here:
1) Fujifilm is not writing a volume serial number when formatting, and
2) Android uses the volume serial number as part of the mount point path, leading to collision.
Fujifilm and Google might both want to pay attention to this issue.
EDIT: Card formatted in a Nikon D810 also has the same problem, no Volume Serial Number.

Copy files from android to USB drive?

Can not find good solution of how to copy files from android device to USB drive. I know that android has API's for that since 3.1 version. However docs are not very clear, where I can use that APIs. Is there someone who has experience on this area? I registered broadcast receiver and after allowing usb connection to app, just wanted to transfer some bytes to USB storage like below:
Set<String> devices = mUsbManager.getDeviceList().keySet();
Object[] array = devices.toArray();
String text = array[0].toString();
byte [] s="hello".getBytes();
UsbDeviceConnection connection=mUsbManager.openDevice(mUsbManager.getDeviceList().get(text));
UsbEndpoint usbEndpoint=mUsbManager.getDeviceList().get(text).getInterface(0).getEndpoint(0);
connection.bulkTransfer(usbEndpoint,s,s.length,10000);
However, I did not get what I expect. Could someone help, please?
Thanks in advance
Found solution on this link: https://github.com/mjdev/libaums. You need to write your file system to interact with the usb drive

Automatic Detection of mass storage/external drive in Android

Is it possible or is there a way in Android v2.2+ to detect if there is a mass storage, external drive or micro SD inserted in the device?
My objective is, I want to create an app that will be invoked once an external storage like micro SD is inserted in the device?
I want to know if:
1) Is there a standard intent broadcasted once an SD is mounted in the device?
2) Do I have to deal with it in the native driver layer to achieve this?
Any thoughts are highly appreciated.
Thanks
Yes there is a standard intent broadcast, you are probably looking for the ACTION_MEDIA_MOUNTED broadcast.
ACTION_MEDIA_MOUNTED
Since: API Level 1
Broadcast Action: External media is present and
mounted at its mount point. The path to the mount point for the
removed media is contained in the Intent.mData field. The Intent
contains an extra with name "read-only" and Boolean value to indicate
if the media was mounted read only.
Source

Categories

Resources