2

Ok, I have searched the forums high and low, and am unable to find an acceptable answer to test if the SD card is properly mounted and is writable on Android 7 devices. (There are many answers, but none that actually work).

I understand that one must use Environment.getExternalStorageState(), as per my code below:

 pathName=context.getFilesDir().getAbsolutePath()+"/"+SavePath;
 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
     pathName= Objects.requireNonNull(context.getExternalFilesDir(SavePath)).getAbsolutePath();

BUT...

Regardless whether the SD card is mounted or not, this always return TRUE, simply because the SD card is mounted as an emulated resource, NOT a removable resource.

I can use Environment.isExternalStorageEmulated() to check this state, BUT it still doesn't tell me whether the SD card is available or not. (i.e.: isExternalStorageEmulated() will always return true, whether there exists an SD card or not, because it is set by the file system on startup and doesn't seem to care whether there is a physical SD card in the slot or not).

Other than trying to write to the SD card, and capturing the exception error if it doesn't exist, is there any way to tell if an SD card is present or not BEFORE I attempt to write to it?

EDIT:

After reviewing the proposed solutions, this is the best I can come up with. This seems very clunky. Any ideas on how to improve this?

        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            if (Environment.isExternalStorageEmulated()){
                File[] storage=getExternalFilesDirs(null);

                // Find the first non-emulated storage space
                for (File file: storage){
                    if (!file.toString().contains("emulated/"))
                        System.out.println(file.toString());
                }

            }
        }
  • https://developer.android.com/training/data-storage/files – Naveen Tamrakar Jun 11 '18 at 11:55
  • getExternalStorageState(File path) expects a file with the path to check. See https://developer.android.com/reference/android/os/Environment.html#getExternalStorageState(). Below Api level 21 it is getStorageState(File path). – Vall0n Jun 11 '18 at 11:57
  • @Vall0n, I am working with API level 22. See edits; any ideas on how to improve this? Many thanks. – Marc Violette Jun 12 '18 at 11:18
  • @MarcViolette How about `Environment.getExternalStorageState(context.getExternalFilesDirs()[0]).equals(Environment.MEDIA_MOUNTED)` But `context.getExternalFilesDirs()` is available since Kitkat. See [here](https://stackoverflow.com/questions/38324985/get-removable-sd-card-path-in-android?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa) – Vall0n Jun 12 '18 at 11:55
  • Also have a look at [this question](https://stackoverflow.com/questions/7616974/how-to-check-internal-and-external-storage-if-exist) and did you test that on a real device with a removable sdcard? Not sure how an emulated device or custom rom will behave... – Vall0n Jun 12 '18 at 12:14

2 Answers2

1

Your edit answer looks good since you discard the emulated storage. As an alternative you can also count the directories. If it's greater than 1 (also discarding the emulated storage) then the storage has an SD card:

public boolean hasExternalSD() {
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
        //External Storage Emulated
        if (Environment.isExternalStorageEmulated()){
            if (ContextCompat.getExternalFilesDirs(context, null).length > 1) {
                return true;
            }
        }
    }
    return false;
}
0

Both getFilesDir() and getExternalStorageDirectory() are always available on every Android device.

They have nothing to do with a removable micro SD card.

greenapps
  • 11,154
  • 2
  • 16
  • 19
  • Ok, so how do I determine if there exists a removable SD card that I can write to at execution time? – Marc Violette Jun 12 '18 at 11:17
  • You have to look at the second item returned by getExternalFilesDirs(). There will only be a second item if a micro SD card is inserted or a flash disk is inserted in a OTG USB port. You will then only be able to write to the obtained app specific directory. – greenapps Jun 12 '18 at 11:41
  • On Android 7+ You can investigate Storage Volumes. – greenapps Jun 12 '18 at 11:42
  • On Android 5+ you can use Intent.ACTION_OPEN_DOCUMENT_TREE to let the user indicate de micro SD card. After that you can use the Storage Access Framework to write to the whole card. – greenapps Jun 12 '18 at 11:47