Android11适配

 一、分区存储

1.背景

Android 11 进一步增强了平台功能,为外部存储设备上的应用和用户数据提供了更好的保护。作为这项工作的一部分,平台引入了进一步的改进,以简化向分区存储的转换。
为了让用户更好地控制自己的文件,保护用户隐私数据,并限制文件混乱情况,Android 11在分区存储基础上限制了应用访问其他应用的文件。

分区存储将存储空间分为两部分:

●  公共目录:Downloads、Documents、Pictures 、DCIM、Movies、Music、Ringtones等

    ■ 公共目录的文件在App卸载后,不会删除
    ■ 可以通过SAF、MediaStore接口访问
    ■ 拥有权限,也能通过路径直接访问
●  应用专属目录
    ■ 应用专属目录只能自己直接访问
    ■ App卸载,数据会清除。

2.兼容影响

当您将应用更新为以 Android 11 为目标平台后,您将无法使用requestLegacyExternalStorage,而且也没有其他标记可以提供停用分区存储。
分区存储对于App访问存储方式、App数据存放以及App间数据共享,都产生很大影响。
而Environment.getExternalStorageDirectory() 在 API Level 29 开始已被弃用,开发者应迁移至 Context#getExternalFilesDir(String), MediaStore, 或Intent#ACTION_OPEN_DOCUMENT。

二、适配

1.应用targetSdkVersion

应用targetSdkVersion >= 30,都会强制打开分区存储,同时requestLegacyExternalStorage将会无效。如果您需要对已安装的应用进行适配分区存储的数据迁移,则可以在应用更新到目标平台为Android 11版本后仍暂时保留原有的存储模式。请在应用的manifest中设置preserveLegacyExternalStorage属性为true,应用更新到android 11可以保留存储继承模式。

2.应用私有目录访问

对于运行在Android 11的应用,无论targetSdkVersion是什么都无法访问Emulated存储中的其他应用私有目录(Android/data)。SAF(Storage Access Framework)同样也禁止访问应用私有目录。
某些应用的核心用例需要访问大量的文件,如文件管理操作或备份和恢复操作。这些应用可通过执行以下操作获取“所有文件访问权限”:

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

●  注意:获得此权限的应用仍然无法访问属于其他应用的应用专用目录。这些目录在存储卷上显示为 Android/data/ 的子目录。

3. 直接路径访问

注意:使用直接路径和原生库保存媒体文件时,应用的性能会略有下降。请尽可能改用MediaStore API。

数据和文件存储概览  |  Android 开发者  |  Android Developers
Android 11 中的存储机制更新  |  Android 开发者  |  Android Developers

4.App运行模式

在Android 11版本上,系统会根据App targetSdkVersion决定运行模式:
●  App targetSdkVersion >= 30,默认为分区存储,并且无法取消。

●  App targetSdkVersion < 29,默认为分区存储,可通过requestLegacyExternalStorage更改

应用可以通过AndroidManifest.xml设置requestLegacyExternalStorage, 选择对应的方式:
 


●  App targetSdkVersion < 29,声明了READ_EXTERNAL_STORAGE,默认Legacy Mode
●  App在下列条件都成立时
   ■  声明 MANAGE_EXTERNAL_STORAGE 权限。
   ■  使用 ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION intent 操作将用户引导至一个系统设置页面,在该页面上,用户可以为您的应用启用以下选项:授予所有文件的管理权限。
App拥有外置存储空间Read、Write权限。但是通过Environment.isExternalStorageLegacy接口判断,返回不一定是Legacy Mode。
判断当前App运行什么模式,可以通过这个API判断:
Environment.isExternalStorageLegacy() (added in api 29);

true表示以传统的兼容方式运行,false表示以分区存储运行

5. 读写公共目录

App启动分区存储后,只能直接访问自身专属目录,所以Android 11,提供了两种访问公共目录的方法(通过MediaStore定义的Uri、通过SAF接口)

