josephus
josephus

Reputation: 8304

Building a Utility to get the path to External Removable storage every time

Recently, I needed to be able to write some data strictly on a phone's external, removable storage (aka SDCard). For lower-end devices without "external" internal storage (you know what I mean), this isn't an issue as

Environment.getExternalStorageDirectory().getAbsolutePath(),

which returns

/mnt/sdcard

is also the path to the sdcard. However on higher-end phones with built-in flash storage (sgs 2 for example), /mnt/sdcard, which is returned from Environment.getExternalStorageDirectory().getAbsolutePath(), is just the path to the internal storage. The real path to the sdcard is `

/mnt/sdcard/external_sd`.

This doesn't stop here, however, as when I tried with an sgs2 that is upgraded to ICS, the path to the sd card is now

/mnt/emmc.

Now I'm trying to build a general Utility class called ExternalStorage which has a static method that returns the path to the sdcard root (as well as some other methods to get the total space, available space, space consumed by a particular dir, etc.) So far, what I have is this:

Updated version:

public static String getRemovableStoragePath() {

        File f = null;
//      Log.d(TAG, "Build.DEVICE: " + Build.DEVICE);
//      Log.d(TAG, "Build.MANUFACTURER: " + Build.MANUFACTURER);
//      Log.d(TAG, "Build.MODEL: " + Build.MODEL);

        if (Build.VERSION.RELEASE.startsWith("4")) {
            f = new File("/mnt/emmc");
        }
        if (Build.MODEL.toLowerCase().startsWith("mele")) {
            return "/mnt/extern_sd0";
        }
        if (Build.DEVICE.equals("nuclear-zoop") || Build.DEVICE.equals("nuclear-f900")) {
            f = new File("/mnt/extsd");
        }

        String path = Environment.getExternalStorageDirectory().getAbsolutePath();
        String extendedPath = "";
        if (Build.DEVICE.toLowerCase().contains("samsung") || Build.MANUFACTURER.toLowerCase().contains("samsung")) {
            extendedPath = "/external_sd/";
            try {
                f = new File(path + extendedPath);
                if (f.exists() && f.isDirectory()) {
                    return f.getAbsolutePath();
                } else if (Build.MODEL.toLowerCase().contains("gt-i9300")) {
                    extendedPath = "/mnt/extSdCard/";
                    try {
                        f = new File(extendedPath);
                        if (f.exists() && f.isDirectory()) {
                            return f.getAbsolutePath();
                        }
                    } catch (Exception e) {
                        // continue execution
                    }
                } else {
                    extendedPath = "/sd";
                }
            } catch (Exception e) {
                // contine execution
            }
        } else if (Build.DEVICE.toLowerCase().contains("e0") || Build.MANUFACTURER.toLowerCase().contains("LGE")) {
            extendedPath = "/_ExternalSD/";
        } else if (Build.MANUFACTURER.toLowerCase().contains("motorola") || Build.DEVICE.toLowerCase().contains("olympus")) {
            f = new File("/mnt/sdcard-ext");
        }
        try {
            if (!extendedPath.equals("")) {
                f = new File(path + extendedPath);
            }
            if (f.exists() && f.isDirectory()) {
                //              Log.d(TAG, "path: " + f.getAbsolutePath());
                return f.getAbsolutePath();
            } else {
            }
        } catch (Exception e) {
            //          e.printStackTrace();
            // f is probably null. no need to print stacktrace.
            return path;
        }

        return path;
//      return Environment.getExternalStorageDirectory().getAbsolutePath();
    }

Has anyone done this already? I know I'm missing many mfg-specific paths, so I need help in completing this utility to support as many android phones as possible.

Upvotes: 4

Views: 3694

Answers (1)

mjp66
mjp66

Reputation: 4213

I'm not sure how reliable this would be but since the removable SD card contains the LOST.DIR folder at its root and gets recreated upon boot (in cases where the user might delete it)...

    File root = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
    for (File sub : root.listFiles()) {
        if (new File(sub + "/lost.dir").exists()) {
            // 'sub' is probably the removable SD
            break;
        }
    }    

If 'sub' is found with a LOST.DIR folder , might want to write its value to sharedPrefs so that this lookup is only performed one time (if there is no value stored) and then just fetched from prefs, OR so that the app knows this path even in case the user deleted LOST.DIR and it currently doesn't exist anywhere.

Upvotes: 2

Related Questions