如何通过子文件DocumentFile的Uri获取授权根目录并校验权限?
从文件Uri获取已授权根目录Uri的解决方案
针对通过Intent.ACTION_OPEN_DOCUMENT_TREE授权文件夹后,仅持有子文件Uri时,如何追溯到原授权目录Uri的问题,可通过以下原生API实现,无需正则修改Uri或额外保存目录树Uri:
实现逻辑
利用Android原生的DocumentsContract API解析文件的文档ID,递归向上遍历父节点,同时结合ContentResolver的持久化权限列表进行匹配,找到第一个属于已授权范围的目录树Uri。
示例代码(Kotlin)
import android.content.Context import android.net.Uri import android.provider.DocumentsContract fun getAuthorizedRootUri(context: Context, fileUri: Uri): Uri? { val authority = fileUri.authority ?: return null var currentDocId = DocumentsContract.getDocumentId(fileUri) val persistedPermissions = context.contentResolver.persistedUriPermissions while (true) { // 构建当前节点的树Uri,与ACTION_OPEN_DOCUMENT_TREE返回的格式一致 val currentTreeUri = DocumentsContract.buildTreeDocumentUri(authority, currentDocId) // 检查该Uri是否在已持久化的授权列表中 if (persistedPermissions.any { it.uri == currentTreeUri }) { return currentTreeUri } // 获取父节点的文档ID,无父节点则终止循环 val parentDocId = runCatching { DocumentsContract.getParentDocumentId( context.contentResolver, DocumentsContract.buildDocumentUri(authority, currentDocId) ) }.getOrNull() ?: break currentDocId = parentDocId } return null }
关键细节说明
DocumentsContract.getDocumentId():提取文件Uri对应的唯一文档标识,用于后续节点遍历。DocumentsContract.buildTreeDocumentUri():将文档ID转换为树结构Uri,这是ACTION_OPEN_DOCUMENT_TREE返回的标准格式。ContentResolver.persistedUriPermissions:获取应用已保存的所有文档权限Uri,确保找到的是用户主动授权的目录。- 异常捕获:通过
runCatching处理无父节点或权限不足的情况,避免崩溃。
内容的提问来源于stack exchange,提问作者passerby
相关产品推荐
相关产品推荐

