Android Q 适配

本文深入探讨Android Q引入的沙盒机制,旨在解决应用文件存储混乱问题,确保应用读写文件目录仅与自身相关。文章详细介绍了沙盒机制的工作原理,包括文件保存位置的变化、适配指导以及如何使用MediaStore API和存储访问框架(SAF)来访问不同类型的文件。
  • 应用运行于 Android Q 设备上
  • 启用了 Scoped Storage
    • 应用的目标版本是 Android Q,并且没有将清单文件(AndroidManifest.xml)属性allowExternalStorageSandbox 设置为 false
    • 应用的目标版本是 Android 9(API Level 28) 或更低,并且将清单文件属性 allowExternalStorageSandbox 设置为 true
沙盒机制介绍

如果需要将文件保存在 SD 卡根目录,在 Android Q 之前,可以通过 Environment.getExternalStoragePublicDirectory() 方法获取对应的目录,将文件保存至其中。比如通过 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) 获取到绝对路径为 /sdcard/Pictures 的目录,将图片保存至其中之后,其他应用获取到 READ_EXTERNAL_STORAGE 权限就可以访问到该目录下的所有文件,但从 Android Q 开始,为了解决应用文件存储位置混乱的问题,引入了沙盒机制,该机制确保应用直接读取和写入文件(指通过 File 类操作文件)的目录只和应用相关,对 SD 根目录下文件的操作会被映射到应用的沙盒目录中,比如 上面的Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) 目录在沙盒中对应的典型绝对路径为 /sdcard/Android/sandbox/{packageName}/Pictures,沙盒中的文件目录在应用被卸载时默认会被清空,但应用的卸载提示对话框中会给一个保留应用数据的选项,如果勾选则沙盒中的文件就不会被删除。

适配指导
  1. 保存在 Context.getExternalFilesDir() 中的文件
    无需适配。将应用相关的文件保存在 Context.getExternalFilesDir() 中是 Android 官方推荐的方式,在 Android Q 和低版本的系统上具有一致的行为。应用对该目录下的文件具有完全的读写权限,无需额外申请。该目录的典型绝对路径为 /sdcard/Android/data/{packageName}/files。

  2. 保存在 SD 卡根目录中的文件
    在 Android Q 上,应用无法再直接读取和写入 SD 卡根目录上的文件。如果要访问其他应用创建的文件,根据使用场景的不同有以下两种情况。

2.1 访问图片、音频或视频等媒体文件
使用 MediaStore API。 文件需要存在于以下媒体集合中:

  • MediaStore.Images,对应图片
  • MediaStore.Video,对应视频
  • MediaStore.Audio,对应音频
    下面是两个使用示例。
  1. 读取所有图片路径
    在这里插入图片描述
    如果要读取其他应用创建的文件的话,需要申请并获取到 READ_EXTERNAL_STORAGE 权限,否则只能读取到应用本身创建的文件。

  2. 将图片保存到 Media.Images 中
    在这里插入图片描述
    2.2 其他应用创建的任意文件
    使用存储访问框架(Storage Access Framework,简写为 SAF)。

SAF 是 Android 4.4(Android API Level 19)引入的,用户可以通过易用的标准 UI,以统一的方式在所有应用和提供程序(providers)中浏览文件或访问最近使用的文件。

下面是几个使用示例,更详细的说明请参考官方文档。

  • 检索文档
    在这里插入图片描述
    Intent.CATEGORY_OPENABLE 可对结果进行过滤,以仅显示可以打开的文档(比如图片),intent.setType(“text/plain”) 可做进一步过滤,以仅显示 MIME 类型为纯文本的文档。

  • 处理返回结果
    用户在选择器中选择文档后,系统就会调用 onActivityResult() 方法。指向所选文档的 URI 包含在 data 参数中。使用 getData() 提取 URI。获得 URI 后,即可对文件进行操作。
    在这里插入图片描述

  • 创建新文档
    使用 ACTION_CREATE_DOCUMENT Intent 在文档提供程序中创建新文档,需要为该 Intent 提供一个 MIME 类型和文件名。
    在这里插入图片描述
    创建新文档后,即可在 onActivityResult() 中获取到其 URI,然后继续向其写入内容。

下表总结了应用如何访问外部存储上的文件:

文件位置所需权限访问方式(注)卸载时是否被移除?
应用特有目录getExternalFilesDir()
媒体几何(图片,视频,音频)READ_EXTERNAL_STORAGE 只有访问其他应用时才需要)MediaStore
下载及其他位置存储访问框架

注:可以通过存储访问框架访问上表中的所有文件位置而无需申请任何权限。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值