Find location of a removable SD card

前端 未结 22 2611
南方客
南方客 2020-11-21 11:32

Is there an universal way to find the location of an external SD card?

Please, do not be confused with External Storage.

Environment.getExternalStorage

相关标签:
22条回答
  • 2020-11-21 11:47

    Just simply use this:

    String primary_sd = System.getenv("EXTERNAL_STORAGE");
    if(primary_sd != null)
        Log.i("EXTERNAL_STORAGE", primary_sd);
    String secondary_sd = System.getenv("SECONDARY_STORAGE");
    if(secondary_sd != null)
        Log.i("SECONDARY_STORAGE", secondary_sd)
    
    0 讨论(0)
  • 2020-11-21 11:47

    I don't know why but I need to call .createNewFile() on a File created in the public storage directories before using it. In the framework the comments for that method say it isn't useful. Here's a sample...

    
     String myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS) + File.separator + "My Directory";
                final File myDir = new File(myPath);
                try {
                    myDir.mkdirs();
                } catch (Exception ex) {
                    Toast.makeText(this, "error: " + ex.getMessage(), Toast.LENGTH_LONG).show();
                }

            String fname = "whatever";
            File newFile = new File(myDir, fname);
    
            Log.i(TAG, "File exists --> " + newFile.exists()) //will be false  
        try {
                if (newFile.createNewFile()) {
    
                     //continue 
    
                  } else {
    
                    Log.e(TAG, "error creating file");
    
                }
    
            } catch (Exception e) {
                Log.e(TAG, e.toString());
            }
    

    0 讨论(0)
  • 2020-11-21 11:48

    I had an application that used a ListPreference where the user was required to select the location of where they wanted to save something.

    In that app, I scanned /proc/mounts and /system/etc/vold.fstab for sdcard mount points. I stored the mount points from each file into two separate ArrayLists.

    Then, I compared one list with the other and discarded items that were not in both lists. That gave me a list of root paths to each sdcard.

    From there, I tested the paths with File.exists(), File.isDirectory(), and File.canWrite(). If any of those tests were false, I discarded that path from the list.

    Whatever was left in the list, I converted to a String[] array so it could be used by the ListPreference values attribute.

    You can view the code here: http://sapienmobile.com/?p=204

    0 讨论(0)
  • 2020-11-21 11:48

    it been so late but finally i got something i have tested most of devices( by manufacturer and android versions) its working on Android 2.2+. if you find it is not working, comment it with your device name. i will fix it. if anyone interested i will explain how it works.

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FilenameFilter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    import android.util.Log;
    
    
    /**
     * @author ajeet
     *05-Dec-2014  2014
     *
     */
    public class StorageUtil {
    
        public boolean isRemovebleSDCardMounted() {
            File file = new File("/sys/class/block/");
            File[] files = file.listFiles(new MmcblkFilter("mmcblk\\d$"));
            boolean flag = false;
            for (File mmcfile : files) {
                File scrfile = new File(mmcfile, "device/scr");
                if (scrfile.exists()) {
                    flag = true;
                    break;
                }
            }
            return flag;
        }
    
        public String getRemovebleSDCardPath() throws IOException {
            String sdpath = null;
            File file = new File("/sys/class/block/");
            File[] files = file.listFiles(new MmcblkFilter("mmcblk\\d$"));
            String sdcardDevfile = null;
            for (File mmcfile : files) {
                Log.d("SDCARD", mmcfile.getAbsolutePath());
                File scrfile = new File(mmcfile, "device/scr");
                if (scrfile.exists()) {
                    sdcardDevfile = mmcfile.getName();
                    Log.d("SDCARD", mmcfile.getName());
                    break;
                }
            }
            if (sdcardDevfile == null) {
                return null;
            }
            FileInputStream is;
            BufferedReader reader;
    
            files = file.listFiles(new MmcblkFilter(sdcardDevfile + "p\\d+"));
            String deviceName = null;
            if (files.length > 0) {
                Log.d("SDCARD", files[0].getAbsolutePath());
                File devfile = new File(files[0], "dev");
                if (devfile.exists()) {
                    FileInputStream fis = new FileInputStream(devfile);
                    reader = new BufferedReader(new InputStreamReader(fis));
                    String line = reader.readLine();
                    deviceName = line;
                }
                Log.d("SDCARD", "" + deviceName);
                if (deviceName == null) {
                    return null;
                }
                Log.d("SDCARD", deviceName);
    
                final File mountFile = new File("/proc/self/mountinfo");
    
                if (mountFile.exists()) {
                    is = new FileInputStream(mountFile);
                    reader = new BufferedReader(new InputStreamReader(is));
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        // Log.d("SDCARD", line);
                        // line = reader.readLine();
                        // Log.d("SDCARD", line);
                        String[] mPonts = line.split("\\s+");
                        if (mPonts.length > 6) {
                            if (mPonts[2].trim().equalsIgnoreCase(deviceName)) {
                                if (mPonts[4].contains(".android_secure")
                                        || mPonts[4].contains("asec")) {
                                    continue;
                                }
                                sdpath = mPonts[4];
                                Log.d("SDCARD", mPonts[4]);
    
                            }
                        }
    
                    }
                }
    
            }
    
            return sdpath;
        }
    
        static class MmcblkFilter implements FilenameFilter {
            private String pattern;
    
            public MmcblkFilter(String pattern) {
                this.pattern = pattern;
    
            }
    
            @Override
            public boolean accept(File dir, String filename) {
                if (filename.matches(pattern)) {
                    return true;
                }
                return false;
            }
    
        }
    
    }
    
    0 讨论(0)
  • 2020-11-21 11:49

    In order to retrieve all the External Storages (whether they are SD cards or internal non-removable storages), you can use the following code:

    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");
                }
            }
        }
    }
    

    Alternatively, you might use System.getenv("EXTERNAL_STORAGE") to retrieve the primary External Storage directory (e.g. "/storage/sdcard0") and System.getenv("SECONDARY_STORAGE") to retieve the list of all the secondary directories (e.g. "/storage/extSdCard:/storage/UsbDriveA:/storage/UsbDriveB"). Remember that, also in this case, you might want to filter the list of secondary directories in order to exclude the USB drives.

    In any case, please note that using hard-coded paths is always a bad approach (expecially when every manufacturer may change it as pleased).

    0 讨论(0)
  • 2020-11-21 11:50

    This solution handles the fact that System.getenv("SECONDARY_STORAGE") is of no use with Marshmallow.

    Tested and working on:

    • Samsung Galaxy Tab 2 (Android 4.1.1 - Stock)
    • Samsung Galaxy Note 8.0 (Android 4.2.2 - Stock)
    • Samsung Galaxy S4 (Android 4.4 - Stock)
    • Samsung Galaxy S4 (Android 5.1.1 - Cyanogenmod)
    • Samsung Galaxy Tab A (Android 6.0.1 - Stock)

      /**
       * Returns all available external SD-Card roots in the system.
       *
       * @return paths to all available external SD-Card roots in the system.
       */
      public static String[] getStorageDirectories() {
          String [] storageDirectories;
          String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
      
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
              List<String> results = new ArrayList<String>();
              File[] externalDirs = applicationContext.getExternalFilesDirs(null);
              for (File file : externalDirs) {
                  String path = file.getPath().split("/Android")[0];
                  if((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Environment.isExternalStorageRemovable(file))
                          || rawSecondaryStoragesStr != null && rawSecondaryStoragesStr.contains(path)){
                      results.add(path);
                  }
              }
              storageDirectories = results.toArray(new String[0]);
          }else{
              final Set<String> rv = new HashSet<String>();
      
              if (!TextUtils.isEmpty(rawSecondaryStoragesStr)) {
                  final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
                  Collections.addAll(rv, rawSecondaryStorages);
              }
              storageDirectories = rv.toArray(new String[rv.size()]);
          }
          return storageDirectories;
      }
      
    0 讨论(0)
提交回复
热议问题