You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取DOCUMENT_TREE权限后访问被拒及READ_EXTERNAL_STORAGE权限咨询

问题解答

1. 关于READ_EXTERNAL_STORAGE权限的疑问

  • 访问通过DOCUMENT_TREE选择的特定文件夹,不需要申请READ_EXTERNAL_STORAGE权限。从Android 10(API 29)开始,存储访问框架(SAF)的设计就是让用户主动授权访问指定目录,完全不需要依赖传统的外部存储权限。
  • 如果你的状态保存类应用申请了READ_EXTERNAL_STORAGE,Play Console大概率会拒绝上架。因为该权限允许访问整个外部存储,而你的功能仅需访问用户指定的特定目录,属于过度申请权限,违反Google的权限使用规范。建议仅通过SAF实现功能,不要申请该权限。

2. 通过DOCUMENT_TREE正确获取权限并避免访问被拒

要解决访问被拒的问题,核心是正确使用SAF的权限机制,并且不要尝试获取本地文件路径,直接通过ContentResolver操作文件:

步骤1:持久化DOCUMENT_TREE权限

用户通过SAF选择目录后,必须调用takePersistableUriPermission保存权限,这样应用重启后仍能访问该目录:

// 假设通过ACTION_OPEN_DOCUMENT_TREE获取到目标目录uri
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
contentResolver.takePersistableUriPermission(uri, takeFlags)

步骤2:通过流操作复制文件,避免使用本地路径

不要试图将DOCUMENT_TREE的URI转换为本地文件路径(这在很多场景下不可行,且会触发权限问题),直接用ContentResolver打开输入输出流来复制视频:

// 源视频文件URI(来自DOCUMENT_TREE目录下)
val sourceUri = ... 
// 目标文件URI(可通过SAF获取目标目录权限后创建,或使用应用私有目录)
val targetUri = ...

contentResolver.openInputStream(sourceUri)?.use { inputStream ->
    contentResolver.openOutputStream(targetUri)?.use { outputStream ->
        inputStream.copyTo(outputStream)
    }
}

步骤3:确保目标目录的访问权限

如果是复制到外部其他文件夹,同样需要通过SAF获取该目标目录的访问权限;若复制到应用私有目录(如getExternalFilesDir()下的路径),则无需额外权限。

内容的提问来源于stack exchange,提问作者Deepesh kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:00:46