DocumentProvider — 什么是文档提供程序、创建提供程序和处理文件

作者: IT Sectr 发布日期: 2026-07-10 阅读时间: 6 分钟

DocumentProvider — 是一个抽象的 Android 类,实现了通过 Storage Access Framework 访问文件的内容提供程序。提供程序在 AndroidManifest.xml 中注册,并通过系统选择器向其他应用程序提供文件。根据 Android Developers (2026),DocumentsProvider 需要实现 queryRoots、queryDocument 和 queryChildDocuments 方法,以在文件选择对话框中显示文件结构。

要点

  • DocumentsProvider — 用于在 Android 中创建自定义文件提供程序的抽象类。
  • 存储 — 提供程序可以连接本地文件、云服务和虚拟文档。
  • queryRoots — 必需方法,返回存储的根目录。
  • queryChildDocuments — 返回目录内容,用于在选择器中导航。
  • 注册 在 AndroidManifest 中,使用 android.content.action.DOCUMENTS_PROVIDER intent-filter。

什么是 DocumentProvider?

DocumentsProvider — 是一个基本的 Android 类,继承自 ContentProvider,允许应用程序通过 SAF 系统界面将其文件提供给其他应用程序。提供程序创建了一个虚拟文件系统,用户可以在文档选择对话框中看到它。

每个提供程序将文件组织到 根 (roots) — 顶级入口点。例如,Google Drive 有根 “我的磁盘” 和 “与我共享”。在根内部,提供程序返回一个文档树,其中每个文档都是具有特定 MIME 类型、大小和日期的文件或目录。

DocumentProvider 是 android.provider 包的一部分,自 Android 4.4 (API 19) 起可用。提供程序被云服务、密码管理器、笔记应用程序以及所有以自有格式存储文件的程序使用。

如何创建自定义 DocumentProvider

创建 您自己的 DocumentProvider 始于继承 DocumentsProvider 类并实现四个必需方法。提供程序定义了在选择文件时在 SAF 系统选择器中显示的文件结构。

第一个方法 — queryRoots,返回一个包含 Root.COLUMN_ROOT_ID、Root.COLUMN_TITLE、Root.COLUMN_SUMMARY 和 Root.COLUMN_FLAGS 列的光标。每个根可以支持标志:FLAG_SUPPORTS_CREATE、FLAG_SUPPORTS_SEARCH 和 FLAG_SUPPORTS_IS_CHILD。

第二个必需方法 — queryChildDocuments,返回指定 URI 的子文档。当用户在选择器中打开目录时,将调用此方法。每个文档包含列:Document.COLUMN_DOCUMENT_ID、COLUMN_DISPLAY_NAME、COLUMN_MIME_TYPE、COLUMN_SIZE 和 COLUMN_LAST_MODIFIED。

DocumentsProvider 的必需方法

DocumentsProvider 需要实现四个方法,这些方法形成了选择器的文件结构。没有它们,提供程序将无法工作 — SAF 系统对话框将无法显示文件。

  • queryRoots — 返回存储的根入口点。每个根由光标中的一行表示,包含 ID、名称和图标。
  • queryDocument — 根据其 ID 返回一个文档。用于获取有关特定文件的信息。
  • queryChildDocuments — 返回指定父目录 URI 的子文档。
  • openDocument — 根据 ID 打开文档并返回 ParcelFileDescriptor 以供读取或写入。

此外,还可以实现 createDocument 以创建新文件、deleteDocument 以删除和 renameDocument 以重命名。这些方法需要在根中使用 FLAG_SUPPORTS_CREATE 标志。

在 AndroidManifest 中注册提供程序

DocumentProvider 在 AndroidManifest.xml 中注册为普通的 ContentProvider,带有额外的 intent-filter 和标志。提供程序必须通过 permission 保护免受直接访问 — 建议使用 android:exported="true" 并带有显式 permission。

xml
<provider
    android:name=".provider.CustomDocumentProvider"
    android:authorities="com.example.app.documents"
    android:exported="true"
    android:grantUriPermissions="true"
    android:permission="android.permission.MANAGE_DOCUMENTS">
    <intent-filter>
        <action
            android:name="android.content.action.DOCUMENTS_PROVIDER" />
    </intent-filter>
    <meta-data
        android:name="android.content.documents.roots"
        android:resource="@xml/file_paths" />
</provider>

grantUriPermissions 标志允许 SAF 临时将访问权限委托给调用应用程序。authorities 属性必须是唯一的 — 通常使用带有 .documents 后缀的包名。还建议指定带有 XML 资源的 meta-data 以配置根。

