Storage Access Framework:什么是它,工作原理及文件访问

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

Storage Access Framework — 是一个 Android 框架,用于通过系统选择对话框安全访问文件和文档。应用无需请求广泛的存储读取权限,而是获取用户所选文件的 URI 链接。根据 Android Developers (2026),SAF 通过 DocumentProvider 支持本地存储、Google Drive 和 Dropbox 云服务。该框架在 Android 4.4 中引入,并从 Android 10 开始成为文档处理的标准。

要点

  • SAF — 用于通过系统对话框选择文件而无需广泛权限的 Android 框架。
  • URI 链接 取代直接文件路径:应用通过 content URI 处理文件。
  • Persistent permissions 允许在应用重启后保持对文件的访问。
  • DocumentProvider 扩展 SAF 以访问云存储和自定义存储。
  • Android 10 使 SAF 成为访问应用沙箱外文件的必需方式。

什么是 Storage Access Framework?

Storage Access Framework — 是 Android SDK 的一部分,提供通过系统对话框选择和创建文档的统一界面。SAF 抽象了文件的物理位置:应用不知道文件从哪里读取 — 从本地磁盘、Google Drive 还是 Dropbox。

SAF 的架构包括三个组件:发起请求的客户端应用、标准文件选择对话框 — 系统选择器,以及实现特定存储文件访问的DocumentProvider 内容提供者。用户无论数据来源如何,都能看到统一的界面。

SAF 从 Android 4.4 (API 19) 开始可用。最初该框架仅支持文档,但在 Android 5.0 中通过 ACTION_OPEN_DOCUMENT_TREE 添加了对目录的支持。从 Android 10 开始,SAF 成为访问应用专属存储外任何文件的推荐方式。

SAF 如何工作:系统选择器和 URI

SAF 通过 Intent 使用 ACTION_OPEN_DOCUMENT 动作启动系统文件选择对话框。用户可以看到可用来源列表:内部存储、Google Drive、Dropbox 和其他注册的提供者。选择文件后,系统返回一个 content URI 并附带临时访问权限。

Content URI 的格式为 content://com.android.externalstorage.documents/document/primary/Download/file.pdf。与 file:// URI 不同,content URI 不透露文件的真实路径,并通过 DocumentProvider 工作。应用通过 ContentResolver.openInputStream 基于获取的 URI 读取文件。

系统选择器自动支持按 MIME 类型搜索、排序和过滤文件。开发者通过 Intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("application/pdf", "image/*")) 指定需要的类型,选择器仅显示相关文件。

URI 访问的生命周期

默认情况下,URI 在应用重启或设备重启前有效。对于长期访问,应用请求 takePersistableUriPermission — 这允许在后续启动时读取文件,而无需通过对话框重新选择。

ACTION_OPEN_DOCUMENT 和 ACTION_CREATE_DOCUMENT

SAF 提供三种主要文件操作:打开、创建和选择文件夹树。ACTION_OPEN_DOCUMENT 打开系统选择器以选择现有文件。ACTION_CREATE_DOCUMENT 创建新文件 — 用户在对话框中输入名称,应用获取 URI 进行写入。

ACTION_OPEN_DOCUMENT_TREE 允许选择整个目录并访问其中的所有文件。它在文件管理器、备份和同步应用中使用。应用获取目录的 URI,并可以通过 DocumentFile 递归枚举内容。

动作目的标志
ACTION_OPEN_DOCUMENT选择现有文件READ_FLAG
ACTION_CREATE_DOCUMENT创建新文件WRITE_FLAG
ACTION_OPEN_DOCUMENT_TREE选择目录READ + WRITE

对于每个动作,MIME 类型通过 EXTRA_MIME_TYPES 指定。可以指定多个类型:"application/pdf","image/*","text/plain"。如果未指定类型,选择器显示所有文件。

Persistent URI permissions

Persistent URI permissions — 是一种 SAF 机制,允许在当前会话结束后保持对文件的访问。没有此标志,URI 仅在应用重启前有效。应用请求 FLAG_GRANT_PERSISTABLE_URI_PERMISSION 标志以及 READ 和 WRITE 标志。

为保存权限,使用 ContentResolver.takePersistableUriPermission 方法。系统将 URI 存储在特殊注册表中,并在应用下次启动时恢复访问。要检查应用是否具有对 URI 的持久访问,使用 ContentResolver.persistedUriPermissions

