首页 > 解决方案 > 在 Android 中从 File Api 迁移到 Storage Access Framework (SAF)

问题描述

由于 Android 11 和范围存储,我必须开始使用存储访问框架 (SAF),但我有很多源代码可以使用File API. 问题 1:我是否必须重写所有内容才能使用DocumentFile

伪用例:
用户创建并选择自己的目录,系统返回Uri

//Start pick a directory
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)   
startActivityForResult(intent, requestCode)

...

onActivityResult {
    //check requestCode + resultCode
    ...
    //get Uri
    val selectedDir = data.getData();
    if (selectedDir == null) {
        return;
    }
    //take persist permission for later use
    getContentResolver().takePersistableUriPermission(selectedDir, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}

现在我拥有Uri由具有读/写持久权限的用户选择的文件夹。

来自安卓文档

为了帮助您的应用更顺畅地与第三方媒体库配合使用,Android 11 允许您使用除 MediaStore API 之外的 API 来使用直接文件路径从共享存储访问媒体文件。这些 API 包括:
文件 API。
本机库,例如 fopen()。

问题 2File API :好吧,当我有Urifrom时,我该如何使用ACTION_OPEN_DOCUMENT_TREE

问题 3 :这是否意味着我必须复制所有代码才能使用and 从 Android 11+ 与and一起工作到 Android 9(或 10 requestLegacyExternalStorage)?File APISAFUri

目标是:保留代码File API,但获得用户选择目录的读/写权限。

UPDATE 经过巨大的测试DocumentFile在实践中并不适用。也许只有几个文件。
DocumentFile创建不必要的复杂源代码,这是非常缓慢的相关主题。例如,在File API~350ms 和DocumentFile~2300ms 期间创建 1000 个目录。删除和检查文件是否存在总是很慢。

范围存储回顾

惊人的!拥有某种支持库或 Androidx 库来处理文件真的很棒。

谷歌开发者的回答是:

我们正在探索这个选项作为一个实验,敬请期待

标签: androidandroid-fileandroid-fileproviderstorage-access-framework

解决方案


请注意,不推荐使用startActivityForResult()。而是应使用registerForActivityResult() 。不幸的是,我还没有为这种机制找到任何可用的 Java 示例。甚至 Google 的示例代码仍在使用已弃用的功能。我会很高兴任何提示。

PS:还有一些ActivityResultContracts.OpenDocumentTree()函数可能会有所帮助,但我也找不到如何使用它的示例。


推荐阅读