Automatic Detection of mass storage/external drive in Android - 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

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.

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 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

getExternalFilesDir() problems

So the app I'm working on is making use of the external files dir to store some downloaded information. The issue I'm running into is, very ocassionally the getExternalFilesDir() method will return null. My understanding of this method might be flawed, but I was under the impression that it would return null under TWO distinct scenarios:
1) The user has an SD card slot but does NOT have an sd card mounted (or the SD card is mounted but plugged into a computer as mass storage option)
2) The app does not actually have read/write permissions
The app has the read/write permissions (it must since it works in most scenarios), and I I'm checking for the first case with the following code:
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
editor.putBoolean(AUDIO_LOCATION_KEY, true);
subPath = context.getExternalFilesDir(null).getPath();
}
The app is crashing with a null pointer exception from the getExternalFilesDir line. I can't reproduce the crash, Is there something I'm missing? I would've that that if that check passed that we'd be guaranteed to get something back. Any insight would be much appreciated!
Thanks.

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