API 19+下验证文件路径是否为SD卡及获取SD卡目录方案求助
解决API 19+下获取可移除SD卡路径的问题
我之前也踩过一模一样的坑!尤其是三星Tab S2这类设备,Environment.getExternalStorageDirectory()返回的居然是内置的不可移除存储,完全不是我们要的SD卡路径。毕竟Android对“外部存储”的定义本来就包含了内置可共享存储和可移除SD卡,旧方法根本没法区分两者。
针对API 19及以上的适配,给你两个靠谱的方案:
方案一:用Context.getExternalFilesDirs()(推荐)
这个API从API 19开始支持,会返回所有外部存储的App专属目录数组,包括内置存储和SD卡的。我们只需要从中筛选出可移除的SD卡路径即可:
import android.content.Context; import android.os.Environment; import java.io.File; public class StorageUtils { // 获取可移除SD卡的根目录 public static String getRemovableSdCardRoot(Context context) { File[] externalDirs = context.getExternalFilesDirs(null); for (File dir : externalDirs) { if (dir == null) continue; // 排除内置外部存储,剩下的就是SD卡的App专属目录 if (!isInternalExternalStorage(dir)) { // 从App专属目录截取到SD卡根目录 // 示例路径:/storage/XXXX-XXXX/Android/data/com.yourapp.package/files String appDirPath = dir.getAbsolutePath(); return appDirPath.substring(0, appDirPath.indexOf("/Android/data")); } } return null; // 未检测到可移除SD卡 } // 判断是否是内置的外部存储 private static boolean isInternalExternalStorage(File dir) { return Environment.getExternalStorageDirectory().equals(dir); } }
注意事项:
- 这个方法返回的是SD卡的根目录,如果你只需要访问App在SD卡上的私有目录,直接用
dir.getAbsolutePath()即可,无需截取 - 权限方面:API 19-28需要添加
READ_EXTERNAL_STORAGE权限;API 29+如果只访问App私有目录不需要额外权限,若要访问SD卡其他公共目录,需要适配分区存储,或者针对API 30+申请MANAGE_EXTERNAL_STORAGE权限
方案二:读取系统挂载信息(备选,兼容性稍差)
如果上面的方法不满足需求,还可以通过读取/proc/mounts文件来解析SD卡挂载路径,但这种方法依赖厂商的挂载规则,稳定性不如方案一:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class StorageUtils { public static List<String> getSdCardPaths() { List<String> paths = new ArrayList<>(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("/proc/mounts")); String line; while ((line = reader.readLine()) != null) { // 筛选出vfat或exfat格式的可移除存储(SD卡常见格式) if ((line.contains("vfat") || line.contains("exfat")) && line.contains("/storage/")) { String[] parts = line.split(" "); String path = parts[1]; // 排除内置存储的挂载路径 if (!path.equals(Environment.getExternalStorageDirectory().getAbsolutePath())) { paths.add(path); } } } } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return paths; } }
提示:
- 这个方法可能会返回多个路径,需要你自己验证哪些是有效的可移除SD卡路径
- 同样需要对应的存储权限才能访问这些路径
内容的提问来源于stack exchange,提问作者Projava
相关产品推荐
相关产品推荐