5.1通过MediaStore定义的Uri

MediaStore提供了下列几种类型的访问Uri,通过查找对应Uri数据,达到访问的目的。
下列每种类型又分为三种Uri,Internal、External、可移动存储:

●Audio
   ■  Internal: MediaStore.Audio.Media.INTERNAL_CONTENT_URI

       content://media/internal/audio/media。

   ■  External: MediaStore.Audio.Media.EXTERNAL_CONTENT_URI

       content://media/external/audio/media。

   ■  可移动存储: MediaStore.Audio.Media.getContentUri

       content://media/<volumeName>/audio/media。
●  Video
   ■    Internal: MediaStore.Video.Media.INTERNAL_CONTENT_URI
         content://media/internal/video/media。
   ■    External: MediaStore.Video.Media.EXTERNAL_CONTENT_URI
         content://media/external/video/media。
   ■    可移动存储: MediaStore.Video.Media.getContentUri
         content://media/<volumeName>/video/media。
●  Image
   ■    Internal: MediaStore.Images.Media.INTERNAL_CONTENT_URI
         content://media/internal/images/media。
   ■    External: MediaStore.Images.Media.EXTERNAL_CONTENT_URI
         content://media/external/images/media。
   ■    可移动存储: MediaStore.Images.Media.getContentUri
         content://media/<volumeName>/images/media。
●  File
   ■    MediaStore. Files.Media.getContentUri
         content://media/<volumeName>/file。
●  Downloads
   ■    Internal: MediaStore.Downloads.INTERNAL_CONTENT_URI
         content://media/internal/downloads。
   ■    External: MediaStore.Downloads.EXTERNAL_CONTENT_URI
content://media/external/downloads。
   ■    可移动存储: MediaStore.Downloads.getContentUri
content://media/<volumeName>/downloads。

5.2.通过SAF接口

SAF,即Storage Access Framework,通过选择不同的DocumentsProvider,提供给用户打开、浏览文件。在Android 11上,无法通过SAF选择外部存储器External Storage根目录、Downloads目录以及App专属目录(Android/data、Android/obb)。

Android默认提供了下列DocumentsProvider:
MediaDocumentsProvider、ExternalStorageProvider、 DownloadStorageProvider。
他们之间差异是:

6.访问应用的专属目录--私有目录

访问应用专属目录分为两种情况,第一是访问App自身专属目录,第二是访问其他App的专属目录。

6.1.App自身专属目录

   Android 11获取应用专属目录
   ■  获取Media接口:getExternalMediaDirs
   ■  获取Cache接口:getExternalCacheDirs
   ■  获取Obb接口:getObbDirs
   ■  获取Data接口:getExternalFilesDirs
   应用专属目录App本身可以直接访问。

6.2.其他App的专属目录

Android 11,App无法访问其他App的专属目录(Android/data)。如果需要访问其他应用专属目录数据,需要被访问者按照下列方法来提供:
6.2.1.通过SAF文件
●  共享App自定义DocumentsProvider
    App自定义DocumentsProvider需要做以下步骤:
    a)指定DocumentsProvider

   b)DocumentsProvider实现基本接口

●  访问App通过ACTION_OPEN_DOCUMENT,启动浏览

三、文件访问限制

              如果您的应用以 Android 11 为目标平台并使用存储访问框架 (SAF),则您无法再使用ACTION_OPEN_DOCUMENT和ACTION_OPEN_DOCUMENT_TREE操作访问某些目录,具体限制如下:

1.访问目录

 您无法再使用ACTION_OPEN_DOCUMENT_TREE 操作来请求访问以下目录:
Downloads根目录。
内部存储根目录

2. 访问文件

您无法再使用 ACTION_OPEN_DOCUMENT_TREE 或 ACTION_OPEN_DOCUMENT操作来请求用户从以下目录中选择单独的文件:
Android/data/ 目录及其所有子目录。
Android/obb/ 目录及其所有子目录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值