Android 11 中的存储机制更新

Android 11 进一步增强了平台功能,为外部存储设备上的应用和用户数据提供了更好的保护。作为这项工作的一部分,平台引入了进一步的改进,以简化向分区存储的转换。

此预览版引入了多项我们去年在 Android 开发者峰会上展示的增强功能,例如可主动选择启用的媒体原始文件路径访问机制、面向媒体的批量编辑操作,以及存储访问框架的界面更新。

在即将推出的开发者预览版中,您可以看到有关文件访问机制的其他增强功能以及有关文件管理和图库的政策更新。我们一如既往地诚邀您提供反馈,帮助我们完善下一版 Android。请使用问题跟踪器向我们发送反馈意见。

欢迎您提供相关反馈!请填写这份简短的调查问卷,将您使用此功能的情况告知我们。特别是,请将受此功能影响的用例告知我们。

分区存储强制执行

为了给开发者更多时间进行测试,以 Android 10(API 级别 29)为目标平台的应用仍可请求 requestLegacyExternalStorage 属性。应用可以利用此标记暂时停用与分区存储相关的变更,例如授予对不同目录和不同类型的媒体文件的访问权限。当您将应用更新为以 Android 11 为目标平台后,系统会忽略 requestLegacyExternalStorage 标记。

保持与 Android 10 的兼容性

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

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

如果您的应用使用旧版存储模型且之前以 Android 10 或更低版本为目标平台,您可能会将数据存储到启用分区存储模型后您的应用无法访问的目录中。在以 Android 11 为目标平台之前,请将数据迁移到与分区存储兼容的目录。在大多数情况下,您可以将数据迁移到您的应用专用目录

如果您有需要迁移的数据,当用户升级到以 Android 11 为目标平台的新版应用时,可以保留旧版存储模型。这样,用户就可以保留对您的应用之前用于保存数据的目录中存储的应用数据的访问权限。如需启用旧版存储模型以进行升级,请在应用的清单中将 preserveLegacyExternalStorage 属性设为 true

注意:大多数应用都不需要使用 preserveLegacyExternalStorage。此标记仅适用于这样一种情况:您将应用数据迁移到了与分区存储兼容的位置,并且希望用户在更新您的应用时保留对数据的访问权限。使用此标记会导致更难以测试分区存储对您应用的用户有何影响,因为当用户更新您的应用时,它会继续使用旧版存储模型。

如果您使用 preserveLegacyExternalStorage,旧版存储模型只在用户卸载您的应用之前保持有效。如果用户在搭载 Android 11 的设备上安装或重新安装您的应用,那么无论 preserveLegacyExternalStorage 的值是什么,您的应用都无法停用分区存储模型。

测试分区存储

如需在您的应用中启用分区存储,而不考虑应用的目标 SDK 版本和清单标记值,请启用以下应用兼容性标记:

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

管理设备存储空间

如果您的应用是文件管理器应用并且在 Android 11 上运行,它就不能再删除其他应用的缓存文件,即使您的应用具有所有文件访问权限也是如此。相反,您的应用应执行以下操作:

  1. 通过调用 ACTION_MANAGE_STORAGE intent 操作检查可用空间。
  2. 如果设备上的可用空间不足,请提示用户同意让您的应用清除所有缓存。为此,请调用 ACTION_CLEAR_APP_CACHE intent 操作。

媒体文件访问权限

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

执行批量操作

为实现各种设备之间的一致性并增加用户便利性,Android 11 向 MediaStore API 中添加了多种方法。对于希望简化特定媒体文件更改流程(例如在原位置编辑照片)的应用而言,这些方法尤为有用。

添加的方法如下:

createWriteRequest()
用户向应用授予对指定媒体文件组的写入访问权限的请求。
createFavoriteRequest()
用户将设备上指定的媒体文件标记为“收藏”的请求。对该文件具有读取访问权限的任何应用都可以看到用户已将该文件标记为“收藏”。
createTrashRequest()
用户将指定的媒体文件放入设备垃圾箱的请求。垃圾箱中的内容会在系统定义的时间段后被永久删除。
createDeleteRequest()
用户立即永久删除指定的媒体文件(而不是先将其放入垃圾箱)的请求。

系统在调用以上任何一个方法后,会构建一个 PendingIntent 对象。应用调用此 intent 后,用户会看到一个对话框,请求用户同意应用更新或删除指定的媒体文件。

使用原始路径访问文件

Android 11 允许具有 READ_EXTERNAL_STORAGE 权限的应用读取使用直接文件路径和原生库的设备媒体文件。借助此功能,您的应用与第三方媒体库会配合使用得更顺畅。

如果您使用直接文件路径和原生库,建议您在应用的清单文件中将 requestLegacyExternalStorage 设置为 true,从而选择停用分区存储。这样,您的应用就可以在搭载 Android 10 的设备上正常工作。

访问其他应用的私有目录

在 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 引入了与存储权限相关的以下变更。

以任何版本为目标平台

第一个对话框中显示了一个名为“在‘设置’中允许”的链接
图 1. 应用使用分区存储并请求 READ_EXTERNAL_STORAGE 权限时显示的对话框。

不管应用的目标 SDK 版本是什么,以下变更均会在 Android 11 中生效:

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

    用户可以在系统设置中查看哪些应用具有 READ_EXTERNAL_STORAGE 权限。在设置 > 隐私 > 权限管理器 > 文件和媒体页面上,具有该权限的每个应用都列在允许存储所有文件下。

    注意:如果您的应用以 Android 11 为目标平台,请记住,对“所有文件”的这种访问权限是只读访问权限。如需使用此应用读取和写入共享的存储空间中的所有文件,需要具有所有文件访问权限。

以 Android 11 为目标平台

如果应用以 Android 11 为目标平台,那么 WRITE_EXTERNAL_STORAGE 权限和 WRITE_MEDIA_STORAGE 特许权限将不再提供任何其他访问权限。

所有文件访问权限

某些应用的核心用例需要访问大量的文件,如文件管理操作或备份和恢复操作。这些应用可通过执行以下操作获取“所有文件访问权限”:

  1. 声明 MANAGE_EXTERNAL_STORAGE 权限。
  2. 使用 ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION intent 操作将用户引导至一个系统设置页面,在该页面上,用户可以为您的应用启用以下选项:授予所有文件的管理权限

“所有文件访问权限”可授予以下权限:

应用可以使用 MediaStore API 或原始文件路径访问这些文件。如果您的应用使用存储访问框架,您不能使用它访问“所有文件访问权限”提供的其他文件和目录。

MANAGE_EXTERNAL_STORAGE 权限允许应用访问共享的存储空间中的潜在敏感数据。在即将推出的开发者预览版中,Google Play 会为需要此权限的应用提供相关指南,敬请期待。

如需详细了解此特殊权限以及 Android 11 中 Android 存储 API 的其他更改,请参阅标题为 Android 上的现代用户存储的媒体文章。