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

Android 4.4(API 级别 19)引入了存储访问框架 (SAF)。SAF 允许用户浏览和打开所有首选文档存储提供程序中的文档、图像和其他文件。一个标准的、易于使用的 UI 允许用户以一致的方式跨应用和提供程序浏览文件并访问最近的文件。

云存储或本地存储服务可以通过实现一个 DocumentsProvider 来参与此生态系统,该提供程序封装了它们的服務。需要访问提供程序文档的客户端应用可以通过几行代码与 SAF 集成。

SAF 包括以下内容

  • 文档提供程序:一个内容提供程序,允许存储服务(如 Google 云端硬盘)显示其管理的文件。文档提供程序是作为 DocumentsProvider 类子类的实现。文档提供程序模式基于传统的文件夹层次结构,但您的文档提供程序如何物理存储数据取决于您。Android 平台包含几个内置文档提供程序,如下载、图像和视频。
  • 客户端应用:一个自定义应用,它调用 ACTION_CREATE_DOCUMENTACTION_OPEN_DOCUMENTACTION_OPEN_DOCUMENT_TREE 意图操作,并接收文档提供程序返回的文件。
  • 选择器:一个系统 UI,允许用户从满足客户端应用搜索条件的所有文档提供程序中访问文档。

SAF 提供以下功能

  • 允许用户从所有文档提供程序中浏览内容,而不仅仅是单个应用。
  • 使您的应用能够对文档提供程序拥有的文档进行长期、持久访问。通过这种访问,用户可以在提供程序上添加、编辑、保存和删除文件。
  • 支持多个用户帐户和短暂根,如 USB 存储提供程序,这些提供程序仅在驱动器插入时出现。

概述

SAF 以内容提供程序为中心,该提供程序是 DocumentsProvider 类的一个子类。在文档提供程序中,数据被结构化为传统的文件夹层次结构

data model

图 1. 文档提供程序数据模型。根指向单个文档,然后开始树的扇出。

注意以下几点

  • 每个文档提供程序报告一个或多个,这些根是探索文档树的起点。每个根都有一个唯一的 COLUMN_ROOT_ID,并且它指向一个文档(目录),表示该根下的内容。根是动态设计的,以支持多个帐户、短暂 USB 存储设备或用户登录和注销等用例。
  • 每个根下是一个单个文档。该文档指向 1 到 N 个文档,每个文档依次可以指向 1 到 N 个文档。
  • 每个存储后端通过使用唯一的 COLUMN_DOCUMENT_ID 来引用,从而呈现单个文件和目录。文档 ID 是唯一的,并且在发出后不会更改,因为它们用于在设备重启时持久化 URI 授权。
  • 文档可以是具有特定 MIME 类型的可打开文件,也可以是包含其他文档的目录,其 MIME 类型为 MIME_TYPE_DIR
  • 每个文档都可以具有不同的功能,如 COLUMN_FLAGS 所述。例如,FLAG_SUPPORTS_WRITEFLAG_SUPPORTS_DELETEFLAG_SUPPORTS_THUMBNAIL。相同的 COLUMN_DOCUMENT_ID 可以包含在多个目录中。

控制流程

文档提供程序数据模型基于传统的文件夹层次结构。但是,您可以根据自己的喜好存储数据,只要可以使用 DocumentsProvider API 访问数据即可。例如,您可以使用基于标签的云存储来存储数据。

图 2 显示了照片应用程序如何使用 SAF 访问存储数据。

app

图 2. 存储访问框架流程。

注意以下几点

  • 在 SAF 中,提供程序和客户端不会直接交互。客户端请求与文件的交互权限,即读取、编辑、创建或删除文件。
  • 交互从应用程序(本例中为照片应用程序)触发 ACTION_OPEN_DOCUMENTACTION_CREATE_DOCUMENT 意图开始。意图可以包含过滤器以进一步细化条件,例如“给我所有具有‘image’ MIME 类型的可打开文件”。
  • 一旦意图触发,系统选择器会转到每个已注册的提供程序并向用户显示匹配的内容根目录。
  • 选择器为用户提供了一个标准界面来访问文档,即使底层文档提供程序截然不同。例如,图 2 显示了 Google Drive 提供程序、USB 提供程序和云提供程序。

在图 3 中,用户正在从在图像搜索中打开的选择器中选择“下载”文件夹。选择器还显示了客户端应用程序可用的所有根目录。

Screenshot of folder selection in system picker

图 3. 选择器显示“下载”文件夹被选择为搜索位置。

用户选择“下载”文件夹后,将显示图像。图 4 显示了此过程的结果。用户现在可以使用提供程序和客户端应用程序支持的方式与图像进行交互。

Screenshot of Downloads folder

图 4. 存储在“下载”文件夹中的图像,如系统选择器中所见。

编写客户端应用程序

在 Android 4.3 及更低版本中,如果要让您的应用程序从其他应用程序检索文件,则必须调用意图,例如 ACTION_PICKACTION_GET_CONTENT。然后,用户会选择一个应用程序来选择文件。选定的应用程序必须提供用户界面,供用户浏览和选择可用文件。

在 Android 4.4(API 级别 19)及更高版本中,您还可以选择使用 ACTION_OPEN_DOCUMENT 意图,该意图会显示一个系统控制的选择器 UI,让用户浏览其他应用程序已提供的文件。从这个单个 UI 中,用户可以选择来自任何支持应用程序的文件。

在 Android 5.0(API 级别 21)及更高版本中,您还可以使用 ACTION_OPEN_DOCUMENT_TREE 意图,让用户为客户端应用程序选择目录进行访问。

注意: ACTION_OPEN_DOCUMENT 并不是 ACTION_GET_CONTENT 的替代品。您使用哪个取决于应用程序的需要。

  • 如果要让应用程序读取或导入数据,请使用 ACTION_GET_CONTENT。使用这种方法,应用程序会导入数据的副本,例如图像文件。
  • 如果要让应用程序长期持续访问文档提供程序拥有的文档,请使用 ACTION_OPEN_DOCUMENT。例如,一个照片编辑应用程序可以允许用户编辑存储在文档提供程序中的图像。

有关如何使用系统选择器 UI 支持浏览文件和目录的更多信息,请参阅有关 访问文档和其他文件 的指南。

其他资源

有关文档提供程序的更多信息,请利用以下资源。

示例

视频