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

如何借助Uri权限在Android/data目录下正确写入文件?

解决Android/data目录通过SAF授权后File无法写入的问题

问题原因

从你的输出能看到,df.getUri().getPath()返回的是/tree/primary:Android/data/document/primary:Android/data,这压根不是真实的文件系统路径,只是SAF提供的虚拟路径。Android 10及以上版本,直接用File对象访问通过SAF授权的目录完全无效——系统限制了File API对这类授权目录的直接操作,必须用SAF相关的API(DocumentFile、ContentResolver)来完成读写。

解决方案

要在授权的Android/data目录下写入文件,得靠DocumentFile创建子文件,再用ContentResolver写入内容,具体步骤如下:

  1. 创建目标文件的DocumentFile对象
    通过已授权的目录DocumentFile,调用createFile()方法生成要写入的文件:

    // 已授权的Android/data目录的DocumentFile实例
    DocumentFile androidDataDir = DocumentFile.fromSingleUri(activity.getApplicationContext(), uriPath);
    // 创建目标zip文件,第一个参数是MIME类型,第二个是文件名
    DocumentFile targetFile = androidDataDir.createFile("application/zip", product + ".zip");
    
  2. 通过ContentResolver写入文件内容
    用ContentResolver.openOutputStream()拿到输出流,直接写入数据:

    if (targetFile != null) {
        try (OutputStream outputStream = activity.getContentResolver().openOutputStream(targetFile.getUri())) {
            // 这里替换成你的文件写入逻辑,比如从下载的输入流复制数据
            byte[] buffer = new byte[4096];
            int bytesRead;
            // 假设inputStream是你下载的数据源
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

额外提示

  • 要确保你拿到的SAF授权是目录权限(通过ACTION_OPEN_DOCUMENT_TREE请求的),而不是单个文件权限,这样才能在目录下创建子文件。
  • 如果需要覆盖已存在的文件,先判断文件是否存在,存在就删掉再创建:
    DocumentFile existingFile = androidDataDir.findFile(product + ".zip");
    if (existingFile != null) {
        existingFile.delete();
    }
    DocumentFile targetFile = androidDataDir.createFile("application/zip", product + ".zip");
    

内容的提问来源于stack exchange,提问作者Warley Soares

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:25:15