Android 29+版本文件管理器如何从DocumentFile获取File对象
问题核心结论
Android 11(API 30)及以上版本强制开启分区存储后,应用对OTG等可移动存储介质没有直接的文件系统访问权限,不存在合法通用的方法可以从DocumentFile对象直接转换得到java.io.File对象,这也是你直接调用OTG路径的listFile()方法无法返回文件的根本原因:原生File API没有权限访问未授权的外部存储路径。
常规场景替代实现方案
你不需要强行转换得到File对象,绝大多数文件操作都可以通过DocumentFile或系统提供的ContentResolver接口直接完成:
- 遍历目录下的文件:直接调用
DocumentFile.listFiles()即可正常获取OTG目录下的所有子文件/子文件夹 - 获取文件基础属性:直接调用
DocumentFile的对应方法即可,不需要依赖File API- 文件名:
documentFile.getName() - 文件大小:
documentFile.length() - 修改时间:
documentFile.lastModified() - 类型判断:
documentFile.isDirectory()/documentFile.isFile()
- 文件名:
- 读取文件内容:通过ContentResolver打开对应Uri的输入流
InputStream is = getContentResolver().openInputStream(documentFile.getUri());
- 写入文件内容:同理打开输出流操作即可
OutputStream os = getContentResolver().openOutputStream(documentFile.getUri());
- 文件复制、移动等操作:直接通过输入输出流对接即可,执行效率和原生File API差异极小
特殊场景兼容方案
如果你的应用已经申请了MANAGE_EXTERNAL_STORAGE全文件管理权限,且仅在固定机型场景使用,可以尝试从DocumentFile对应的Uri中提取物理路径生成File对象,这个方案不保证兼容所有厂商机型,公网发布的普通应用不建议使用:
File targetFile = null; Uri uri = documentFile.getUri(); if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { Cursor cursor = getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DATA}, null, null, null); if (cursor != null) { if (cursor.moveToFirst()) { int pathIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DATA); if (pathIndex != -1) { String path = cursor.getString(pathIndex); targetFile = new File(path); } } cursor.close(); } } // 仅当应用持有全文件管理权限时,上述方法得到的File对象才能正常读写
内容的提问来源于stack exchange,提问作者Developer_ rahul
相关产品推荐
相关产品推荐

