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 之前,迁移数据 到与作用域存储兼容的目录。
测试作用域存储
要启用应用中的作用域存储,无论应用的目标 SDK 版本和清单标志值如何,请启用以下应用兼容性标志
DEFAULT_SCOPED_STORAGE
(默认情况下对所有应用启用)FORCE_ENABLE_SCOPED_STORAGE
(默认情况下对所有应用禁用)
要禁用作用域存储并改用旧版存储模型,请取消设置这两个标志。
管理设备存储
从 Android 11 开始,使用作用域存储模型的应用只能访问其自己的特定于应用的缓存文件。如果您的应用需要管理设备存储,请按照有关如何 查询可用空间 的说明操作。
- 通过调用
ACTION_MANAGE_STORAGE
意图操作来检查可用空间。 如果设备上没有足够的可用空间,请提示用户允许您的应用清除所有缓存。为此,请调用
ACTION_CLEAR_APP_CACHE
意图操作。
外部存储上的特定于应用的目录
从 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_TREE
或ACTION_OPEN_DOCUMENT
intent 操作来请求用户从以下目录中选择单个文件:
Android/data/
目录及其所有子目录。Android/obb/
目录及其所有子目录。
测试更改
要测试此行为更改,请执行以下操作:
- 使用
ACTION_OPEN_DOCUMENT
操作调用 intent。检查Android/data/
和Android/obb/
目录是否都不显示。 - 执行以下任一操作:
- 启用
RESTRICT_STORAGE_ACCESS_FRAMEWORK
应用兼容性标志。 - 面向 Android 11 或更高版本。
- 启用
- 使用
ACTION_OPEN_DOCUMENT_TREE
操作调用 intent。检查Download
目录是否显示,以及与该目录关联的操作按钮是否呈灰色。
权限
Android 11 引入了以下与存储权限相关的更改。
面向任何版本
以下更改在 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 中存储更改的更多信息,请查看以下资料: