在 Android API 29 中访问外部存储
Posted
技术标签:
【中文标题】在 Android API 29 中访问外部存储【英文标题】:Accessing external storage in Android API 29 【发布时间】:2020-12-29 16:22:45 【问题描述】:我正在尝试实现一些清理工具。越来越多的厂商出于“安全原因”禁止root设备,禁止不请求解锁。
API 28 之后,这段代码会报错:
ActivityCompat.requestPermissions(this, new String[]
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
, 1); // Request permission or not, Will got same result
File rootFolder = Environment.getExternalStorageDirectory(); // That is working fine
rootFolder.listFiles(); // That will return null
当然,我可以用这个:
android:requestLegacyExternalStorage="true"
但我相信将来会被杀死。
那么,有什么优雅的方式来管理 SDCard?
【问题讨论】:
这适用于 Android 10。使用它,即使您为 Android 11 编译它也适用于 Android 10 设备。而且...该代码不适用于可移动的微型 sd 卡。 有一个名为 MANAGE_EXTERNAL_STORAGE 的权限可供某些应用程序使用,例如文件管理器、设备迁移应用程序等。它可以让您完全访问文件系统。您的清理工具应该属于同一类别developer.android.com/training/data-storage/manage-all-files 【参考方案1】:在 Android 10 上,Environment.getExternalStorageDirectory()
和 Environment.getExternalStoragePublicDirectory()
将返回存储路径,但路径不可读写。
对于 Android 10,如果您将 android:requestLegacyExternalStorage="true"
添加到清单文件中的应用程序标记,则可以继续使用 Environment.getExternalStorageDirectory() 和 Environment.getExternalStoragePublicDirectory() 提供的路径。在运行时,您的应用可以调用 Environment.isExternalStorageLegacy()
来检查请求是否已完成。
另一种(未知)可能性(仅适用于 Android 10)是将 <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
添加到清单文件中。
用户必须进入应用程序的高级设置并从Advanced settings Install unknown apps | Allow from this source
启用。
这样做的好处是用户可以切换访问权限。如果你实现一个意图,你可以让用户更容易
Settings.ACTION_APPLICATION_DETAILS_SETTINGS
他可以更改设置。
有趣的是 Environment.isExternalStorageLegacy() 也返回 true。
为 Android 11 编译这两个选项都不适用于 Android 11 设备。 (但它们继续适用于 Android 10 设备)。 Environment.getExternalStorageDirectory() 和 Environment.getExternalStoragePublicDirectory() 的路径是usable again in read mode and very often in write mode too
。这很棒,因为可以再次使用 File 类简单地列出目录的内容,例如下载或图片或 DCIM/Camera。
但是将<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
添加到清单文件并实现一个意图
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
将为您的应用程序提供对所有文件的读/写访问权限,即使在可移动 micro sd 卡上也是如此。
(最后,您可以使用自己的应用程序删除无法在自己的 Android 设备上读取/写入自己的 micro sd 卡的 google 禁令)。
Environment.isExternalStorageManager()
可用于检查权限是否打开/关闭。
只要您不尝试将应用上传到 Play 商店就可以了。
【讨论】:
一旦你添加了 android:requestLegacyExternalStorage="true" 用 android:requestLegacyExternalStorage="false" 更新你的应用程序没有任何效果。并且 isExternalStorageLegacy() 不断返回 true。必须卸载该应用程序。有了新的解决方案,就没有这样的麻烦了。 遗憾的是,Android 11 下的 ,,/Android/data 目录仍然无法访问。也适用于新加坡武装部队。 VLC 没有权限"android.permission.MANAGE_EXTERNAL_STORAGE"
github.com/videolan/vlc-android/blob/master/application/… 并且它仍然可以删除 Android 11 上的文件。Android Studio 也给出了关于 MANAGE_EXTERNAL_STORAGE
的警告,因此通常不应该被应用程序使用
@user25,也可以使用 SAF。你可以忽略这个警告,好吧......除非你想去看戏。
VLC 仍然使用 29 SDK,这就是为什么它适用于他们..【参考方案2】:
在你的清单中使用 android:requestLegacyExternalStorage="true"
【讨论】:
这在将来不会总是有效,除非 Play 商店例外。所以,除非你真的需要它,否则你应该避免使用它。以上是关于在 Android API 29 中访问外部存储的主要内容,如果未能解决你的问题,请参考以下文章
以编程方式测试是否在Android 10+中禁用了旧版外部存储访问
应用程序如何在没有 root 的情况下访问 Android 6.0(API 级别 23)中 USB OTG 存储上的文件?