Android11(30)/Android10(29)分区存储-存储访问框架(SAF)

在这里插入图片描述

概述

存储访问框架(SAF)是在Android 4.4(API 级别 19)引入的。借助 SAF,用户可轻松打开文档、图像及其他文件。

存储访问框架包含三部分:

  • 文档提供程序 — 文档提供程序以 DocumentsProvider 类的子类形式实现。Android 平台包含有内置文档提供程序,如 Downloads、Images 和 Videos。
  • 客户端应用 — 应用可以通过发送 ACTION_OPEN_DOCUMENTACTION_CREATE_DOCUMENT 的Intent来启动选择器,并可以接收文档提供程序返回的文件。
  • 选择器 — 系统界面,可让用户选择客户端应用期望格式的文档。

三者的关系如下图
在这里插入图片描述

客户端可以通过以下的Action来启动系统选择器,让用户做相关的操作:

  • ACTION_OPEN_DOCUMENT 打开用户选择的文件
  • ACTION_CREATE_DOCUMENT 在用户选择的位置创建文件
  • ACTION_OPEN_DOCUMENT_TREE 访问某个目录,在Android5.0(API 级别 21)首次引入。

创建应用并写入内容

我们以创建一个jpg文件写入内容为例,来看看如何使用SAF。

  • 通过 ACTION_CREATE_DOCUMENT的Intent启动系统选择器
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {    addCategory(Intent.CATEGORY_OPENABLE)    type = "image/jpeg"    putExtra(Intent.EXTRA_TITLE, "invoice.jpg")}startActivityForResult(intent, REQUEST_CODE_CREATE_FILE)
  • 用户选择某个目录创建invoice.jpg文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OlrfzaR2-1600607710842)(/Volumes/work/Android分区存储/Android发布文章/SAF/create_document.png)]

  • onActivityResult中写入内容
REQUEST_CODE_CREATE_FILE -> {
    val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or
            Intent.FLAG_GRANT_WRITE_URI_PERMISSION
    contentResolver.takePersistableUriPermission(uri, takeFlags)
    val documentFile = DocumentFile.fromSingleUri(this, uri)
    val outputStream = contentResolver.openOutputStream(uri) ?: return
    val inputStream = this.assets.open("friends.jpg")
    try {
        outputStream.use { outputStream ->
            inputStream.use { inputStream ->
                val byteArray = ByteArray(1024)
                while (true) {
                    val readCount = inputStream.read(byteArray)
                    if (readCount == -1) {
                        break
                    }
                    outputStream.write(byteArray, 0, readCount)
                }
            }
        }
    } catch (e: IOException) {
        Log.e("wfeii", "$e")
    }
}

DocumentFile

对于返回的文件或者目录我们可以使用DocumentFile来操作,DocumentFile提供了三个静态方法,用于获取DocumentFile对象,分别是:

  • //根据File获取DocumentFile
    public static DocumentFile fromFile(@NonNull File file)
    
  • //根据Uri获取目录的DocumentFile
    public static DocumentFile fromTreeUri(@NonNull Context context, @NonNull Uri treeUri)
    
  • //根据Uri获取文件的DocumentFile
    public static DocumentFile fromSingleUri(@NonNull Context context, @NonNull Uri singleUri)
    

DocumentFile提供了很多实用的接口,比如获取文件名等等,方便我们的操作。

引入方式:

  • //androidx
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    
  • //非androidx
    implementation 'com.android.support:support-v4:28.0.0'
    

SAF针对选择文件是很方便的,以前我们使用它的时候,是先获取其对应File的目录再来做出来,而Android11中非公共目录下文件是不能直接操作的,我们可以复制我们自己的目录下,然后再做操作。

参考文档

Android 11 中的存储机制更新

访问应用专属文件

共享存储空间

使用存储访问框架打开文件

管理存储的所有文件

FileProvider的使用

代码地址:https://github.com/wfeii/Android11

限于个人水平,有错误请指出,大家共同学习进步!

扫码关注公众号,查看更多内容。
img

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值