Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the internal and external sdcard path in android

Most of the new android devices have an internal sdcard and an external sdcard. I want to make a file explorer app but I can't find out how to get the path to use in my app because

File file = Environment.getExternalStorageDirectory();

just returns in most device /mnt/sdcard but there is another path for the other external sdcard like /storage1 or /storage2 . Any help appreciated.

like image 793
Mahmoud Jorban Avatar asked Nov 13 '12 12:11

Mahmoud Jorban


People also ask

How do I find my internal storage path?

With Google's Android 8.0 Oreo release, meanwhile, the file manager lives in Android's Downloads app. All you have to do is open that app and select the "Show internal storage" option in its menu to browse through your phone's full internal storage.

Where is the external storage folder on Android?

Environment. getExternalStorageDirectory() : return the primary external storage root directory. Context. getExternalFilesDir(String type) : return the absolute path of the directory on the primary external storage where the application can place its own files.


5 Answers

How to get the internal and external sdcard path in android

Methods to store in Internal Storage:

File getDir (String name, int mode)

File getFilesDir () 

Above methods are present in Context class

Methods to store in phone's internal memory:

File getExternalStorageDirectory ()

File getExternalFilesDir (String type)

File getExternalStoragePublicDirectory (String type)

In the beginning, everyone used Environment.getExternalStorageDirectory() , which pointed to the root of phone's internal memory. As a result, root directory was filled with random content.

Later, these two methods were added:

In Context class they added getExternalFilesDir(), pointing to an app-specific directory on phone's internal memory. This directory and its contents will be deleted when the app is uninstalled.

Environment.getExternalStoragePublicDirectory() for centralized places to store well-known file types, like photos and movies. This directory and its contents will NOT be deleted when the app is uninstalled.

Methods to store in Removable Storage i.e. micro SD card

Before API level 19, there was no official way to store in SD card. But many could do it using unofficial APIs.

Officially, one method was introduced in Context class in API level 19 (Android version 4.4 - Kitkat).

File[] getExternalFilesDirs (String type)

It returns absolute paths to application-specific directories on all shared/external storage devices where the application can place persistent files it owns. These files are internal to the application, and not typically visible to the user as media.

That means, it will return paths to both Micro SD card and Internal memory. Generally, second returned path would be storage path of micro SD card.

The Internal and External Storage terminology according to Google/official Android docs is quite different from what we think.

like image 55
AnV Avatar answered Sep 29 '22 11:09

AnV


Yes. Different manufacturer use different SDcard name like in Samsung Tab 3 its extsd, and other samsung devices use sdcard like this different manufacturer use different names.

I had the same requirement as you. so i have created a sample example for you from my project goto this link Android Directory chooser example which uses the androi-dirchooser library. This example detect the SDcard and list all the subfolders and it also detects if the device has morethan one SDcard.

Part of the code looks like this For full example goto the link Android Directory Chooser

/**
* Returns the path to internal storage ex:- /storage/emulated/0
 *
* @return
 */
private String getInternalDirectoryPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath();
 }

/**
 * Returns the SDcard storage path for samsung ex:- /storage/extSdCard
 *
 * @return
 */
    private String getSDcardDirectoryPath() {
    return System.getenv("SECONDARY_STORAGE");
}


 mSdcardLayout.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        String sdCardPath;
        /***
         * Null check because user may click on already selected buton before selecting the folder
         * And mSelectedDir may contain some wrong path like when user confirm dialog and swith back again
         */

        if (mSelectedDir != null && !mSelectedDir.getAbsolutePath().contains(System.getenv("SECONDARY_STORAGE"))) {
            mCurrentInternalPath = mSelectedDir.getAbsolutePath();
        } else {
            mCurrentInternalPath = getInternalDirectoryPath();
        }
        if (mCurrentSDcardPath != null) {
            sdCardPath = mCurrentSDcardPath;
        } else {
            sdCardPath = getSDcardDirectoryPath();
        }
        //When there is only one SDcard
        if (sdCardPath != null) {
            if (!sdCardPath.contains(":")) {
                updateButtonColor(STORAGE_EXTERNAL);
                File dir = new File(sdCardPath);
                changeDirectory(dir);
            } else if (sdCardPath.contains(":")) {
                //Multiple Sdcards show root folder and remove the Internal storage from that.
                updateButtonColor(STORAGE_EXTERNAL);
                File dir = new File("/storage");
                changeDirectory(dir);
            }
        } else {
            //In some unknown scenario at least we can list the root folder
            updateButtonColor(STORAGE_EXTERNAL);
            File dir = new File("/storage");
            changeDirectory(dir);
        }


    }
});
like image 25
Shivaraj Patil Avatar answered Oct 02 '22 11:10

