24

Here we are developing android app for android TV box. How can I get the list of mounted external storage like USB stick, SDCARD and SATA HDD.

Chirag
  • 56,621
  • 29
  • 151
  • 198
Android_Qmax
  • 241
  • 1
  • 2
  • 5
  • I now this topic is old but this may help. you should use thi method. System.getenv(); see project Environment3 to access all storage that are connected to your device. https://github.com/omidfaraji/Environment3 – Omid Faraji Mar 22 '16 at 18:28

6 Answers6

66

I use /proc/mounts file to get the list of available storage options

public class StorageUtils {

    private static final String TAG = "StorageUtils";

    public static class StorageInfo {

        public final String path;
        public final boolean readonly;
        public final boolean removable;     
        public final int number;

        StorageInfo(String path, boolean readonly, boolean removable, int number) {
            this.path = path;
            this.readonly = readonly;
            this.removable = removable;         
            this.number = number;
        }

        public String getDisplayName() {
            StringBuilder res = new StringBuilder();
            if (!removable) {
                res.append("Internal SD card");
            } else if (number > 1) {
                res.append("SD card " + number);
            } else {
                res.append("SD card");
            }
            if (readonly) {
                res.append(" (Read only)");
            }
            return res.toString();
        }
    }

    public static List<StorageInfo> getStorageList() {

        List<StorageInfo> list = new ArrayList<StorageInfo>();
        String def_path = Environment.getExternalStorageDirectory().getPath();
        boolean def_path_removable = Environment.isExternalStorageRemovable();
        String def_path_state = Environment.getExternalStorageState();
        boolean def_path_available = def_path_state.equals(Environment.MEDIA_MOUNTED)
                                    || def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
        boolean def_path_readonly = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);

        HashSet<String> paths = new HashSet<String>();
        int cur_removable_number = 1;

        if (def_path_available) {
            paths.add(def_path);
            list.add(0, new StorageInfo(def_path, def_path_readonly, def_path_removable, def_path_removable ? cur_removable_number++ : -1));
        }

        BufferedReader buf_reader = null;
        try {
            buf_reader = new BufferedReader(new FileReader("/proc/mounts"));
            String line;
            Log.d(TAG, "/proc/mounts");
            while ((line = buf_reader.readLine()) != null) {
                Log.d(TAG, line);
                if (line.contains("vfat") || line.contains("/mnt")) {
                    StringTokenizer tokens = new StringTokenizer(line, " ");
                    String unused = tokens.nextToken(); //device
                    String mount_point = tokens.nextToken(); //mount point
                    if (paths.contains(mount_point)) {
                        continue;
                    }
                    unused = tokens.nextToken(); //file system
                    List<String> flags = Arrays.asList(tokens.nextToken().split(",")); //flags
                    boolean readonly = flags.contains("ro");

                    if (line.contains("/dev/block/vold")) {
                        if (!line.contains("/mnt/secure")
                            && !line.contains("/mnt/asec")
                            && !line.contains("/mnt/obb")
                            && !line.contains("/dev/mapper")
                            && !line.contains("tmpfs")) {
                            paths.add(mount_point);
                            list.add(new StorageInfo(mount_point, readonly, true, cur_removable_number++));
                        }
                    }
                }
            }

        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (buf_reader != null) {
                try {
                    buf_reader.close();
                } catch (IOException ex) {}
            }
        }
        return list;
    }
}
Vitaliy Polchuk
  • 1,878
  • 19
  • 12
  • 6
    Actually, this is the best answer, it precisely does what the OP asked for. – WonderCsabo Dec 07 '13 at 20:26
  • 1
    This does not work for large SD Cards using the exfat filesystem please check : http://stackoverflow.com/questions/11281010/how-can-i-get-external-sd-card-path-for-android-4-0 – joecks Feb 17 '15 at 14:51
  • @WonderCsabo There is a much shorter way. See my answer. – android developer May 22 '15 at 16:03
  • Saved Me Bro.. Thank you very much @VitaliyPolchuk – Deep Dave Dec 05 '16 at 14:55
  • Thanks it works great, but just in case if the "proc/mounts" file doesn't exist i can get the file via this script(i use it as a fallback if this file is not existing), we get the same file like this answer http://stackoverflow.com/a/17085125/1348103 Just add one modification nowadays partitions starts with "/storage/" and "/dev/block/" can be "/dev/fuse" ok – Diljeet Feb 18 '17 at 22:11
  • This code is for the Internal and External SDCard but how can I find the USB directory path – Amit Thaper Oct 23 '18 at 08:07
  • Uhm, I stole this code... Is this ok that I use this code in a project? – BeChris 100 Jan 22 '21 at 17:48
13

To get all available external storage folders (including SD cards), you can use this :

File[] externalStorageFiles=ContextCompat.getExternalFilesDirs(this,null);

To go to the "root" of each external storage (the one that is the real mounting folder path), you can use this function I've made:

  /** Given any file/folder inside an sd card, this will return the path of the sd card */
  private static String getRootOfInnerSdCardFolder(File file)
    {
    if(file==null)
      return null;
    final long totalSpace=file.getTotalSpace();
    while(true)
      {
      final File parentFile=file.getParentFile();
      if(parentFile==null||parentFile.getTotalSpace()!=totalSpace)
        return file.getAbsolutePath();
      file=parentFile;
      }
    }
