概述

存储访问框架(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 orIntent.FLAG_GRANT_WRITE_URI_PERMISSIONcontentResolver.takePersistableUriPermission(uri, takeFlags)val documentFile = DocumentFile.fromSingleUri(this, uri)val outputStream = contentResolver.openOutputStream(uri) ?: returnval 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

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

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

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

  1. android增加内置存储分区,详解Android10的分区存储机制(Scoped Storage)适配教程

    1. 简介 大家应该都有过这样的体会,手机用着用着里面就充斥着各种不懂的文件夹和文件.甚至是连已经删除的软件的文件夹还存在. 为什么会发生的这样的问题呢? 因为google的缺席,导致android生 ...

  2. android SAF存储访问框架

    Android 4.4(API 级别 19)引入了Storage Access Framework存储访问框架 (SAF),SAF 让用户能够在其所有首选文档存储提供程序中方便地浏览并打开文档.图像以 ...

  3. android文件存储框架,Android 存储访问框架|undefined

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? Android 4.4(API 级别 19)引入了存储访问框架 (SAF).SAF 让用户能够在其所有首选文档存储提供程 ...

  4. Android Native APP开发笔记:文件存储与访问

    文章目录 目的 基础说明 应用专属存储空间 共享存储 其它 总结 目的 APP开发与使用过程中免不了和文件打交道,对于Windows或Linux而言文件的存储与访问操作都很方便,直接通过文件系统路径和 ...

  5. 第21章 DMA—直接存储区访问

    本章参考资料:<STM32F76xxx参考手册>DMA控制器章节. 学习本章时,配合<STM32F76xxx参考手册>DMA控制器章节一起阅读,效果会更佳,特别是涉及到寄存器说 ...

  6. Android存储访问框架的使用

    存储访问框架,简称:SAF, 就是系统文件选择器+文件操作API.先选择文件,在用文件操作API处理文件.系统文件选择器,就和Windows的文件选择框一样. 其实绝大多数app,都不会使用这个东西, ...

  7. 浅谈云上攻防——对象存储服务访问策略评估机制研究

    前言 近些年来,越来越多的IT产业正在向云原生的开发和部署模式转变,这些模式的转变也带来了一些全新的安全挑战. 对象存储作为云原生的一项重要功能,同样面临着一些列安全挑战.但在对象存储所导致的安全问题 ...

  8. 海量数据的存储和访问解决方案

    数据库水平切分的实现原理解析---分库,分表,主从,集群,负载均衡器 第1章  引言 随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计的瓶颈问题.对于一个大型的互联网应用,每天几十亿的PV ...

  9. 《STM32从零开始学习历程》——DMA直接存储区访问实验例程

    <STM32从零开始学习历程>@EnzoReventon DMA-直接存储区访问实验例程 本章节为DMA直接存储区访问的实验例程讲解,以"正点原子"的例程为基础进行讲解 ...

最新文章

  1. extract-text-webpack-plugin 的使用及安装
  2. 编辑器性能测试:Atom 、VS Code、Sublime Text
  3. [翻译]XNA 3.0 Game Programming Recipes之twenty-one
  4. kafkatool 配置_kafka tools的使用
  5. 置springboot自带tomcat的最大连接数和最大并发数
  6. 【测试基础】测试用例的设计方法
  7. SegmentFault Hackathon 文艺复兴
  8. mybatis generator生成example_[Springboot系列] SpringBoot与Mybatis结合
  9. mysql rr和rc_MySQL Transaction--RC和RR区别
  10. python网页提交表单_Html表单——使用python在web页面上显示用户提交的数据
  11. MySQL高级知识(十六)——小表驱动大表
  12. 程序员该如在低代码和无代码开发中抉择?
  13. 优化算法之遗传算法(Genetic Algorithm, GA)
  14. 计算机二级excel经典操作题,计算机二级office经典题库
  15. 数据可视化BI平台--CBoard的使用
  16. 【无人机学习】无人机基础知识
  17. 使用ARKit编写测量应用程序代码:交互和测量
  18. cmd如何远程重启服务器
  19. android简单的自定义涂鸦控件
  20. 京东回归港股不是上岸,刘强东还有更大的杀招!

热门文章

  1. 你管这叫操作系统源码(五)
  2. Docker报错: Error response from daemon: Mounts denied.The path xxx is not shared from OS X and is not
  3. 全方位体验Windows的日历功能
  4. 面试官:来考考你几道常见的MySQL题目吧
  5. webshell一句话木马大全
  6. 怎么获取红米Note 4X的Root权限
  7. rd如何撰写总体设计文档和详细设计文档
  8. 【mysql innodb索引结构B+树】
  9. SQL中除法计算保留整数或几位小数(除法那些事儿!)
  10. matlab错误使用 sum 数据类型无效。第一个参数必须为数值或逻辑值。解决方法