Shivaraj Patil


For all Android versions,

Permissions:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />

Use requestLegacyExternalStorage for Android 10 (add to AndroidManifest > application tag):

android:requestLegacyExternalStorage="true"

Get internal directory path:

@Nullable
public static String getInternalStorageDirectoryPath(Context context) {
    String storageDirectoryPath;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        if(storageManager == null) {
            storageDirectoryPath = null; //you can replace it with the Environment.getExternalStorageDirectory().getAbsolutePath()
        } else {
            storageDirectoryPath = storageManager.getPrimaryStorageVolume().getDirectory().getAbsolutePath();
        }
    } else {
        storageDirectoryPath = Environment.getExternalStorageDirectory().getAbsolutePath();
    }

    return storageDirectoryPath;
}

Get external directories:

@NonNull
public static List<String> getExternalStorageDirectoryPaths(Context context) {
    List<String> externalPaths = new ArrayList<>();
    String internalStoragePath = getInternalStorageDirectoryPath(context);

    File[] allExternalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
    for(File filesDir : allExternalFilesDirs) {
        if(filesDir != null) {
            int nameSubPos = filesDir.getAbsolutePath().lastIndexOf("/Android/data");
            if(nameSubPos > 0) {
                String filesDirName = filesDir.getAbsolutePath().substring(0, nameSubPos);
                if(!filesDirName.equals(internalStoragePath)) {
                    externalPaths.add(filesDirName);
                }
            }
        }
    }

    return externalPaths;
}
like image 43
Atakan Yildirim Avatar answered Sep 28 '22 11:09

Atakan Yildirim


Since there is no direct meathod to get the paths the solution may be Scan the /system/etc/vold.fstab file and look for lines like this: dev_mount sdcard /mnt/sdcard 1 /devices/platform/s3c-sdhci.0/mmc_host/mmc0

When one is found, split it into its elements and then pull out the path to the that mount point and add it to the arraylist

emphasized textsome devices are missing the vold file entirely so we add a path here to make sure the list always includes the path to the first sdcard, whether real or emulated.

    sVold.add("/mnt/sdcard");

    try {
        Scanner scanner = new Scanner(new File("/system/etc/vold.fstab"));
        while (scanner.hasNext()) {
            String line = scanner.nextLine();
            if (line.startsWith("dev_mount")) {
                String[] lineElements = line.split(" ");
                String element = lineElements[2];

                if (element.contains(":"))
                    element = element.substring(0, element.indexOf(":"));

                if (element.contains("usb"))
                    continue;

                // don't add the default vold path
                // it's already in the list.
                if (!sVold.contains(element))
                    sVold.add(element);
            }
        }
    } catch (Exception e) {
        // swallow - don't care
        e.printStackTrace();
    }
}

Now that we have a cleaned list of mount paths, test each one to make sure it's a valid and available path. If it is not, remove it from the list.

private static void testAndCleanList() 
{
    for (int i = 0; i < sVold.size(); i++) {
        String voldPath = sVold.get(i);
        File path = new File(voldPath);
        if (!path.exists() || !path.isDirectory() || !path.canWrite())
            sVold.remove(i--);
    }
}
like image 44
Emel Elias Avatar answered Sep 30 '22 11:09

Emel Elias


I'm not sure how general an answer this but I tested it on a motorola XT830C with Android 4.4 and on a Nexus 7 android 6.0.1. and on a Samsung SM-T530NU Android 5.0.2. I used System.getenv("SECONDARY_STORAGE") and Environment.getExternalStorageDirectory().getAbsolutePath().
The Nexus which has no second SD card, System.getenv returns null and Envirnoment.getExterna... gives /storage/emulated/0.
The motorola device which has an external SD card gives /storage/sdcard1 for System.getenv("SECONDARY_STORAGE") and Envirnoment.getExterna... gives /storage/emulated/0.
The samsumg returns /storage/extSdCard for the external SD.
In my case I am making a subdirectory on the external location and am using

 appDirectory = (System.getenv("SECONDARY_STORAGE") == null)
       ? Environment.getExternalStorageDirectory().getAbsolutePath()
       : System.getenv("SECONDARY_STORAGE");

to find the sdcard. Making a subdirectory in this directory is working.
Of course I had to set permission in the manifest file to access the external memory.
I also have a Nook 8" color tablet. When I get a chance to test on them, I'll post if I have any problems with this approach.

like image 34
steven smith Avatar answered Oct 01 '22 11:10

steven smith