Android Studio中如何通过Uri访问Android/data/目录下的子文件夹
问题排查及修复方案
核心问题根因
- 错误的子目录Uri构建方式:直接给treeDocumentId拼接
/com.tencent.ig/字符串的方式不符合DocumentProvider的路径规则,系统无法识别这个拼接后的id指向的子目录,会自动 fallback 到根目录。 - 未校验子目录是否存在:如果
com.tencent.ig目录不存在,直接构建Uri后操作也会默认写入根目录。 createFile第一个参数传空不符合规范:第一个参数需要传正确的MIME类型,空值可能导致文件创建逻辑异常。- 原代码中获取持久化权限Uri的写法存在语法错误:
getPersistedUriPermissions()返回的是权限列表,需要先取对应条目再获取Uri。
修复后的代码实现
public void copy(File src, Uri dst) throws IOException { // 1. 正确获取已授权的Android/data根目录Uri Uri treeUri = getPersistedUriPermissions().get(0).getUri(); DocumentFile rootDir = DocumentFile.fromTreeUri(this, treeUri); if (rootDir == null || !rootDir.exists()) { Toast.makeText(this, "根目录权限未获取成功", Toast.LENGTH_LONG).show(); return; } // 2. 查找或创建目标子目录 com.tencent.ig DocumentFile targetSubDir = rootDir.findFile("com.tencent.ig"); if (targetSubDir == null || !targetSubDir.isDirectory()) { targetSubDir = rootDir.createDirectory("com.tencent.ig"); if (targetSubDir == null) { Toast.makeText(this, "子目录创建失败", Toast.LENGTH_LONG).show(); return; } } // 3. 在目标子目录下创建文件,传入正确的MIME类型 DocumentFile targetFile = targetSubDir.createFile("application/octet-stream", "Active.sav"); if (targetFile == null) { Toast.makeText(this, "目标文件创建失败", Toast.LENGTH_LONG).show(); return; } // 4. 执行文件流拷贝 try (InputStream in = new FileInputStream(src); OutputStream out = getContentResolver().openOutputStream(targetFile.getUri(), "w")) { byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } } }
额外注意事项
- 申请权限的时候必须引导用户手动选中
Android/data根目录完成授权,不能默认选中其他目录。 - Android 13及以上版本如果 targetSdk >=33,需要额外确认特殊目录访问权限的申请逻辑适配了系统版本要求。
- 拷贝操作建议放到子线程执行,避免阻塞主线程导致ANR。
内容的提问来源于stack exchange,提问作者S I A
相关产品推荐
相关产品推荐

