SMagic
SMagic

Reputation: 357

A sure shot method to find if SDCard is present

Android check for SD Card mounted always returns true
My question has been asked earlier also & as there were no satisfactory answers, I am stuck. My requirement is very simple.
I am working on an app where I need to ask the user to select a storage to save in app downloads. I need a method that confirms that external SDcard is present.
Have already tried following methods:

This is always returning true probably owing to this reason: https://stackoverflow.com/a/7790228/3475715

final Boolean isSDPresent = Environment.getExternalStorageState().
                      equals(android.os.Environment.MEDIA_MOUNTED);



Following is also not working coz maybe the hard coded path is different for different mobiles

File file = new File("/mnt/extSdCard");
    try {
        File list[] = file.listFiles();
        Toast.makeText(getApplicationContext(), 
         "Yes sdcard is mounted,file count " + list.length,
         Toast.LENGTH_LONG).show();

    } catch (NullPointerException o) {
        Toast.makeText(getApplicationContext(), 
         "Sorry no sdcard is mounted:", Toast.LENGTH_LONG).show();
    }

Any suggestions are appreciated!

Upvotes: 1

Views: 795

Answers (2)

AnV
AnV

Reputation: 2844

You should use getExternalFilesDirs method. This method returns path(s) to both internal memory & Micro SD card (if present). The second returned path would be path of Micro SD card. But that path may not be root directory of Micro SD card.

getExternalFilesDirs introduced in API level 19 is the only official method that can be used to get SD card path. All others methods will return either public or private storage locations(paths) of internal memory.

I have tested this method on my phone & emulator. Kindly, note that I have passed null as parameter for getExternalFilesDirs during testing. But You could also pass parameter(s) like Environment.DIRECTORY_PICTURES, Environment.DIRECTORY_MOVIES etc.

TEST RESULTS:-

When my phone has memory card inserted, getExternalFilesDirs returned :

1st path (internal memory): /storage/emulated/0/Android/data/my_package.appname/files

2nd path (Micro SD): /storage/sdcard1/Android/data/my_package.appname/files

Note: root directory of my SD card is: /storage/sdcard1

On my emulator, getExternalFilesDirs returned :

1st path (internal memory): /storage/emulated/0/Android/data/my_package.appname/files

2nd path (Micro SD): /storage/11E9-4214/Android/data/my_package.appname/files

Note: On emulator, SD card is emulated(not real one).

If Micro SD card is ejected (either on phone or emulator) getExternalFilesDirs returns null

1st path (internal memory): path to internal memory - It varies depending on device

2nd path (Micro SD): null

BUT ;

On some devices, you may not get the Micro SD card path. It means getExternalFilesDirs will return only one path(internal memory). Second path would be empty i.e. it will not return any second path.

Reason: OEM of that particular device may not have set the path (i.e. SECONDARY_STORAGE environment variable) in the device.

This answer for this question says,

the OEM must have set the SECONDARY_STORAGE environment variable in the device specific init.rc file as mentioned here: https://source.android.com/devices/storage/config-example.html

Also the comment made by somesh on the above mentioned answer says,

If that environment variable is not set, you can't write to the sdcard by making use of getExternalFilesDirs since its not going to return the sdcard path.

In those kind of cases, assume that memory card is not present and save whatever you want to save in internal memory.

To Summarize, If getExternalFilesDirs doesn't return second path or returned second path is null, don't store in SD card (store in internal storage); else store in second path returned by getExternalFilesDirs

Suggestion:

To understand about different storage locations in Android, please go through my answer on stackoverflow

Upvotes: 4

somesh
somesh

Reputation: 2579

Android does not expose any API that allows you to get the path of the sdcard root path. You can use reflection and obtain the sdcard root path from StorageManager.java -> getVolumePaths() - http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/os/storage/StorageManager.java#590

You cannot arbitrarily save to any location on the SD Card. You can either use one of the paths returned from getExternalFilesDirs or use SAF(Storage Access Framework) to explicitly request for user permission to write to SD Card. How to use the new SD card access API presented for Android 5.0 (Lollipop)?

Upvotes: 1

Related Questions