简体   繁体   中英

How to get sdcard(Secondary) storage path in android?

I'm developing a File Manager app. I want show to the user the internal storage and the sdcard storage if it exists. For internal storage I use Environment.getExternalStorageDirectory().getPath() . How can I get the SD storage?

not sure this solution fits a File Manager but after many years trying to get the right code, this is my most recent one:

/**
 * Returns all available SD-Cards in the system (include emulated)
 *
 * Warning: Hack! Based on Android source code of version 4.3 (API 18)
 * Because there is no standard way to get it.
 *
 * @return paths to all available SD-Cards in the system (include emulated)
 */
public static String[] getStorageDirectories(Context pContext)
{
    // Final set of paths
    final Set<String> rv = new HashSet<>();

    //Get primary & secondary external device storage (internal storage & micro SDCARD slot...)
    File[]  listExternalDirs = ContextCompat.getExternalFilesDirs(pContext, null);
    for(int i=0;i<listExternalDirs.length;i++){
        if(listExternalDirs[i] != null) {
            String path = listExternalDirs[i].getAbsolutePath();
            int indexMountRoot = path.indexOf("/Android/data/");
            if(indexMountRoot >= 0 && indexMountRoot <= path.length()){
                //Get the root path for the external directory
                rv.add(path.substring(0, indexMountRoot));
            }
        }
    }
    return rv.toArray(new String[rv.size()]);
}

If you worked on only Android 4.0+.These answers here will help you:

how-can-i-get-external-sd-card-path-for-android-4-0

Some code example from the answers:

public static HashSet<String> getExternalMounts() {
    final HashSet<String> out = new HashSet<String>();
    String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
    String s = "";
    try {
        final Process process = new ProcessBuilder().command("mount")
                .redirectErrorStream(true).start();
        process.waitFor();
        final InputStream is = process.getInputStream();
        final byte[] buffer = new byte[1024];
        while (is.read(buffer) != -1) {
            s = s + new String(buffer);
        }
        is.close();
    } catch (final Exception e) {
        e.printStackTrace();
    }

    // parse output
    final String[] lines = s.split("\n");
    for (String line : lines) {
        if (!line.toLowerCase(Locale.US).contains("asec")) {
            if (line.matches(reg)) {
                String[] parts = line.split(" ");
                for (String part : parts) {
                    if (part.startsWith("/"))
                        if (!part.toLowerCase(Locale.US).contains("vold"))
                            out.add(part);
                }
            }
        }
    }
    return out;
}

Another answer here.

private static final Pattern DIR_SEPORATOR = Pattern.compile("/");

/**
 * Raturns all available SD-Cards in the system (include emulated)
 *
 * Warning: Hack! Based on Android source code of version 4.3 (API 18)
 * Because there is no standart way to get it.
 * TODO: Test on future Android versions 4.4+
 *
 * @return paths to all available SD-Cards in the system (include emulated)
 */
public static String[] getStorageDirectories()
{
    // Final set of paths
    final Set<String> rv = new HashSet<String>();
    // Primary physical SD-CARD (not emulated)
    final String rawExternalStorage = System.getenv("EXTERNAL_STORAGE");
    // All Secondary SD-CARDs (all exclude primary) separated by ":"
    final String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
    // Primary emulated SD-CARD
    final String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET");
    if(TextUtils.isEmpty(rawEmulatedStorageTarget))
    {
        // Device has physical external storage; use plain paths.
        if(TextUtils.isEmpty(rawExternalStorage))
        {
            // EXTERNAL_STORAGE undefined; falling back to default.
            rv.add("/storage/sdcard0");
        }
        else
        {
            rv.add(rawExternalStorage);
        }
    }
    else
    {
        // Device has emulated storage; external storage paths should have
        // userId burned into them.
        final String rawUserId;
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
        {
            rawUserId = "";
        }
        else
        {
            final String path = Environment.getExternalStorageDirectory().getAbsolutePath();
            final String[] folders = DIR_SEPORATOR.split(path);
            final String lastFolder = folders[folders.length - 1];
            boolean isDigit = false;
            try
            {
                Integer.valueOf(lastFolder);
                isDigit = true;
            }
            catch(NumberFormatException ignored)
            {
            }
            rawUserId = isDigit ? lastFolder : "";
        }
        // /storage/emulated/0[1,2,...]
        if(TextUtils.isEmpty(rawUserId))
        {
            rv.add(rawEmulatedStorageTarget);
        }
        else
        {
            rv.add(rawEmulatedStorageTarget + File.separator + rawUserId);
        }
    }
    // Add all secondary storages
    if(!TextUtils.isEmpty(rawSecondaryStoragesStr))
    {
        // All Secondary SD-CARDs splited into array
        final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
        Collections.addAll(rv, rawSecondaryStorages);
    }
    return rv.toArray(new String[rv.size()]);
}

