使用Android DocumentFile API时如何正确获取并保存子文件夹内容列表
DocumentFile子文件夹URI持久化问题解决方案
问题原因
你拿到的子文件夹URI属于文档URI(document URI),而DocumentFile.fromTreeUri()仅支持传入树URI(tree URI),传入文档URI时系统会自动解析回你最初授权的根树URI,因此会返回父文件夹对象。
正确处理方案
- 第一步:先为初始选中的父文件夹树URI申请持久化权限,避免重启应用后权限失效:
val takeFlags = intent.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) contentResolver.takePersistableUriPermission(parentTreeUri, takeFlags)
- 第二步:根据适配需求选择对应的URI保存方案:
方案1:API 26及以上版本,生成子树URI保存
通过DocumentsContract.buildDocumentUriUsingTree()方法,基于已授权的父树URI和子文件夹的文档ID生成可被fromTreeUri识别的子树URI,后续直接调用DocumentFile.fromTreeUri()即可正常解析:
// 遍历拿到子文件夹的DocumentFile对象后,生成子树URI val childDocId = DocumentsContract.getDocumentId(childFolderDoc.uri) val childTreeUri = DocumentsContract.buildDocumentUriUsingTree(parentTreeUri, childDocId) // 保存childTreeUri.toString()到本地即可
后续使用时直接调用DocumentFile.fromTreeUri(context, Uri.parse(savedChildTreeUri))就能拿到正确的子文件夹对象。
方案2:全版本兼容,直接保存文档URI
不需要生成子树URI,直接保存子文件夹的原始文档URI,后续使用时调用DocumentFile.fromSingleUri()解析即可,只要你已经持有父路径的持久化权限,该对象可正常调用listFiles()、createFile()等所有操作方法:
// 直接保存childFolderDoc.uri.toString()到本地 // 后续使用 val childFolder = DocumentFile.fromSingleUri(context, Uri.parse(savedChildDocUri))
注意事项
保存URI时直接将URI对象转为String存储到SharedPreferences、本地数据库等持久化存储即可,使用时再通过Uri.parse()转回URI对象即可正常使用。
内容的提问来源于stack exchange,提问作者user1026605
相关产品推荐
相关产品推荐