android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • This would require support of library 4 (to use ContextCompat), getTotalSpace() requires min API Level 9, does not work for API Level 8. – A.B. Sep 24 '16 at 05:57
  • @A.B. ok. using API 9 and above is quite fine nowadays. – android developer Sep 24 '16 at 15:45
  • This may also return private file system folders, that are not readable or writable by the app. – david.schreiber Nov 17 '16 at 20:34
  • @david.schreiber Can you give an example, and how to fix it? – android developer Nov 18 '16 at 00:15
  • As stated by the documentation, the `getExternalFilesDirs` returns app private paths on all external storages. This does not ensure that the root of this external mount is readable or writeable by the app too. – david.schreiber Nov 18 '16 at 08:58
  • @david.schreiber But is there any case you've tested that it didn't work? – android developer Nov 19 '16 at 22:57
  • @androiddeveloper yes, first device I tested failed and generated at least one invalid path (SM-T580 with plugged SD card). – david.schreiber Nov 21 '16 at 13:54
  • @david.schreiber That's too bad. So to which path does it go to? And, do you know of a better way? Also, just to check, have you added the permission of reading from external storage? – android developer Nov 22 '16 at 08:09
  • @androiddeveloper can't tell you the exact path, as I quickly moved on as soon as I noticed the issue leaving my comment here. Not only did I grant the correct permissions, also I checked validity of paths manually using adb. I'm now using a similar approach to what pedja proposed, accessing all possible location (app private and public) by constructing possible paths and testing them for read and write access. – david.schreiber Nov 22 '16 at 14:32
  • @david.schreiber Can you please post a new answer when you found something that seems to work on all Android versions/devices you've tested? – android developer Nov 23 '16 at 08:11
  • I would not go that far to call it a general solution, so I rather not post it. – david.schreiber Nov 23 '16 at 08:16
8

Environment.getExternalStorageState() returns path to internal SD mount point like "/mnt/sdcard"

No, Environment.getExternalStorageDirectory() refers to whatever the device manufacturer considered to be "external storage". On some devices, this is removable media, like an SD card. On some devices, this is a portion of on-device flash. Here, "external storage" means "the stuff accessible via USB Mass Storage mode when mounted on a host machine", at least for Android 1.x and 2.x.

But the question is about external SD. How to get a path like "/mnt/sdcard/external_sd" (it may differ from device to device)?

Android has no concept of "external SD", aside from external storage, as described above.

If a device manufacturer has elected to have external storage be on-board flash and also has an SD card, you will need to contact that manufacturer to determine whether or not you can use the SD card (not guaranteed) and what the rules are for using it, such as what path to use for it.

Try this out:

Manifest.xml:

<receiver android:name=".MyReceiver">
    <intent-filter>
         <action android:name="android.intent.action.ums_connected" />
     </intent-filter>
  </receiver>

Myreceiver:

public class MyReceiver extends BroadcastReceiver{
if (intent.getAction().equalsIgnoreCase(
        "android.intent.action.UMS_CONNECTED")) {...}
}
Brian Mains
  • 50,520
  • 35
  • 148
  • 257
Shishir Shetty
  • 2,021
  • 3
  • 20
  • 35
  • Hi Shishir... Thanks... But this device is having Sdcard slot and two usb host port. So the end user may use any usb mass storage. In this case i have to give options. Now Sdcard is working fine enough with "Environment.getExternalStorageDirectory()" – Android_Qmax Feb 18 '12 at 12:32
  • Manifest.xml : – Shishir Shetty Feb 18 '12 at 13:09
  • hi there, how can get path like /mnt/sda1 because am trying to get path of mounted flash from code, but Environment.getExternalStorageDirectory() is giving me /mnt/sdcard ? thanks – Darko Rodic Jul 24 '13 at 13:20
3

Another alternative.

First get all external files dirs

File[] externalStorageFiles=ContextCompat.getExternalFilesDirs(this,null);

Then call this function for each of the folders

private static String getRootOfExternalStorage(File file)
{
    if (file == null)
        return null;
    String path = file.getAbsolutePath();
    return path.replaceAll("/Android/data/" + getPackageName() + "/files", "");
}
pedja
  • 3,285
  • 5
  • 36
  • 48
1

You can use the getExternalStorageDirectory() to get the external storage directory. The documentation gives a good explanation of its usage http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory%28%29

For USB devices you probably have to look into the UsbManager class or more generally android.hardware.usb http://developer.android.com/reference/android/hardware/usb/UsbManager.html

shiraz
  • 1,208
  • 2
  • 12
  • 26
  • Thanks a lot shiraz By default it shows SDCARD alone, in some case it may be USB stick or SATA HDD. For this what i've to do – Android_Qmax Feb 18 '12 at 10:37
  • Thanks again for ur effort.... But it's api level 12(android 3.0). But i'm using 2.2 and 2.3 android. Is this possible with 2.2 or 2.3 android – Android_Qmax Feb 18 '12 at 12:21
  • 2
    For me, `getExternalStorageDirectory()` not good working, because return sdcard0 - this is internal memory. I have Samsung Galaxy Note 2. – Peter Sep 18 '13 at 21:12
-3

I now this topic is old but this may help. you should use thi method.

System.getenv();

see project Environment3 to access all storage that are connected to your device.

https://github.com/omidfaraji/Environment3