Android中使用SAF的Intent.ACTION_CREATE_DOCUMENT创建文件为0字节的问题
问题解决:SAF创建文件后写入字节数组及文件移动方案
一、为什么创建的文件是空的?
Intent.ACTION_CREATE_DOCUMENT仅负责让用户选择保存位置并创建空文件,本身不会自动写入数据。你需要在用户完成位置选择后,通过返回的Uri手动执行写入操作。
二、如何将字节数组写入SAF创建的文件?
用户选择保存位置并返回后,在结果回调中获取目标文件的Uri,再通过ContentResolver打开输出流写入字节数组即可。
代码示例:
1. 用AndroidX推荐的ActivityResultLauncher替代startActivityForResult
// 初始化结果回调 private final ActivityResultLauncher<Intent> createFileLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { Uri targetUri = result.getData().getData(); if (targetUri != null) { // 写入字节数组 writeBytesToUri(targetUri, dataForWriting); } } } ); // 修改createFile方法,用launcher启动Intent public void createFile(File url) { Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); USBUtils.intentUriFilter(url, intent); // 你的MIME类型设置逻辑 intent.putExtra(Intent.EXTRA_TITLE, url.getName()); // 注意:Android 10+中Uri.fromFile(url)可能触发FileUriExposedException,建议通过SAF获取原目录Uri // intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, 合法的SAF目录Uri); createFileLauncher.launch(intent); }
2. 实现字节数组写入方法
private void writeBytesToUri(Uri targetUri, byte[] data) { try (OutputStream outputStream = getContentResolver().openOutputStream(targetUri)) { if (outputStream != null) { outputStream.write(data); outputStream.flush(); // 写入成功后的逻辑,比如提示用户 } } catch (IOException e) { e.printStackTrace(); // 处理写入失败的情况 } }
三、能否通过Intent移动Files.write()创建的文件?
Android没有直接实现文件移动的Intent,需通过以下步骤模拟移动效果:
- 用
Intent.ACTION_CREATE_DOCUMENT或Intent.ACTION_OPEN_DOCUMENT_TREE让用户选择目标位置; - 将原文件的字节数组写入目标位置的文件;
- 写入成功后删除原文件。
代码示例(移动文件逻辑)
// 假设sourceFile是Files.write创建的本地文件 private void moveFile(File sourceFile, Uri targetUri) { try { // 读取原文件字节数组 byte[] data = Files.readAllBytes(sourceFile.toPath()); // 写入目标Uri try (OutputStream outputStream = getContentResolver().openOutputStream(targetUri)) { if (outputStream != null) { outputStream.write(data); outputStream.flush(); // 写入成功后删除原文件 Files.delete(sourceFile.toPath()); } } } catch (IOException e) { e.printStackTrace(); } }
USB驱动器操作注意事项
Android 10+下无法通过File对象直接访问USB外部存储,必须依赖SAF的Uri进行读写。你当前采用的SAF方案是正确的,只要通过ContentResolver操作Uri,就能正常写入USB驱动器。
内容的提问来源于stack exchange,提问作者Khiem Luong
相关产品推荐
相关产品推荐

