Get USB Storage Volume Android 11 - android

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?

Related

How can I write a file to my SD card in Android?

I have a requirement for my Android app to be able to receive files from a server and save them in an arbitrary location on my SD card. When I say "SD card", I don't mean the /sdcard/ directory - AKA /storage/emulated/0/, I mean the physical removable SD card.
My initial attempt:
FileOutputStream(File("storage/ABCD-1234", "test_file.txt")).use {
it.write("Hello world!".toByteArray())
}
where "ABCD-1234" is replaced with the actual storage ID string. This gives me an IOException saying permission denied, even though I have the WRITE_EXTERNAL_STORAGE permission granted. Fine, there must just be some restrictions on SD card writing access. So I spent most of today researching around the internet for apps which can already do this. And I come across this one called SSH/SFTP Server, using which I was able to push a file to the device's SD card via WinSCP from a laptop over WiFi. The thing is, I can't figure out how to go about requesting this ability in my app. Can anyone point me in the right direction?
This is targeting Android Q (10), in case it matters at all.

Grant USB permissions as device owner

A device owner can grant runtime permissions to a third-party app using DevicePolicyManager.setPermissionGrantState() to avoid user prompts.
But is there any way for a device owner to grant USB permissions as well, so that this app gets access to plugged USB devices without user prompt ?
I've tried to call UsbManager.grantPermission() (with reflection) but it raises a SecurityException since it requires the MANAGE_USB permission which is granted only to system apps (and not to device owner, obviously).
NB: I'm looking for a solution working on a non-root & non-custom Android system, the device owner app is set using Android Enterprise provisioning methods.
There is a special system config to disable USB permission dialogs:
https://github.com/aosp-mirror/platform_frameworks_base/blob/8ff4a5a5b510e724b25ac00369696594bb0c9fdc/core/res/res/values/config.xml#L2283
Maybe you can also change it at runtime with root privileges using setprop.
Another way is to customize the UsbUserSettingsManager class, specifically this method: https://android.googlesource.com/platform/frameworks/base.git/+/master/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java#178
I assumed that as a device owner you have full control over your ROM source code.
It's a bit old, but hopefully it helps s.o. else.
I've been using this for granting permission to apps
public boolean setPermissionGrantState (ComponentName admin,
String packageName,
String permission,
int grantState)
Link: https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setPermissionGrantState(android.content.ComponentName,%20java.lang.String,%20java.lang.String,%20int)

How can I read files from usb device on 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

How to write the data to USB stick(Pendrive) from the application in android

In my application i have to write the Data to USB stick(Pendrive) from the application.
My application will support to write the data to Local memory and USB stick(Pendrive).
Currently i am able to write the data to Local memory ,but i am unable to write to USB stick(Pendrive).
Do we need to add any extra permission other than WRITE_EXTERNAL_STORAGE?
Is writing to USB stick(Pendrive) through app possible?
I am able to ready the files which are there in the USB,i am not able to write the data.
Here is the folder path where i want to write the data.
"/storage/usb1/TestFolder"
Can i get some help on this?
In order to write some data to USB, we need
uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE"
By referring some links i got to know that the above permission can get by Provider of the device.
So we can apply above mechanism to get it done.

How to “lock down” the device, on removal of SIM card or SD card?

I am distributing android phones with vital business information to my agents. Incase user remove SIM card, SD card or try to modify the data stored on the device storage, system need to lock down and if possible send notification to the concern persons.
This would require changing the baseband software of the device. You CANNOT do this on a post-production phone.
Update
Potentionally you can do something with the DeviceAdmin Api
I think you could register a DeviceAdmin, and as soon as the phone boots up check the SIM and SDCARD. Then you could either continue to wipe data or set a new password for the device using resetPassword and call locknow. This way the phone is locked and the user will need password from you
Don't store critical information on the phone.
Failing that, don't store critical information in plain-text.
Use some kind of network-based authentication to control access at run-time.
At the end of the day, your data will never be 100% secure against a determined software hacker. Or a user with a camera. So work with trustworthy people.
You can simple do following things.
1) register receiver on SD card states, if it is unmounted take action accordingly, can do same with the sim , for SIM save the sim number which can be get from TelephonyManager class.
2) and if user switch off the phone and then pull sd card or sim, on reboot app can check if the sdcard is present or the Sim changed. in this case too you can take action accordingly,
but if user replaces the sdcard in switch off mode you can not do anything.
I think it's possible to:
Register BroadcastListener for the BOOT_COMPLETED broadcast
So after boot completing you will have BroadcastReceiver started - where you can check presense of SIM or SD card - which is easy like:
telephonyMgr =
(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String simSerial = telephonyMgr.getSimSerialNumber();
If check fails you can either BRICK device (which is cruel) or wipe data through DevicePolicyManager.wipeData

Categories

Resources