如何获得Android 4.0以上的外部SD卡path?

三星Galaxy S3有一个extrenal SD卡插槽,安装到/mnt/extSdCard

我的问题是:如何通过像Environment.getExternalStorageDirectory()这样的path得到这个path? 这将返回mnt/sdcard ,我无法find外部SD卡的API。 (或某些平板电脑上的可移动USB存储)

谢谢!

我在这里find的解决scheme有一个变种

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

原来的方法进行了testing和工作

  • 华为X3(现货)
  • Galaxy S2(现货)
  • Galaxy S3(股票)

我不确定当他们被testing时,这些版本的Android版本。

我已经testing了我的修改版本

  • 摩托Xoom 4.1.2(股票)
  • Galaxy Nexus(cyanogenmod 10)使用otg电缆
  • macros达不可思议(cyanogenmod 7.2)这返回内部和外部。 这个设备有点古怪,因为它的内部很大程度上没有使用,因为getExternalStorage()返回的是sdcard的path。

以及一些使用SD卡作为主要存储的单一存储设备

  • HTC G1(cyanogenmod 6.1)
  • HTC G1(现货)
  • HTC Vision / G2(现货)

除了令人难以置信的所有这些设备只返回他​​们的可移动存储。 可能有一些额外的检查,我应该做的,但这至less比我迄今为止find的任何解决scheme好一点。

我发现了更可靠的方法来获得系统中所有SD-CARD的path。 这适用于所有Android版本,并返回到所有存储的path(包括仿真)。

在我的所有设备上正常工作。

PS:基于Environment类的源代码。

 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()]); } 

我想使用外部SD卡你需要使用这个:

 new File("/mnt/external_sd/") 

要么

 new File("/mnt/extSdCard/") 

在你的情况下…

取代Environment.getExternalStorageDirectory()

为我工作。 你应该先检查目录mnt中的内容,然后从那里开始工作。


