Android下如何检测已挂载外部存储数量并获取其路径
Hey there! 针对你提出的关于Android系统中检测外部存储(外置SD卡、USB存储)数量、获取路径的问题,我来一步步给你梳理清楚:
先澄清几个常见误区
关于/root/mnt/sdcard路径的适用性
先明确一点:
/root/mnt/sdcard这个路径几乎不会出现在正常的Android设备中,你大概率是混淆了/mnt/sdcard?
实际上,/mnt/sdcard早期是很多设备用来映射主外部存储的路径,但现在Android版本迭代后,它已经是一个软链接,指向/storage/emulated/0(对应多用户模式下的主用户空间)。而且这个路径并不适用于所有设备——不同厂商可能会自定义路径,比如有些设备用/storage/sdcard0这类命名,硬编码这个路径的可靠性极低,绝对不推荐这么做。
Environment.getExternalStorageDirectory()的局限
你说得没错,这个API只能返回主外部存储的路径,也就是系统默认的那个外部存储(通常是内置扩展存储,或是插入SD卡后被设为主存储的那个),完全无法获取其他挂载的外置SD卡、USB存储设备。
核心方案:检测所有已挂载外部存储的数量与路径
下面两种方法是实战中常用的方案,优先推荐官方API的方式:
方法一:使用Android官方API(Android 4.4+ 推荐)
从Android 4.4(API 19)开始,系统提供了Context.getExternalFilesDirs()、Context.getExternalCacheDirs()这类方法,它们会返回所有可用的外部存储目录(包括主存储、外置SD卡、USB存储)。我们可以通过返回数组的有效条目数统计数量,再通过路径处理得到根目录。
示例代码:
// 获取所有外部存储的应用私有目录 File[] externalFilesDirs = getApplicationContext().getExternalFilesDirs(null); int mountedStorageCount = 0; List<String> storageRootPaths = new ArrayList<>(); for (File dir : externalFilesDirs) { // 只筛选已挂载的存储 if (dir != null && Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState(dir))) { mountedStorageCount++; // 从私有目录路径切割出存储根路径 String rootPath = dir.getAbsolutePath().split("/Android/data/")[0]; storageRootPaths.add(rootPath); } } // mountedStorageCount 就是已挂载的外部存储总数 // storageRootPaths 是所有已挂载存储的根路径列表
优点:这种方法是官方推荐的,适配性强,而且返回的路径已经经过系统授权,Android 10+不需要额外申请
WRITE_EXTERNAL_STORAGE权限。
方法二:读取系统挂载文件(权限要求高,适配需谨慎)
如果你的场景需要更底层的信息,可以尝试读取系统挂载文件或遍历/storage目录,但这种方法在高版本Android中可能因权限限制失效,且适配成本高。
读取/proc/mounts文件
这个文件记录了系统所有已挂载的文件系统,我们可以筛选出外部存储相关的条目:
try { BufferedReader reader = new BufferedReader(new FileReader("/proc/mounts")); String line; List<String> storagePaths = new ArrayList<>(); while ((line = reader.readLine()) != null) { // 筛选常见的外部存储文件系统类型与路径 if (line.contains("/storage/") && (line.contains("vfat") || line.contains("exfat") || line.contains("ext4"))) { String[] parts = line.split(" "); String path = parts[1]; // 排除虚拟存储和临时目录 if (!path.contains("/emulated/") && !path.contains("/self/")) { storagePaths.add(path); } } } reader.close(); int mountedCount = storagePaths.size(); } catch (IOException e) { e.printStackTrace(); }
遍历/storage目录
/storage目录通常包含所有已挂载的外部存储目录,直接遍历即可:
File storageDir = new File("/storage"); File[] storageItems = storageDir.listFiles(); int mountedCount = 0; List<String> paths = new ArrayList<>(); if (storageItems != null) { for (File item : storageItems) { if (item.isDirectory() && Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState(item))) { mountedCount++; paths.add(item.getAbsolutePath()); } } }
总结
- 统计已挂载数量:优先用
getExternalFilesDirs()返回的数组,过滤状态为MEDIA_MOUNTED的条目,数量就是结果。 - 获取所有路径:通过官方API的私有目录路径切割得到根路径,绝对不要硬编码任何固定路径。
/root/mnt/sdcard完全不适用于正常设备,/mnt/sdcard也只是旧版本的软链接,不要依赖它。
内容的提问来源于stack exchange,提问作者MJ55