代码示例:实现 DocumentsProvider

实现 DocumentsProvider 需要从 openDocument 方法返回 ParcelFileDescriptor。对于本地文件,使用 ParcelFileDescriptor.open;对于云文件 — 使用带有 Pipe 的 ParcelFileDescriptor.open 进行流式传输。代码必须处理访问错误和文件不存在的情况。

kotlin
class CustomDocumentProvider : DocumentsProvider() {

    override fun queryRoots(): Cursor {
        val matrix = MatrixCursor(Root.COLUMNS)
        matrix.newRow().add(Root.COLUMN_ROOT_ID, "local")
            .add(Root.COLUMN_TITLE, "My Files")
            .add(Root.COLUMN_SUMMARY, "Local documents")
            .add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE)
        return matrix
    }

    override fun openDocument(
        documentId: String, flags: Int, cursor: CancellationSignal?
    ): ParcelFileDescriptor {
        val file = File(context.filesDir, documentId)
        val accessMode = ParcelFileDescriptor.parseMode(flags)
        return ParcelFileDescriptor.open(file, accessMode)
    }
}

处理虚拟文档

DocumentProvider 可以返回 虚拟文件 — 在磁盘上不作为单独文件存在的文档。例如,数据库中的笔记可以表示为虚拟 PDF。为此,使用带有 FLAG_VIRTUAL_DOCUMENT 标志的 MIME 类型,openDocument 在发送前将数据转换为请求的格式。

iOS 中的 DocumentProvider:UIDocumentPickerViewController

iOS 有类似的机制 — UIDocumentPickerViewController,它也提供统一的文件选择界面。然而,在 iOS 中,文档提供程序通过 UIDocumentPickerDelegate 和 Document Provider 类型的应用程序扩展 (App Extensions) 来实现。

与 Android DocumentsProvider 不同,iOS UIDocumentPickerViewController 不需要为本地文件创建自定义提供程序 — 系统选择器默认支持 iCloud Drive 和本地存储。第三方云服务通过 Document Provider extension 注册,使用 Info.plist 键 NSExtensionFileProviderDocumentInterface。

主要区别:在 Android 中,DocumentProvider 通过 SAF Intent 被主动调用,必须自己实现导航。在 iOS 中,UIDocumentPickerViewController 使用内置的系统文件浏览器,提供程序扩展仅负责按需提供内容。

常见问题

Android 中的 DocumentProvider 是什么?

DocumentsProvider — 是一个抽象的 Android 类,用于创建自定义文档提供程序。它允许应用程序通过 Storage Access Framework 系统对话框将其文件提供给其他应用程序。

DocumentsProvider 中有哪些必需的方法?

四个方法是必需的:queryRoots(存储根)、queryDocument(一个文档)、queryChildDocuments(文件夹内容)和 openDocument(打开文件)。没有它们,提供程序将无法工作。

如何在 AndroidManifest 中注册 DocumentProvider?

提供程序注册为 <provider>,带有类名、唯一的 authorities、带有 android.content.action.DOCUMENTS_PROVIDER 操作的 intent-filter 和 grantUriPermissions="true"。

DocumentProvider 与 FileProvider 有何不同?

FileProvider 为您的应用程序的特定文件生成内容 URI。DocumentsProvider 创建一个完整的文件系统,在 SAF 选择器中可见,支持导航和搜索。

如何在 DocumentProvider 中创建虚拟文档?

在 COLUMN_FLAGS 列中使用 FLAG_VIRTUAL_DOCUMENT 标志,以及带有前缀 “vnd.android.document/” 的 MIME 类型。在 openDocument 中,通过带有 Pipe 的 ParcelFileDescriptor 将数据转换为请求的格式。

总结

  • DocumentsProvider — 用于创建与 Storage Access Framework 集成的自定义文件提供程序的基本 Android 类。
  • queryRoots 定义根入口点 — 系统选择器中带有不同文件集的选项卡。
  • queryChildDocuments 和 queryDocument 提供对提供程序虚拟文件系统的导航。
  • openDocument 根据 SAF 请求返回 ParcelFileDescriptor 以供读取或写入文件。
  • 在 AndroidManifest 中注册 需要 DOCUMENTS_PROVIDER intent-filter 和 authorities。
  • 虚拟文档 允许提供在磁盘上不作为单独文件存在的文件 — 例如,数据库笔记作为 PDF。
  • iOS 类似物 — 带有 Document Provider extension 的 UIDocumentPickerViewController,用于云存储。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读