你应该使用某种select方法来select使用哪个SD卡:

 File storageDir = new File("/mnt/"); if(storageDir.isDirectory()){ String[] dirList = storageDir.list(); //TODO some type of selecton method? } 

为了检索所有外部存储 (无论是SD卡还是内部不可移动存储 ),可以使用以下代码:

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

或者,您可以使用System.getenv(“EXTERNAL_STORAGE”)来检索主外部存储目录(例如“/ storage / sdcard0” )和System.getenv(“SECONDARY_STORAGE”)以检索所有辅助目录(例如“ / storage / extSdCard:/ storage / UsbDriveA:/ storage / UsbDriveB“ )。 请记住,在这种情况下,也可能需要筛选辅助目录列表以排除USB驱动器。

无论如何,请注意,使用硬编码path总是一个不好的方法(尤其是当每个制造商可能会改变它的喜悦)。

好消息! 在KitKat中,现在有一个公共API用于与这些辅助共享存储设备进行交互。

新的Context.getExternalFilesDirs()Context.getExternalCacheDirs()方法可以返回多个path,包括主设备和辅助设备。 然后,您可以遍历它们并检查Environment.getStorageState()File.getFreeSpace()以确定存储文件的最佳位置。 这些方法也可以在support-v4库中的ContextCompat上使用。

另请注意,如果您只想使用Context返回的目录,则不再需要READ_WRITE_EXTERNAL_STORAGE权限。 outlook未来,您将始终拥有对这些目录的读/写访问权限,而无需额外的权限。

应用程序也可以继续在旧设备上工作,通过终止其权限请求,如下所示:

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" /> 

我正在使用Dmitriy Lozenko的解决scheme,直到我检查了一个华硕Zenfone2棉花糖6.0.1和解决scheme不工作。 获得EMULATED_STORAGE_TARGET时 ,解决scheme失败,特别是microSDpath/存储/ F99C-10F4 / 。 我编辑了代码,从context.getExternalFilesDirs(null)获取仿真应用程序path的仿真根path,并添加了更多的物理path。

这是我改进的完整解决scheme

 import android.content.Context; import android.os.Build; import android.os.Environment; import android.text.TextUtils; import java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; public class StorageUtil { private static final Pattern DIR_SEPARATOR = Pattern.compile("/"); /** * Returns all available SD-Cards in the system (include emulated) * <p/> * Warning: Hack! Based on Android source code of version 4.3 (API 18) * Because there is no standard way to get it. * Edited by hendrawd * * @return paths to all available SD-Cards in the system (include emulated) */ public static String[] getStorageDirectories(Context context) { // Final set of paths final Set<String> rv = new HashSet<>(); // 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)) { //fix of empty raw emulated storage on marshmallow if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { File[] files = context.getExternalFilesDirs(null); for (File file : files) { if (file == null) continue; String applicationSpecificAbsolutePath = file.getAbsolutePath(); String emulatedRootPath = applicationSpecificAbsolutePath.substring(0, applicationSpecificAbsolutePath.indexOf("Android/data")); rv.add(emulatedRootPath); } } else { // Device has physical external storage; use plain paths. if (TextUtils.isEmpty(rawExternalStorage)) { // EXTERNAL_STORAGE undefined; falling back to default. rv.addAll(Arrays.asList(getPhysicalPaths())); } 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_SEPARATOR.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()]); } /** * @return physicalPaths based on phone model */ private static String[] getPhysicalPaths() { return new String[]{ "/storage/sdcard0", "/storage/sdcard1", //Motorola Xoom "/storage/extsdcard", //Samsung SGS3 "/storage/sdcard0/external_sdcard", //User request "/mnt/extsdcard", "/mnt/sdcard/external_sd", //Samsung galaxy family "/mnt/external_sd", "/mnt/media_rw/sdcard1", //4.4.2 on CyanogenMod S3 "/removable/microsd", //Asus transformer prime "/mnt/emmc", "/storage/external_SD", //LG "/storage/ext_sd", //HTC One Max "/storage/removable/sdcard1", //Sony Xperia Z1 "/data/sdext", "/data/sdext2", "/data/sdext3", "/data/sdext4", "/sdcard1", //Sony Xperia Z "/sdcard2", //HTC One M8s "/storage/microsd" //ASUS ZenFone 2 }; } } 

如果您有任何问题或build议,请告诉我

我做了以下访问所有的外部SD卡。

附:

 File primaryExtSd=Environment.getExternalStorageDirectory(); 

你得到的主要外部SD的path然后:

 File parentDir=new File(primaryExtSd.getParent()); 

您将获得主外部存储的父目录,并且它也是所有外部sd的父目录。 现在,你可以列出所有的存储并select你想要的。

希望它是有用的。

以下是我如何获得SD卡path列表(不包括主要外部存储):

  /** * returns a list of all available sd cards paths, or null if not found. * * @param includePrimaryExternalStorage set to true if you wish to also include the path of the primary external storage */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static List<String> getSdCardPaths(final Context context,final boolean includePrimaryExternalStorage) { final File[] externalCacheDirs=ContextCompat.getExternalCacheDirs(context); if(externalCacheDirs==null||externalCacheDirs.length==0) return null; if(externalCacheDirs.length==1) { if(externalCacheDirs[0]==null) return null; final String storageState=EnvironmentCompat.getStorageState(externalCacheDirs[0]); if(!Environment.MEDIA_MOUNTED.equals(storageState)) return null; if(!includePrimaryExternalStorage&&VERSION.SDK_INT>=VERSION_CODES.HONEYCOMB&&Environment.isExternalStorageEmulated()) return null; } final List<String> result=new ArrayList<>(); if(includePrimaryExternalStorage||externalCacheDirs.length==1) result.add(getRootOfInnerSdCardFolder(externalCacheDirs[0])); for(int i=1;i<externalCacheDirs.length;++i) { final File file=externalCacheDirs[i]; if(file==null) continue; final String storageState=EnvironmentCompat.getStorageState(file); if(Environment.MEDIA_MOUNTED.equals(storageState)) result.add(getRootOfInnerSdCardFolder(externalCacheDirs[i])); } if(result.isEmpty()) return null; return result; } /** 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; } } 

感谢你们提供的线索,特别是@SmartLemon,我得到了解决scheme。 如果有人需要它,我把我的最终解决scheme放在这里(find第一个列出的外部SD卡):

 public File getExternalSDCardDirectory() { File innerDir = Environment.getExternalStorageDirectory(); File rootDir = innerDir.getParentFile(); File firstExtSdCard = innerDir ; File[] files = rootDir.listFiles(); for (File file : files) { if (file.compareTo(innerDir) != 0) { firstExtSdCard = file; break; } } //Log.i("2", firstExtSdCard.getAbsolutePath().toString()); return firstExtSdCard; } 

如果没有外部SD卡,则返回机载存储。 我将使用它,如果SD卡不存在,您可能需要更改它。

参考我的代码,希望对你有所帮助:

  Runtime runtime = Runtime.getRuntime(); Process proc = runtime.exec("mount"); InputStream is = proc.getInputStream(); InputStreamReader isr = new InputStreamReader(is); String line; String mount = new String(); BufferedReader br = new BufferedReader(isr); while ((line = br.readLine()) != null) { if (line.contains("secure")) continue; if (line.contains("asec")) continue; if (line.contains("fat")) {//TF card String columns[] = line.split(" "); if (columns != null && columns.length > 1) { mount = mount.concat("*" + columns[1] + "\n"); } } else if (line.contains("fuse")) {//internal storage String columns[] = line.split(" "); if (columns != null && columns.length > 1) { mount = mount.concat(columns[1] + "\n"); } } } txtView.setText(mount); 

实际上,在某些设备中,外部SD卡默认名称显示为extSdCard ,而其他设备则显示为sdcard1

这段代码有助于找出确切的path,并有助于检索外部设备的path。

 String sdpath,sd1path,usbdiskpath,sd0path; if(new File("/storage/extSdCard/").exists()) { sdpath="/storage/extSdCard/"; Log.i("Sd Cardext Path",sdpath); } if(new File("/storage/sdcard1/").exists()) { sd1path="/storage/sdcard1/"; Log.i("Sd Card1 Path",sd1path); } if(new File("/storage/usbcard1/").exists()) { usbdiskpath="/storage/usbcard1/"; Log.i("USB Path",usbdiskpath); } if(new File("/storage/sdcard0/").exists()) { sd0path="/storage/sdcard0/"; Log.i("Sd Card0 Path",sd0path); } 

是。 不同的厂商使用不同的SDcard名称如Samsung Tab 3其extsd,而其他三星设备使用这种不同厂商的sdcard使用不同的名称。

我有和你一样的要求。 所以我从我的项目中为您创build了一个示例示例转到此链接使用androi-dirchooser库的Android目录select器示例。 此示例检测SD卡并列出所有子文件夹,并检测设备是否有多个SD卡。

部分代码看起来像这样完整的例子goto链接Android目录select器

 /** * 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); } } }); 

在某些设备上(例如三星Galaxy sII),内置存储卡可以在vfat中使用。 在这种情况下,使用参考代码,我们获得path内部存储卡(/ mnt / sdcad),但没有外部卡。 代码参考下面解决这个问题。

 static String getExternalStorage(){ String exts = Environment.getExternalStorageDirectory().getPath(); try { FileReader fr = new FileReader(new File("/proc/mounts")); BufferedReader br = new BufferedReader(fr); String sdCard=null; String line; while((line = br.readLine())!=null){ if(line.contains("secure") || line.contains("asec")) continue; if(line.contains("fat")){ String[] pars = line.split("\\s"); if(pars.length<2) continue; if(pars[1].equals(exts)) continue; sdCard =pars[1]; break; } } fr.close(); br.close(); return sdCard; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } 
  File[] files = null; File file = new File("/storage");// /storage/emulated if (file.exists()) { files = file.listFiles(); } if (null != files) for (int j = 0; j < files.length; j++) { Log.e(TAG, "" + files[j]); Log.e(TAG, "//--//--// " + files[j].exists()); if (files[j].toString().replaceAll("_", "") .toLowerCase().contains("extsdcard")) { external_path = files[j].toString(); break; } else if (files[j].toString().replaceAll("_", "") .toLowerCase() .contains("sdcard".concat(Integer.toString(j)))) { // external_path = files[j].toString(); } Log.e(TAG, "--///--///-- " + external_path); } 

这个解决scheme(从这个问题的其他答案汇编而来)处理事实(如@ono所述) System.getenv("SECONDARY_STORAGE")对棉花糖没有用处。

经过testing和工作:

  • Samsung Galaxy Tab 2(Android 4.1.1 – 股票)
  • 三星Galaxy Note 8.0(Android 4.2.2 – 股票)
  • 三星Galaxy S4(Android 4.4 – 股票)
  • 三星Galaxy S4(Android 5.1.1 – Cyanogenmod)
  • 三星Galaxy Tab A(Android 6.0.1 – 股票)

     /** * 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; } 

我相信这个代码肯定会解决你的问题…这对我来说工作正常… \

 try { File mountFile = new File("/proc/mounts"); usbFoundCount=0; sdcardFoundCount=0; if(mountFile.exists()) { Scanner usbscanner = new Scanner(mountFile); while (usbscanner.hasNext()) { String line = usbscanner.nextLine(); if (line.startsWith("/dev/fuse /storage/usbcard1")) { usbFoundCount=1; Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/usbcard1" ); } } } if(mountFile.exists()){ Scanner sdcardscanner = new Scanner(mountFile); while (sdcardscanner.hasNext()) { String line = sdcardscanner.nextLine(); if (line.startsWith("/dev/fuse /storage/sdcard1")) { sdcardFoundCount=1; Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/sdcard1" ); } } } if(usbFoundCount==1) { Toast.makeText(context,"USB Connected and properly mounted", 7000).show(); Log.i("-----USB--------","USB Connected and properly mounted" ); } else { Toast.makeText(context,"USB not found!!!!", 7000).show(); Log.i("-----USB--------","USB not found!!!!" ); } if(sdcardFoundCount==1) { Toast.makeText(context,"SDCard Connected and properly mounted", 7000).show(); Log.i("-----SDCard--------","SDCard Connected and properly mounted" ); } else { Toast.makeText(context,"SDCard not found!!!!", 7000).show(); Log.i("-----SDCard--------","SDCard not found!!!!" ); } }catch (Exception e) { e.printStackTrace(); } 

这不是真的。 / mnt / sdcard / external_sd即使没有安装SD卡也可以存在。 当您尝试写入/ mnt / sdcard / external_sd未挂载时,您的应用程序将崩溃。

你需要检查SD卡是否安装在第一次使用:

 boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); 

要访问我的SD卡上的文件,在我的HTC One X(Android)上,我使用这个path:

文件:///storage/sdcard0/folder/filename.jpg

注意tripple“/”!

  String path = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_PICTURES; File dir = new File(path); 

You can use something like – Context.getExternalCacheDirs() or Context.getExternalFilesDirs() or Context.getObbDirs(). They give application specific directories in all external storage devices where the application can store its files.

So something like this – Context.getExternalCacheDirs()[i].getParentFile().getParentFile().getParentFile().getParent() can get you the root path of external storage devices.

I know these commands are for a different purpose but other answers didn't work for me.

This link gave me good pointers – https://possiblemobile.com/2014/03/android-external-storage/

System.getenv("SECONDARY_STORAGE") returns null for Marshmallow. This is another way of finding all the externals dirs. You can check if it's removable which determines if internal/external

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { File[] externalCacheDirs = context.getExternalCacheDirs(); for (File file : externalCacheDirs) { if (Environment.isExternalStorageRemovable(file)) { // It's a removable storage } } } 

I have tried the solutions provided by Dmitriy Lozenko and Gnathonic on my Samsung Galaxy Tab S2 (Model: T819Y) but none helped me retrieve path to an external SD Card directory. mount command execution contained the required path to external SD Card directory (ie /Storage/A5F9-15F4) but it did not match the regular expression hence it was not returned. I don't get the directory naming mechanism followed by Samsung. Why they deviate from standards (ie extsdcard) and come up with something really fishy like in my case (ie /Storage/A5F9-15F4) . 有什么我失踪? Anyways, following changes in regular expression of Gnathonic's solution helped me get valid sdcard directory:

 final HashSet<String> out = new HashSet<String>(); String reg = "(?i).*(vold|media_rw).*(sdcard|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; 

I am not sure if this is a valid solution and if it will give results for other Samsung tablets but it has fixed my problem for now. Following is another method to retrieve removable SD Card path in Android (v6.0). I have tested the method with android marshmallow and it works. Approach used in it is very basic and will surely work for other versions too but testing is mandatory. Some insight into it will be helpful:

 public static String getSDCardDirPathForAndroidMarshmallow() { File rootDir = null; try { // Getting external storage directory file File innerDir = Environment.getExternalStorageDirectory(); // Temporarily saving retrieved external storage directory as root // directory rootDir = innerDir; // Splitting path for external storage directory to get its root // directory String externalStorageDirPath = innerDir.getAbsolutePath(); if (externalStorageDirPath != null && externalStorageDirPath.length() > 1 && externalStorageDirPath.startsWith("/")) { externalStorageDirPath = externalStorageDirPath.substring(1, externalStorageDirPath.length()); } if (externalStorageDirPath != null && externalStorageDirPath.endsWith("/")) { externalStorageDirPath = externalStorageDirPath.substring(0, externalStorageDirPath.length() - 1); } String[] pathElements = externalStorageDirPath.split("/"); for (int i = 0; i < pathElements.length - 1; i++) { rootDir = rootDir.getParentFile(); } File[] files = rootDir.listFiles(); for (File file : files) { if (file.exists() && file.compareTo(innerDir) != 0) { // Try-catch is implemented to prevent from any IO exception try { if (Environment.isExternalStorageRemovable(file)) { return file.getAbsolutePath(); } } catch (Exception e) { e.printStackTrace(); } } } } catch (Exception ex) { ex.printStackTrace(); } return null; } 

Kindly share if you have any other approach to handle this issue. 谢谢

 String secStore = System.getenv("SECONDARY_STORAGE"); File externalsdpath = new File(secStore); 

This will get the path of external sd secondary storage.

 //manifest file outside the application tag //please give permission write this //<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> File file = new File("/mnt"); String[] fileNameList = file.list(); //file names list inside the mnr folder String all_names = ""; //for the log information String foundedFullNameOfExtCard = ""; // full name of ext card will come here boolean isExtCardFounded = false; for (String name : fileNameList) { if (!isExtCardFounded) { isExtCardFounded = name.contains("ext"); foundedFullNameOfExtCard = name; } all_names += name + "\n"; // for log } Log.d("dialog", all_names + foundedFullNameOfExtCard); 

On Galaxy S3 Android 4.3 the path I use is ./storage/extSdCard/Card/ and it does the job. 希望它有帮助,

The following steps worked for me. You just need to write this lines:

 String sdf = new String(Environment.getExternalStorageDirectory().getName()); String sddir = new String(Environment.getExternalStorageDirectory().getPath().replace(sdf,"")); 

The first line will give the name of sd directory, and you just need to use it in the replace method for the second string. The second string will contain the path for the internal and removable sd(/storage/ in my case) . I just needed this path for my app but you can go further if you need it.