Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why getExternalFilesDirs() doesn't work on some devices?

My app runs on Android 5.0. I use method getExternalFilesDirs() to check if external SD card is available. If it returns more than 1 File, that means external SD card exists.

But on some devices (for example Elephone G2), method getExternalFilesDirs() returns only one directory of primary storage. I'm sure that device has external SD card (/storage/sdcard1/).

Can any one give me the answer?

like image 628
TOP Avatar asked Oct 26 '15 16:10

TOP


3 Answers

this issue there is in some of Lenovo device too.

my solution is this.

String EXTERNAL_SD_PATH1;
String EXTERNAL_SD_PATH2;

public boolean hasExternalSDCard()
{
    try
    {
        String state = Environment.getExternalStorageState();
        if(Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state))
        return true;
    }
    catch (Throwable e)
    {}

    return false;
}

        @SuppressLint("SdCardPath")
        protected synchronized void _prepareStorage()
        {
            EXTERNAL_SD_PATH1 = null;
            EXTERNAL_SD_PATH2 = null;
            if (hasExternalSDCard())
            {
                try
                {
                    if(VERSION_SDK_INT > 18)
                    {
                        Context context = getContext();
                        File[]  sds = getExternalFilesDirs("");

                        if(sds == null)
                            return;

                        if(sds.length >= 2)
                        {
                            EXTERNAL_SD_PATH1 = TextWorker.getSubStringBeforeLastMark(sds[1].getAbsolutePath(),"/Android/");
                            if(sds.length > 2)
                                EXTERNAL_SD_PATH2 = TextWorker.getSubStringBeforeLastMark(sds[2].getAbsolutePath(),"/Android/");
                        }
                        else
                        {
                            String internal = sds[0].getAbsolutePath();
                            internal = TextWorker.getSubStringBeforeLastMark(internal,"/Android/");
                            int len = internal.length();
                            int num = Integer.valueOf(internal.substring(len - 1));

                            String ex1 = internal.substring(0, len-1) + (num+1);
                            File sd1 = new File(ex1);
                            if(sd1.exists())
                                EXTERNAL_SD_PATH1 = sd1.getAbsolutePath();

                            String ex2 = internal.substring(0, len-1) + (num+2);
                            File sd2 = new File(ex2);
                            if(sd2.exists())
                                EXTERNAL_SD_PATH2 = sd2.getAbsolutePath();
                        }
                    }

                    else
                    {
                        File sd = Environment.getExternalStorageDirectory();
                        String path = sd.getAbsolutePath();
                        if (sd.exists() && (path.contains("/mnt/") || path.contains("/storage") || path.contains("/sdcard")) && (!path.contains("emulate")))
                        {
                            EXTERNAL_SD_PATH1 = path;
                        }
                    }
                }
                catch (Throwable e)
                {}
            }

        }


        public static String getSubStringBeforeLastMark(String str,String mark)
    { 
        int l = str.lastIndexOf(mark);
        if(l == -1 || l == 0)
            return "";

        return str.substring(0, l);
    }
like image 141
Ali Bagheri Avatar answered Nov 05 '22 11:11

Ali Bagheri


In my projects using this code & i don't have any problem.

method of getExternalFilesDirs return array with 2 length.

Dirs[0] ==> Internal Sorage Dirs[1] ==> External Storage

 File[] Dirs = ContextCompat.getExternalFilesDirs(MyApp.GetContext(), null);
like image 22
Mohammad Hossein Gerami Avatar answered Nov 05 '22 11:11

Mohammad Hossein Gerami


For getExternalFilesDirs to return the path of the sdcard, 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

Look at the source of getExternalFilesDirs here: http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/app/ContextImpl.java#1039

The value is obtained from Environment.buildExternalStorageAppFilesDirs. Look at that source here: http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/os/Environment.java#206

The value is dependent on mExternalDirsForApp, which in turn is populated by reading the contents of SECONDARY_STORAGE variable: http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/os/Environment.java#136

As you can see, if the SECONDARY_STORAGE variable is not set, the sdcard path will not be returned. You can cross-check this by going to adb shell and looking at the output of echo $SECONDARY_STORAGE

like image 15
somesh Avatar answered Nov 05 '22 13:11

somesh