android - 在 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
:好吧,当我有Uri
from时,我该如何使用ACTION_OPEN_DOCUMENT_TREE
?
问题 3 :这是否意味着我必须复制所有代码才能使用and 从 Android 11+ 与and一起工作到 Android 9(或 10 requestLegacyExternalStorage
)?File API
SAF
Uri
目标是:保留代码File API
,但获得用户选择目录的读/写权限。
UPDATE
经过巨大的测试DocumentFile
在实践中并不适用。也许只有几个文件。
DocumentFile
创建不必要的复杂源代码,这是非常缓慢的相关主题。例如,在File API
~350ms 和DocumentFile
~2300ms 期间创建 1000 个目录。删除和检查文件是否存在总是很慢。
惊人的!拥有某种支持库或 Androidx 库来处理文件真的很棒。
谷歌开发者的回答是:
我们正在探索这个选项作为一个实验,敬请期待
解决方案
请注意,不推荐使用startActivityForResult()。而是应使用registerForActivityResult() 。不幸的是,我还没有为这种机制找到任何可用的 Java 示例。甚至 Google 的示例代码仍在使用已弃用的功能。我会很高兴任何提示。
PS:还有一些ActivityResultContracts.OpenDocumentTree()函数可能会有所帮助,但我也找不到如何使用它的示例。
推荐阅读
- apache-kafka - 将 Kafka 1 更新为 Kafka 2
- php - 比嵌套 SELECT 语句 SQL 更好的方法
- r - 在本地使用 R 运行 git 存储库
- .net-core - 如何使用 OpenID 处理 .net 核心中的访问被拒绝?
- c# - 如何有条件地在 RX 中缓冲
- python - 如何修复以下有关获取 url 的错误
- azure-functions - 您的 azure 函数应用将 functions_worker_runtime 设置为节点,而您的本地项目设置为 none
- javascript - 合并和定位两个媒体流
- powershell - 是否可以选择用另一个输出替换 PsExec 错误代码的输出?
- c# - 图表工具提示中的格式数字