用户可以通过设置 → 应用 → 权限撤销已保存的权限。应用应处理文件访问意外消失的场景。建议在开始工作前通过 ContentResolver.openInputStream 检查访问权限,并正确处理 SecurityException。

代码示例:通过 SAF 选择文件

SAF 通过标准 Intent 启动。代码最小化:创建一个带有 ACTION_OPEN_DOCUMENT 的 Intent,指定 MIME 类型,并通过 ActivityResultContracts.StartActivityForResult 启动。选择文件后,回调在 data.data 中获取 URI,然后用于读取。

kotlin
val pickFile = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    result.data?.data?.let { uri ->
        val inputStream = contentResolver?.openInputStream(uri)
        // read from inputStream
    }
}

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
    addCategory(Intent.CATEGORY_OPENABLE)
    setType("application/pdf")
    putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
pickFile.launch(intent)

通过 ACTION_CREATE_DOCUMENT 创建文件

要写入新文件,请使用 ACTION_CREATE_DOCUMENT。Intent 接受 MIME 类型并通过 EXTRA_TITLE 接受文件名。选择文件夹并确认后,用户返回一个 URI,应用通过 ContentResolver.openOutputStream 将数据写入其中。系统会自动在选定位置创建文件。

SAF vs READ_EXTERNAL_STORAGE

SAF 与传统 READ_EXTERNAL_STORAGE 的区别在于安全性的根本不同方法。"一次性"请求整个存储访问,而是仅请求特定文件的访问。这最小化了攻击面并提高了用户信任。

READ_EXTERNAL_STORAGE 允许访问设备上的所有文件,包括其他应用的照片和文档。在 Android 10+ 上,这种方法受到限制。相反,SAF 仅提供对用户所选文件的访问,并要求每个文件明确确认。批量处理媒体请使用 MediaStore,单个文档使用 SAF。

SAF 的主要缺点是需要单独选择每个文件。对于批量操作(备份、文件夹同步),使用 ACTION_OPEN_DOCUMENT_TREE,它提供对所选目录中所有文件的访问。解决方案取决于场景:SAF 适用于用户选择,MediaStore 适用于对媒体的编程访问。

常见问题

Android 中的 Storage Access Framework 是什么?

Storage Access Framework — 是一个 Android 框架,用于通过系统选择对话框安全访问文件。应用无需请求广泛的存储读取权限即可获取所选文件的 content URI。

如何通过 SAF 打开文件?

创建带有 ACTION_OPEN_DOCUMENT 的 Intent,通过 setType 指定 MIME 类型,并通过 ActivityResultContracts 启动。在回调中从 data.data 获取 URI,并通过 ContentResolver.openInputStream 读取。

什么是 persistent URI permissions?

Persistent URI permissions — 是在应用重启后保持 URI 访问的机制。通过 FLAG_GRANT_PERSISTABLE_URI_PERMISSION 标志和 takePersistableUriPermission 方法请求。

SAF 支持哪些 MIME 类型?

SAF 支持任何 MIME 类型:application/pdfimage/*text/plainapplication/zip 等。类型通过 Intent.putExtra 与 EXTRA_MIME_TYPES 数组指定。

SAF 与 MediaStore 有何不同?

SAF 旨在让用户通过系统对话框选择单个文件。MediaStore 通过媒体数据库提供对设备所有媒体文件的编程访问,无需用户参与。

总结

  • Storage Access Framework — Android 框架,用于通过系统选择器安全访问文件,无需广泛权限。
  • Content URI 取代文件路径:应用通过 DocumentProvider 而非直接 file:// 链接处理文件。
  • ACTION_OPEN_DOCUMENT 打开现有文件,ACTION_CREATE_DOCUMENT 创建新文件,ACTION_OPEN_DOCUMENT_TREE 选择文件夹。
  • Persistent permissions 通过 takePersistableUriPermission 在应用重启后保持 URI 访问。
  • Android 10 使 SAF 成为访问应用专属存储外文件的必需方式,限制了 READ_EXTERNAL_STORAGE。
  • DocumentProvider 扩展 SAF 以集成云存储和自定义存储。
  • 选择 SAF 和 MediaStore 取决于场景:SAF — 用于用户选择,MediaStore — 用于对媒体的编程访问。

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

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

讨论项目

另请阅读