如何判断Android中两个文件路径是否位于同一存储卷?
Android 判断两个文件路径是否属于同一存储卷
前提说明
已获取MANAGE_EXTERNAL_STORAGE权限,且确认可访问所有存储卷。
推荐实现:使用系统提供的StorageManager API
直接依赖Android系统的存储管理API是最可靠的方式,能避免路径别名(如同一SD卡的/mnt/media_rw/XXX和/storage/XXX挂载点)导致的判断错误。
代码示例(Kotlin)
import android.content.Context import android.os.storage.StorageManager import java.io.File fun isSameStorageVolume(context: Context, path1: String, path2: String): Boolean { val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager val file1 = File(path1) val file2 = File(path2) // 获取路径对应的存储卷实例 val volume1 = storageManager.getStorageVolume(file1) val volume2 = storageManager.getStorageVolume(file2) // 路径无效时返回false if (volume1 == null || volume2 == null) return false // 通过UUID判断是否为同一存储卷(也可直接比较StorageVolume对象引用) return volume1.uuid == volume2.uuid }
原理说明
StorageManager.getStorageVolume(File)会自动解析路径对应的实际存储卷,不管路径是内部存储的/storage/emulated/0,还是SD卡的/mnt/media_rw/XXX或/storage/XXX,只要属于同一物理存储设备,就会返回同一个StorageVolume实例,通过uuid可以准确区分不同存储卷。
兼容旧版本方案:解析/proc/mounts文件
如果需要兼容API 24以下的系统,可通过读取系统挂载信息文件/proc/mounts来判断挂载点:
代码示例(Kotlin)
import java.io.File fun getMountPoint(path: String): String? { return runCatching { File("/proc/mounts").readLines() .map { it.split("\\s+".toRegex()) } .filter { it.size >= 2 } // 匹配最长的挂载点前缀,避免子目录挂载的干扰 .find { parts -> val mountPoint = parts[1] path.startsWith(mountPoint) && (path.length == mountPoint.length || path[mountPoint.length] == '/') }?.get(1) }.getOrNull() } fun isSameMountPoint(path1: String, path2: String): Boolean { val mount1 = getMountPoint(path1) val mount2 = getMountPoint(path2) return mount1 == mount2 }
注意事项
- 需要确保应用有读取
/proc/mounts的权限,MANAGE_EXTERNAL_STORAGE权限已足够覆盖。 - 该方法依赖系统文件格式,不同ROM可能存在格式差异,稳定性不如官方API。
示例验证
针对你给出的路径:
/storage/emulated/0/b.txt属于内部存储卷/mnt/media_rw/0X84-15XX/a.txt和/storage/9CXX-6BXX/c.txt如果是同一SD卡的不同挂载路径,使用官方API会判断为同一存储卷,而直接解析路径前缀会误判为不同,这也是之前错误答案的问题所在。
内容的提问来源于stack exchange,提问作者Cyber Avater
相关产品推荐
相关产品推荐

