Android API Guides 之 App Components(15) - Content Providers - Storage Access Framework

Android 4.4引入了Storage Access Framework (SAF),使得用户可以方便地浏览和打开来自各种文档存储服务的文件。SAF提供了一个统一的UI,允许用户在不同的应用和提供商中一致地浏览文件,并提供了创建、编辑、保存和删除文件的能力。它包括文档提供商(作为`DocumentsProvider`子类的内容提供者)和客户端应用。客户端应用通过发送`ACTION_OPEN_DOCUMENT`或`ACTION_CREATE_DOCUMENT`意图来访问文件,而系统会显示一个选择器供用户从所有匹配的提供商中选择文件。
摘要由CSDN通过智能技术生成

Storage Access Framework

Android 4.4 (API level 19) introduces the Storage Access Framework (SAF). The SAF makes it simple for users to browse and open documents, images, and other files across all of their their preferred document storage providers. A standard, easy-to-use UI lets users browse files and access recents in a consistent way across apps and providers.

Cloud or local storage services can participate in this ecosystem by implementing a DocumentsProvider that encapsulates their services. Client apps that need access to a provider's documents can integrate with the SAF with just a few lines of code.

The SAF includes the following:

  • Document provider—A content provider that allows a storage service (such as Google Drive) to reveal the files it manages. A document provider is implemented as a subclass of theDocumentsProvider class. The document-provider schema is based on a traditional file hierarchy, though how your document provider physically stores data is up to you. The Android platform includes several built-in document providers, such as Downloads, Images, and Videos.
  • Client app—A custom app that invokes theACTION_OPEN_DOCUMENT and/or ACTION_CREATE_DOCUMENT intent and receives the files returned by document providers.
  • Picker—A system UI that lets users access documents from all document providers that satisfy the client app's search criteria.

Some of the features offered by the SAF are as follows:

  • Lets users browse content from all document providers, not just a single app.
  • Makes it possible for your app to have long term, persistent access to documents owned by a document provider. Through this access users can add, edit, save, and delete files on the provider.
  • Supports multiple user accounts and transient roots such as USB storage providers, which only appear if the drive is plugged in.

Overview


The SAF centers around a content provider that is a subclass of the DocumentsProvider class. Within adocument provider, data is structured as a traditional file hierarchy:

data model

Figure 1. Document provider data model. A Root points to a single Document, which then starts the fan-out of the entire tree.

Note the following:

  • Each document provider reports one or more "roots" which are starting points into exploring a tree of documents. Each root has a unique COLUMN_ROOT_ID, and it points to a document (a directory) representing the contents under that root. Roots are dynamic by design to support use cases like multiple accounts, transient USB storage devices, or user login/log out.
  • Under each root is a single document. That document points to 1 to N documents, each of which in turn can point to 1 to N documents.
  • Each storage backend surfaces individual files and directories by referencing them with a uniqueCOLUMN_DOCUMENT_ID. Document IDs must be unique and not change once issued, since they are used for persistent URI grants across device reboots.
  • Documents can be either an openable file (with a specific MIME type), or a directory containing additional documents (with the MIME_TYPE_DIR MIME type).
  • Each document can have different capabilities, as described by COLUMN_FLAGS. For example,FLAG_SUPPORTS_WRITEFLAG_SUPPORTS_DELETE, and FLAG_SUPPORTS_THUMBNAIL. The sameCOLUMN_DOCUMENT_ID can be included in multiple directories.

Control Flow


As stated above, the document provider data model is based on a traditional file hierarchy. However, you can physically store your data however you like, as long as it can be accessed through the DocumentsProviderAPI. For example, you could use tag-based cloud storage for your data.

Figure 2 shows an example of how a photo app might use the SAF to access stored data:

app

Figure 2. Storage Access Framework Flow

Note the following:

  • In the SAF, providers and clients don't interact directly. A client requests permission to interact with files (that is, to read, edit, create, or delete files).
  • The interaction starts when an application (in this example, a photo app) fires the intentACTION_OPEN_DOCUMENT or ACTION_CREATE_DOCUMENT. The intent may include filters to further refine the criteria—for example, "give me all openable files that have the 'image' MIME type."
  • Once the intent fires, the system picker goes to each registered provider and shows the user the matching content roots.
  • The picker gives users a standard interface for accessing documents, even though the underlying document providers may be very different. For example, figure 2 shows a Google Drive provider, a USB provider, and a cloud provider.

Figure 3 shows a picker in which a user searching for images has selected a Google Drive account:

picker

Figure 3. Picker

When the user selects Google Drive the images are displayed, as shown in figure 4. From that point on, the user can interact with them in whatever ways are supported by the provider and client app.

picker

Figure 4. Images

Writing a Client App


On Android 4.3 and lower, if you want your app to retrieve a file from another app, it must invoke an intent such as ACTION_PICK or ACTION_GET_CONTENT. The user must then select a single app from which to pick a file and the selected app must provide a user interface for the user to browse and pick from the available files.

On Android 4.4 and higher, you have the additional option of using the ACTION_OPEN_DOCUMENT intent, which displays a picker UI controlled by the system that allows the user to browse all files that other apps have made available. From this single UI, the user can pick a file from any of the supported apps.

ACTION_OPEN_DOCUMENT is not intended to be a replacement for ACTION_GET_CONTENT. The one you should use depends on the needs of your app:

  • Use ACTION_GET_CONTENT if you want your app to simply read/import data. With this approach, the app imports a copy of the data, such as an image file.
  • Use ACTION_OPEN_DOCUMENT if you want your app to have long term, persistent access to documents owned by a document provider. An example would be a photo-editing app that lets users edit images stored in a document provider.

This section describes how to write client apps based on the ACTION_OPEN_DOCUMENT andACTION_CREATE_DOCUMENT intents.

The following snippet uses ACTION_OPEN_DOCUMENT to search for document providers that contain image files:

private static final int READ_REQUEST_CODE = 42;
...
/**
 * Fires an intent to spin up the "file chooser" UI and select an image.
 */
public void performFileSearch() {
    

    // ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file
    // browser.
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);

    // Filter to only show results that can be "opened", such as a
    // file (as opposed to a list of contacts or timezones)
    intent.addCategory(Intent.CATEGORY_OPENABLE);

    // Filter to show only images, using the image MIME data type.
    // If one wanted to search for ogg vorbis files, the type would be "audio/ogg".
    // To search for all documents available via installed storage providers,
    // it would be "*/*".
    intent.setType("image/*");

    startActivityForResult(intent, READ_REQUEST_CODE);
}

Note the following:

  • When the app fires the ACTION_OPEN_DOCUMENT intent, it launches a picker that displays all matching document providers.
  • Adding the category CATEGORY_OPENABLE to the intent filters the results to display only documents that can be opened, such as image files.
  • The statement intent.setType("image/*") further filters to display only documents that have the image MIME data type.

Process Results

Once the user selects a document in the picker, onActivityResult() gets called. The URI that points to the selected document is contained in the resultData parameter. Extract the URI using getData(). Once you have it, you can use it to retrieve the document the user wants. For example:

@Override
public void onActivityResult(int requestCode, int resultCode,
        Intent resultData) {
    

    // The ACTION_OPEN_DOCUMENT intent was sent with the request code
    // READ_REQUEST_CODE. 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值