使用ACTION_OPEN_DOCUMENT_TREE选文件夹后listFiles()始终返回null如何解决
问题原因
- 从Android 10(API 29)开始系统默认开启分区存储,普通应用无法直接通过
File类访问公共目录、其他应用目录,就算你通过Uri转换拿到了真实文件路径,File相关API也没有访问权限,调用listFiles()自然返回null。 - 所有Uri转本地路径的工具类都不是通用方案:如果用户通过
ACTION_OPEN_DOCUMENT_TREE选择的是云盘、第三方存储提供的目录,这类Uri没有对应本地物理文件路径,转换得到的路径本身就是无效的。 - 你已经通过
DocumentFile.fromTreeUri()拿到了对应目录的DocumentFile实例,不需要再绕路转成File使用。
正确实现代码
你可以直接使用DocumentFile提供的API遍历目录、读写文件,修正后的代码如下:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode != RESULT_OK || requestCode != 101) return; Uri treeUri = data.getData(); // 持久化权限,避免APP重启后权限失效 getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri); if (pickedDir == null || !pickedDir.isDirectory()) { return; } // 直接调用DocumentFile的listFiles()获取目录下的文件 DocumentFile[] files = pickedDir.listFiles(); // 遍历文件示例 for (DocumentFile file : files) { String fileName = file.getName(); long fileSize = file.length(); Uri fileUri = file.getUri(); // 如需读取文件内容,通过getContentResolver().openInputStream(fileUri)获取流 } }
注意事项
DocumentFile的listFiles()性能比原生File的listFiles()差,如果目录下文件数量非常多,建议放在子线程执行避免阻塞主线程。- 如需对文件进行读写操作,通过
DocumentFile.getUri()拿到文件Uri后,用ContentResolver的openInputStream/openOutputStream接口操作即可,不需要转换成本地File。
内容的提问来源于stack exchange,提问作者S4D3V
相关产品推荐
相关产品推荐

