Android 11 中的存储机制更新,无权操作SD根目录要使用分区存储

  • 发表于
  • android

Android 11 中的存储机制更新

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

此版本还改进了分区存储,以便开发者更轻松地迁移到此存储模型。如需了解详情,请参阅 Android 存储用例和最佳做法指南,以及标题为 Android 11 存储常见问题解答的 Medium 文章。

强制执行分区存储

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

保持与 Android 10 的兼容性

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

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

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

测试分区存储

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

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

管理设备存储空间

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

  1. 通过调用 ACTION_MANAGE_STORAGE intent 操作检查可用空间。
  2. 如果设备上的可用空间不足,请提示用户同意让您的应用清除所有缓存。为此,请调用 ACTION_CLEAR_APP_CACHE intent 操作。注意ACTION_CLEAR_APP_CACHE intent 操作会严重影响设备的电池续航时间,并且可能会从设备上移除大量的文件。

外部存储设备上的应用专用目录

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

媒体文件访问权限

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

执行批量操作

为实现各种设备之间的一致性并增加用户便利性,Android 11 添加了多种方法,以便开发者更轻松地管理媒体文件组

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

为了帮助您的应用更顺畅地使用第三方媒体库,Android 11 允许您使用除 MediaStore 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_TREE 或 ACTION_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 引入了与存储权限相关的以下变更。

以任何版本为目标平台

Android 11 中的存储机制更新,无权操作SD根目录要使用分区存储
图 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 特许权限将不再提供任何其他访问权限。

请注意,在搭载 Android 10(API 级别 29)或更高版本的设备上,您的应用可以提供明确定义的媒体集合,例如 MediaStore.Downloads,而无需请求任何存储相关权限。详细了解如何在处理应用中的媒体文件时仅请求必要的权限

所有文件访问权限 MANAGE_EXTERNAL_STORAGE

绝大多数需要共享存储空间访问权限的应用都可以遵循共享媒体文件共享非媒体文件方面的最佳做法。但是,某些应用的核心用例需要广泛访问设备上的文件,但无法采用注重隐私保护的存储最佳做法高效地完成这些操作。对于这些情况,Android 提供了一种名为“所有文件访问权限”的特殊应用访问权限。如需了解详情,请参阅有关如何管理存储设备上的所有文件的指南。