[英]Android 26 returns only one path Context.getExternalFilesDirs()
我正在使用getExternalFilesDirs(null)
个 API 模拟器测试 Pixel,当使用getExternalFilesDirs(null)
方法时,它们将返回两个路径(第一个是外部内置 sdcard,第二个是外部可移动 sdcard):
/storage/emulated/0/Android/data/com.*.*/files
/storage/13F6-3510/Android/data/com.*.*/files
但是后来我尝试将 Pixel 与 26 API 一起使用,但我只有一条路径:
/storage/emulated/0/Android/data/com.*.*/files
然后我找到了另一种获取所有存储路径的方法,它返回一些新的东西给我,通常它以/storage/
开头,但现在它以/mnt/media_rw/
:
/storage/emulated/0
/mnt/media_rw/1D13-0D17
使用StorageManager
获取它的方法:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
val storageVolumes = storageManager.storageVolumes
if (!storageVolumes.isNullOrEmpty()) {
for (storageVolume in storageVolumes) {
val volumePath = getVolumePath(storageVolume) ?: continue
result.add(File(volumePath))
}
}
}
@RequiresApi(Build.VERSION_CODES.N)
private fun getVolumePath(storageVolume: StorageVolume): String? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
return storageVolume.directory?.absolutePath
try {
val storageVolumeClazz = StorageVolume::class.java
val getPath = storageVolumeClazz.getMethod("getPath")
return getPath.invoke(storageVolume) as String
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
可以看到这个方法甚至对 API < R (30) 使用了反射
所以我为 Pixel 26 API 得到了这条路径/mnt/media_rw/1D13-0D17
。 我不明白为什么与其他 API 存在差异。
但是这条路径还不能访问,我看不懂。 然后我尝试使用来自 Google Play 的一些流行的文件浏览器/资源管理器应用程序,我发现他们请求一些权限来访问此类外部可移动存储:
我以前从未见过这样的事情。 他们是如何做到的,为什么它甚至存在?
我有带有getExternalFilesDirs(null)
API 的真实设备,它们都不需要使用这种方法来访问外部可移动存储,我可以只使用getExternalFilesDirs(null)
。 同样适用于具有相同 API 的 Pixel 模拟器
那么/mnt/media_rw/*
来自哪里以及如何从我的应用程序请求访问它的权限,如果对于其他 API 我不需要这样做,为什么我什至需要授予此权限?
我在官方 Android 文档中找不到有关它的任何信息
所以我为 Pixel 26 API 得到了这条路径 /mnt/media_rw/1D13-0D17。 我不明白为什么与其他 API 存在差异。 但是这条路径还不能访问,我看不懂。 然后我尝试使用来自 Google Play 的一些流行的文件浏览器/资源管理器应用程序,我发现他们请求一些权限来访问此类外部可移动存储:
我发现这样的路径也不可读和不可列出。
但为什么其他应用程序可以? 我认为他们不能太使用 File 类。 他们将使用存储访问框架。
例如 SDK 27 是 Android O。
对于 Android N、O 和 P,您的应用可以通过以下方式创建访问意图:
volume.createAccessIntent()
请尝试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.