0

I have an application that performs a write operation on an external SD Card (external as in not the "external" in the device's flash memory), but as it has been thoroughly discussed here and in quite a few other questions, it appears there is no generic way / supported API to retrieve an SD Card mounting point that works on every phone, from different manufacturers.

With that in mind, something like the code below needs to be done to find out if an external storage device is mounted and where:

final String state = Environment.getExternalStorageState();

if ( Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) ) {  // we can read the External Storage...           
    //Retrieve the primary External Storage:
    final File primaryExternalStorage = Environment.getExternalStorageDirectory();

    //Retrieve the External Storages' root directory:
    final String externalStorageRootDir;
    if ( (externalStorageRootDir = primaryExternalStorage.getParent()) == null ) {  // no parent...
        Log.i("SD Card Path", "External Storage: " + primaryExternalStorage + "\n");
    }
    else {
        final File externalStorageRoot = new File( externalStorageRootDir );
        final File[] files = externalStorageRoot.listFiles();

        for ( final File file : files ) {
            if ( file.isDirectory() && file.canRead() && (file.listFiles().length > 0) ) {  // it is a real directory (not a USB drive)...
                Log.i("SD Card Path", "External Storage: " + file.getAbsolutePath() + "\n");
            }
        }
    }
}

I could be wrong, but I understand the SD Card could be completely empty and that last condition (file.listFiles().length > 0) could return false. So I thought, instead of checking that length, I would add file.canWrite(). That worked as I expected on the phone I am currently testing on (Motorola Atrix MB860 - it's old, I know, but one of my requirements is make it compatible with versions starting from Gingerbread, API 9), but I am unsure whether or not that condition could return true to /mnt/asec/ or /mnt/obb on other phones , recent or not, since their both readable directories, thus also satisfying the first two conditions (and could even return true to (file.listFiles().length > 0) if it had something written on it (like a 50MB+ size file on /mnt/obb).

So, in short, what I need to know is whether an app will ever have write permission to these two locations or if only the system has such permission. If yes, what else can I check for in order to exclude them from the final path I wish to obtain: the external SD Card installed on the device?

Thank you in advance for any help!

Community
  • 1
  • 1
Nick Fanelli
  • 265
  • 1
  • 6
  • 19
  • Also bear in mind that finding the mount point is useless on most Android 4.4+ devices, as [you won't be able to write to removable media anyway as an ordinary SDK app](http://commonsware.com/blog/2014/04/09/storage-situation-removable-storage.html). Beyond that, your algorithm is odd, as it assumes that the parent of `getExternalStorageDirectory()` has some special meaning, and that's certainly not required of any Android device. – CommonsWare Oct 03 '14 at 18:42
  • What do you mean with a "special meaning", @CommonsWare? As far as I can tell, all it assumes is that `getExternalStorageDirectory()`'s parent is the point where an SD Card or other media/shared storage would be mounted. It could be wrong from the standpoint that in some devices that assumption turns out to be incorrect and, thus, I don't find the path I need, but no other issue is clear to me. Do you mind expanding your comment? – Nick Fanelli Oct 03 '14 at 19:55
  • "As far as I can tell, all it assumes is that getExternalStorageDirectory()'s parent is the point where an SD Card or other media/shared storage would be mounted" -- that would be the special meaning. It'll work on a lot of devices, but there is no requirement that device manufacturers put mount points for removable media in that directory. – CommonsWare Oct 03 '14 at 20:02
  • Ok. Great! Thanks for confirming then! – Nick Fanelli Oct 03 '14 at 20:24

1 Answers1

2

This is the output on a Nexus 5

shell@hammerhead:/ $ ls -la /mnt/                                              
drwxr-xr-x root     system            1970-09-18 01:42 asec
drwx------ media_rw media_rw          1970-09-18 01:42 media_rw
drwxr-xr-x root     system            1970-09-18 01:42 obb

as you can see only root has write permission on the directory. So the only way an app can write that directory is to be executed as root

Blackbelt
  • 156,034
  • 29
  • 297
  • 305