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

Android 11在公共Download目录创建文件是否需要适配SAF及申请权限

问题1解答

该场景无需适配存储访问框架(SAF),你仅操作自有应用生成的公共目录文件,无需调用SAF的文件选择器相关能力。

问题2解答

无需申请特殊权限:

  • Android 11及以上版本,操作自有应用生成的公共下载/公共文档目录文件,不需要申请MANAGE_EXTERNAL_STORAGE(所有文件访问权限),也不需要旧的WRITE_EXTERNAL_STORAGE权限
  • 如果你的应用需要兼容Android 10及更低版本,只需要在对应版本区间申请WRITE_EXTERNAL_STORAGE权限即可

问题3解答

可以不使用SAF访问/storage/emulated/0/Documents目录,逻辑和Download目录一致,仅操作自有应用生成的文件时,直接使用MediaStore API即可完成访问。


原有代码报错原因

Android 11正式强制执行分区存储逻辑,Environment.getExternalStoragePublicDirectory返回的路径已经被限制直接通过File类API访问,因此直接调用createNewFile、FileOutputStream都会抛出IO异常。

适配后的实现代码

// Android 11及以上在Download目录创建/替换文件的实现
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    ContentResolver resolver = getContentResolver();
    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.Downloads.DISPLAY_NAME, "Somefile.txt");
    contentValues.put(MediaStore.Downloads.MIME_TYPE, "text/plain");
    // 替换已存在的同名自有文件,添加IS_PENDING标记先独占写入
    contentValues.put(MediaStore.Downloads.IS_PENDING, 1);
    Uri uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues);
    if (uri != null) {
        try {
            OutputStream fo = resolver.openOutputStream(uri);
            byte[] data1 = {1,1,0,0};
            fo.write(data1);
            fo.close();
            // 写入完成后取消IS_PENDING标记,文件对外可见
            contentValues.clear();
            contentValues.put(MediaStore.Downloads.IS_PENDING, 0);
            resolver.update(uri, contentValues, null, null);
            Log.i(TAG, "文件创建完成");
        } catch (IOException e) {
            Log.e(TAG, "创建文件异常", e);
        }
    }
} else {
    // 低版本走原有逻辑即可
    File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    File file = new File(path, "Somefile.txt");
    String location = file.getAbsolutePath();
    try {
        file.createNewFile();
        byte[] data1 = {1,1,0,0};
        OutputStream fo = new FileOutputStream(file);
        fo.write(data1);
        fo.close();
        Log.i(TAG, "The file is created at " + location);
    } catch (IOException e) {
        Log.e(TAG, "Exception creating file");
        return location;
    }
}

补充说明

如果需要后续追加数据,只需要通过MediaStore查询到对应文件的Uri,用"wa"模式打开输出流写入即可;仅当你需要读取/修改其他应用生成的公共目录文件时,才需要申请额外权限或者适配SAF。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 18:27:04