在 Android 中从 File Api 迁移到 Storage Access Framework (SAF)

Posted

技术标签:

【中文标题】在 Android 中从 File Api 迁移到 Storage Access Framework (SAF)【英文标题】:Migration from File Api to Storage Access Framework (SAF) in Android 【发布时间】:2021-07-19 23:49:07 【问题描述】:

由于 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 doc

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

问题2:好吧,当我有来自ACTION_OPEN_DOCUMENT_TREEUri 时,我该如何使用File API

问题 3:这是否意味着我必须复制所有代码才能使用 File API 复制到 Android 9(或使用 requestLegacyExternalStorage 的 10)以及使用 @ 复制到 Android 11+ 987654334@和Uri?

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

更新 经过大量测试DocumentFile 在实践中不适用。可能只针对几个文件。DocumentFile 创建了不必要的复杂源代码,而且很慢related topic。 例如,在通过File API ~350ms 和通过DocumentFile ~2300ms 期间创建 1000 个目录。删除和检查文件是否存在总是很慢。

来自Scoped Storage Recap

太棒了!如果有某种支持库或 Androidx 库来处理文件,那就太好了。

Google 开发者的回答是:

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

【问题讨论】:

intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION 这对 ACTION_GET_DOCUMENT_TREE 毫无意义。最好删除。 I need: Create a file if it does not exist. With File API: 否。为此使用 SAF。有什么问题? Write to file. With File API: 当然不是。如果您有文件的 uri,则打开该 uri 的输出流并写入该流。 Get Uri of parent with child. With File API: 一个人不会试图让父母一开始。 Goal is: keep the code with the File API, 目标错误。使用 SAF。 【参考方案1】:

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

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

【讨论】:

以上是关于在 Android 中从 File Api 迁移到 Storage Access Framework (SAF)的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 3 中从 URLSession 迁移到 Alamofire 4.3,编码问题

Cordova [Android 平台] 从 API 29 迁移到 API 30

如何在 Android Studio 中从 SVN 导入模块

在 Netbeans 中从 ant 迁移到 maven

在 Python 3 中从 dbus 迁移到 GDbus

在 MVC4 RTM 中从 ASP.NET 成员身份迁移到 SimpleMembership