在 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 Q 中从外部存储访问照片

Android Q:范围存储中的 SQLite 数据库

以编程方式测试是否在Android 10+中禁用了旧版外部存储访问

android中的文件操作详解以及内部存储和外部存储

应用程序如何在没有 root 的情况下访问 Android 6.0(API 级别 23)中 USB OTG 存储上的文件?

Android API 29最新把文件转存到外部公共图片相册库