Android 11中跨路径复制文件后输出文件为空的问题排查求助
解决Android 11跨路径文件复制后文件为空的问题
嘿,我仔细看了你的代码和问题描述,发现了几个关键问题,正是这些问题导致复制后的文件为空,咱们一步步来解决:
1. 文件Uri的编码错误
你第一个Uri里的编码存在问题:
Uri muri = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3Aagora%2file.txt");
这里的%2是不完整的URL编码,路径分隔符/的正确编码应该是%2F,所以修正后的源文件Uri应该是:
Uri muri = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3Aagora%2Ffile.txt");
错误的编码会导致系统无法正确识别文件路径,自然读不到任何文件内容。
2. 错误使用DocumentFile.fromTreeUri处理文件Uri
DocumentFile.fromTreeUri()是专门用来处理目录Tree Uri的API,而你的muri是单个文件的Uri,用这个方法会得到无效的DocumentFile对象,后续调用openInputStream()时要么拿到空流,要么根本读不到数据。处理单个文件Uri应该用DocumentFile.fromSingleUri():
DocumentFile mfile = DocumentFile.fromSingleUri(MainActivity.this, muri);
3. 潜在优化:流处理与异常排查
另外,你的复制方法可以添加一些空值判断和数据刷入逻辑,避免空指针同时确保数据完全写入磁盘,还建议打印异常信息方便后续排查:
修正后的完整代码
// 修正编码后的源文件Uri Uri muri = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3Aagora%2Ffile.txt"); Uri uri2 = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3AAlarms"); // 用fromSingleUri处理单个文件Uri DocumentFile mfile = DocumentFile.fromSingleUri(MainActivity.this, muri); DocumentFile mfile1 = DocumentFile.fromTreeUri(MainActivity.this, uri2); // 改用标准MIME类型text/plain,避免系统识别异常 mfile1 = mfile1.createFile("text/plain", "file.txt"); uri2 = mfile1.getUri(); if (copyFileFromUri2(MainActivity.this, muri, uri2)) { showMessage("file copied successfully"); } else { showMessage("failed to copy the file !"); }
优化后的复制方法
public boolean copyFileFromUri2(Context context, Uri fileUri, Uri targetUri) { InputStream fis = null; OutputStream fos = null; try { ContentResolver content = context.getContentResolver(); fis = content.openInputStream(fileUri); // 先检查输入流是否有效 if (fis == null) { return false; } fos = content.openOutputStream(targetUri); if (fos == null) { return false; } // 增大缓冲区提升复制效率 byte[] buff = new byte[4096]; int length = 0; while ((length = fis.read(buff)) != -1) { fos.write(buff, 0, length); } // 确保所有数据写入磁盘 fos.flush(); } catch (IOException e) { // 打印异常信息方便排查 e.printStackTrace(); return false; } finally { // 安全关闭流 try { if (fis != null) fis.close(); } catch (IOException e) { e.printStackTrace(); } try { if (fos != null) fos.close(); } catch (IOException e) { e.printStackTrace(); } } return true; }
额外测试建议
- 测试前确认源文件
agora/file.txt确实存在,且你的App已经获取了该文件所在目录的访问权限 - 可以在复制前先判断
mfile.exists(),确保源文件可访问
内容的提问来源于stack exchange,提问作者Hasni
相关产品推荐
相关产品推荐

