You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,需通过以下步骤模拟移动效果:

  1. 用Intent.ACTION_CREATE_DOCUMENT或Intent.ACTION_OPEN_DOCUMENT_TREE让用户选择目标位置;
  2. 将原文件的字节数组写入目标位置的文件;
  3. 写入成功后删除原文件。

代码示例(移动文件逻辑)

// 假设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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 08:25:21