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

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

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

SAF 包括以下内容

  • 文档提供程序:一个内容提供程序,允许存储服务(例如 Google Drive)显示其管理的文件。文档提供程序实现为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 支持浏览文件和目录的更多信息,请参阅有关访问文档和其他文件的指南。

其他资源

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

示例

视频