Android 11 中的存储更新

Android 11 (API 级别 30) 进一步增强了平台,为外部存储上的应用和用户数据提供了更好的保护。此版本引入了多项增强功能,例如原始文件路径访问、媒体文件的批量编辑操作以及存储访问框架的更新版 UI。

此版本还改进了分区存储,这使得开发者在迁移到此存储模型后,更容易满足其存储用例

分区存储强制执行

在 Android 11 上运行但以 Android 10 (API 级别 29) 为目标的应用仍可请求 requestLegacyExternalStorage 属性。此标记允许应用暂时退出与分区存储相关的更改,例如授予对不同目录和不同类型媒体文件的访问权限。在您更新应用以 Android 11 为目标后,系统会忽略 requestLegacyExternalStorage 标记。

保持与 Android 10 的兼容性

如果您的应用在 Android 10 设备上运行时选择不使用分区存储,建议您继续在应用的清单文件中将 requestLegacyExternalStorage 设置为 true。这样,您的应用就可以在运行 Android 10 的设备上继续按预期运行。

将数据迁移到使用分区存储时可见的目录

如果您的应用使用旧版存储模型,并且之前以 Android 10 或更低版本为目标,则在启用分区存储模型时,您可能将数据存储在应用无法访问的目录中。在以 Android 11 为目标之前,请将数据迁移到与分区存储兼容的目录。

测试分区存储

若要在应用中启用分区存储(无论应用的 TARGET SDK 版本和清单标记值如何),请启用以下应用兼容性标记:

停用分区存储而改用旧版存储模型,请取消设置这两个标记。

管理设备存储空间

从 Android 11 开始,使用分区存储模型的应用只能访问其自己的应用专属缓存文件。如果您的应用需要管理设备存储空间,请按照说明查询可用空间

  1. 通过调用 ACTION_MANAGE_STORAGE intent 操作来检查可用空间。
  2. 如果设备上没有足够的可用空间,请提示用户授予您的应用清除所有缓存的权限。为此,请调用 ACTION_CLEAR_APP_CACHE intent 操作。

外部存储上的应用专属目录

从 Android 11 开始,应用无法在外部存储上创建自己的应用专属目录。如需访问系统为您的应用提供的目录,请调用 getExternalFilesDirs()

媒体文件访问

为了在保留用户隐私的同时更轻松地访问媒体文件,Android 11 添加了以下功能。

执行批量操作

为了跨设备的一致性和提高用户便利性,Android 11 添加了多种方法,以便更轻松地管理媒体文件组

使用直接文件路径和原生库访问文件

为了帮助您的应用与第三方媒体库更流畅地协作,Android 11 允许您使用 MediaStore API 之外的其他 API,通过直接文件路径从共享存储中访问媒体文件。这些 API 包括:

  • File API。
  • 原生库,例如 fopen()

访问其他应用的数据

为了保护用户隐私,在运行 Android 11 或更高版本的设备上,系统会进一步限制您的应用访问其他应用的私有目录。

访问内部存储上的数据目录

Android 9 (API 级别 28) 开始限制哪些应用可以将其内部存储上的数据目录中的文件设为可供全球其他应用访问。以 Android 9 或更高版本为目标的应用无法将其数据目录中的文件设为可供全球访问

Android 11 进一步扩展了这项限制。如果您的应用以 Android 11 为目标,则无法访问任何其他应用的数据目录中的文件,即使其他应用以 Android 8.1 (API 级别 27) 或更低版本为目标,并已将其数据目录中的文件设为可供全球读取。

访问外部存储上的应用专属目录

在 Android 11 上,应用无法再访问外部存储中任何其他应用的专用应用专属目录中的文件。

文档访问限制

为了给开发者留出测试时间,以下与存储访问框架 (SAF) 相关的更改仅在您的应用以 Android 11 或更高版本为目标时生效。

访问目录

您不能再使用 ACTION_OPEN_DOCUMENT_TREE intent 操作请求访问以下目录:

  • 内部存储卷的根目录。
  • 设备制造商认为可靠的每个 SD 卡卷的根目录,无论该卡是模拟的还是可移除的。可靠的卷是指应用大多数时候可以成功访问的卷。
  • Download 目录。

访问文件

您不能再使用 ACTION_OPEN_DOCUMENT_TREEACTION_OPEN_DOCUMENT intent 操作来请求用户从以下目录中选择单个文件:

  • Android/data/ 目录及其所有子目录。
  • Android/obb/ 目录及其所有子目录。

测试更改

如需测试此行为变更,请执行以下操作:

  1. 调用带有 ACTION_OPEN_DOCUMENT 操作的 intent。检查 Android/data/Android/obb/ 目录是否都不显示。
  2. 执行以下任一操作:
  3. 调用带有 ACTION_OPEN_DOCUMENT_TREE 操作的 intent。检查 Download 目录是否显示以及与该目录关联的操作按钮是否显示为灰色。

权限

Android 11 引入了以下与存储权限相关的更改。

目标版本不限

The first dialog presents a link called Allow in settings
图 1. 应用使用分区存储并请求 READ_EXTERNAL_STORAGE 权限时显示的对话框。

以下更改在 Android 11 中生效,无论您的应用目标 SDK 版本如何:

  • 存储空间运行时权限已重命名为文件和媒体
  • 如果您的应用尚未退出分区存储并请求 READ_EXTERNAL_STORAGE 权限,用户会看到一个与 Android 10 不同的对话框。该对话框会指明您的应用正在请求访问照片和媒体,如图 1 所示。

    用户可以在系统设置中查看哪些应用拥有 READ_EXTERNAL_STORAGE 权限。在设置 > 隐私 > 权限管理器 > 文件和媒体页面上,拥有该权限的每个应用都列在允许访问所有文件下。如果您的应用以 Android 11 为目标,请记住,此“所有文件”访问权限是只读的。如需使用此应用对共享存储中的所有文件进行读操作,您需要拥有所有文件访问权限。

以 Android 11 为目标

如果您的应用以 Android 11 为目标,则 WRITE_EXTERNAL_STORAGE 权限和 WRITE_MEDIA_STORAGE 特权权限都不再提供任何额外访问权限。

请注意,在运行 Android 10 (API 级别 29) 或更高版本的设备上,您的应用无需请求任何与存储相关的权限即可将文件添加到 MediaStore.Downloads 等定义明确的媒体集中。详细了解如何在应用中处理媒体文件时仅请求必要的权限

所有文件访问权限

大多数需要共享存储访问权限的应用都可以遵循共享媒体文件共享非媒体文件的最佳实践。但是,有些应用的核心用例需要广泛访问设备上的文件,但无法使用隐私友好的存储最佳实践高效地做到这一点。针对这些情况,Android 提供了一种特殊应用访问权限,称为所有文件访问权限。如需了解详情,请参阅有关如何在存储设备上管理所有文件的指南。

其他资源

如需详细了解 Android 11 中的存储更改,请查看以下资料:

博文

视频