The third answer is:

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.d(TAG, "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.d(TAG, "External Storage: " + file.getAbsolutePath() + "\n");
            }
        }
    }
}

Similar to code above but without harcoded "/Android/data"

public List<File> getAllStorageLocations() {
    List<File> storageLocations = new ArrayList<>();
    File storageDir = Environment.getExternalStorageDirectory();
    String storagePath = storageDir.getAbsolutePath();
    File[] extFileDirs = getContext().getExternalFilesDirs(null);
    String suffixToStrip = null;
    for (File nextFile : extFileDirs) {
        String nextPath = nextFile.getAbsolutePath();
        if (nextPath.startsWith(storagePath)) {
            suffixToStrip = nextPath.substring(storagePath.length());
            break;
        }
    }
    if (suffixToStrip != null) {
        for (File nextFile : extFileDirs) {
            String nextPath = nextFile.getAbsolutePath();
            int stripIndex = nextPath.lastIndexOf(suffixToStrip);
            if (stripIndex > -1) {
                File path = new File(nextPath.substring(0, stripIndex));
                storageLocations.add(path);
            }
        }
    }
    if (storageLocations.size() == 0) {
        storageLocations.add(storageDir);
    }
    return storageLocations;
}

Try this, iterate from root folder.

    File rootFolder = new File("/");
    boolean isSdcardRemovable = false;
    String path = null;

    loop:
    for(int i=0; i<rootFolder.listFiles().length; i++) {

        if(rootFolder.listFiles()[i].listFiles() != null && 
            !rootFolder.listFiles()[i].toString().contains("system") &&
            !rootFolder.listFiles()[i].toString().contains("etc") && 
            !rootFolder.listFiles()[i].toString().contains("dev") ) {

            File dataDir = new File(Environment.getDataDirectory().getAbsolutePath());

            long dataDirSize = dataDir.getFreeSpace()/(1000*1000);
            long folderSize = rootFolder.listFiles()[i].getFreeSpace()/(1000*1000);

            if(dataDirSize == folderSize || (dataDirSize > folderSize && 
                    folderSize > (dataDirSize-80))) {
                System.err.println("INTERNAL1 "+rootFolder.listFiles()[i]);
                System.err.println(dataDirSize);
                System.err.println(folderSize);
            }
            else {

                File rootSubFolder1 = new File(rootFolder.listFiles()[i].getAbsolutePath());

                if(rootSubFolder1.listFiles() != null) {

                    for(int j=0; j<rootSubFolder1.listFiles().length; j++) {

                        if(rootSubFolder1.listFiles()[j].getTotalSpace() != 0 && 
                            rootSubFolder1.listFiles()[j].getFreeSpace() != 0 &&
                            rootSubFolder1.listFiles()[j].listFiles() != null) {

                            Log.i(TAG, "" + rootSubFolder1.listFiles()[j]);

                            if(rootSubFolder1.listFiles()[j].toString().contains("sdcard") ||
                                rootSubFolder1.listFiles()[j].toString().contains("storage") || 
                                rootSubFolder1.listFiles()[j].toString().contains("mnt")) {

                                folderSize = rootSubFolder1.listFiles()[j].getFreeSpace()/(1000*1000);

                                if(dataDirSize == folderSize || (dataDirSize > folderSize && 
                                    folderSize > (dataDirSize-80))) {
                                    System.err.println("INTERNAL2 " + rootSubFolder1.listFiles()[j]);
                                    System.err.println(dataDirSize);
                                    System.err.println(folderSize);
                                }
                                else {
                                    int pos = rootSubFolder1.listFiles()[j].getAbsolutePath().lastIndexOf('/');
                                    String str = rootSubFolder1.listFiles()[j].getAbsolutePath().substring(pos+1);

                                    if(str.matches("(sd|ext|3039|m_external_sd).*")) {

                                        isSdcardRemovable = true;
                                        System.err.println("EXTERNAL "+rootSubFolder1.listFiles()[j]);
                                        System.err.println(dataDirSize);
                                        System.err.println(folderSize);
                                        path = rootSubFolder1.listFiles()[j].getAbsolutePath()+"/";
                                        break loop;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    if(isSdcardRemovable) {
        if(path != null) {
            getMemoryDetails(path);
            finish();
        }
        else {
            saveResult("fail", "External memory not found.");
            Log.e(TAG, "External memory not found.");
            finish();
        }
    } else {
        saveResult("fail", "External memory not available.");
        Log.e(TAG, "External memory not available.");
        finish();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM