You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android应用SD卡写入权限问题:授权后仍遇SecurityException异常

解决Android中SAF授权后写入SD卡目录的SecurityException问题

你遇到的是Android Scoped Storage下的典型权限问题——虽然通过ACTION_OPEN_DOCUMENT_TREE获取了SD卡目录的写入权限,但直接用传统File流操作content://格式的URI会触发权限拒绝。从Android 10(API 29)开始,系统要求通过Storage Access Framework (SAF) 提供的专属API来操作授权目录,不能直接访问文件路径。

核心原因

你拿到的content://com.android.externalstorage.documents/tree/0FFF170E%3AMyDir/MyFile.MyExt是SAF的文档URI,并非传统文件系统路径。Android会阻止通过FileOutputStream直接写入这类URI,必须用ContentResolver配合DocumentFile完成文件创建和写入。

解决方案步骤

  1. 将授权目录URI转换为DocumentFile
    把用户授权返回的目录tree URI转换成DocumentFile对象,这是SAF操作目录的入口。
  2. 定位已存在的目标子目录
    如果用户授权的是SD卡根目录,需要先找到已存在的MyDir子目录。
  3. 通过SAF API创建文件并写入
    DocumentFile.createFile()创建文件,再通过ContentResolver.openOutputStream()获取输出流写入内容。

完整代码示例

// 假设你已从ACTION_OPEN_DOCUMENT_TREE回调中拿到授权的treeUri
Uri treeUri = ...; // 示例:content://com.android.externalstorage.documents/tree/0FFF170E%3A

// 1. 获取根目录的DocumentFile实例
DocumentFile rootDir = DocumentFile.fromTreeUri(getContext(), treeUri);
if (rootDir == null || !rootDir.isDirectory()) {
    // 目录无效,处理错误逻辑
    return;
}

// 2. 找到已存在的目标子目录MyDir
DocumentFile targetDir = rootDir.findFile("MyDir");
if (targetDir == null || !targetDir.isDirectory()) {
    // 目标目录不存在,处理错误逻辑
    return;
}

// 3. 在目标目录中创建指定文件
// 第一个参数为MIME类型,根据文件类型调整:文本用"text/plain",图片用"image/jpeg",通用二进制用"application/octet-stream"
DocumentFile newFile = targetDir.createFile("application/octet-stream", "MyFile.MyExt");
if (newFile == null) {
    // 文件创建失败,可能是权限不足或目录不可写
    return;
}

// 4. 写入文件内容
try (OutputStream outputStream = getContext().getContentResolver().openOutputStream(newFile.getUri())) {
    // 示例:写入字符串内容
    String content = "测试写入SD卡文件";
    outputStream.write(content.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
    e.printStackTrace();
    // 处理写入异常
}

关键注意事项

  • 禁止混用File API和SAF URI:永远不要把content:// URI转换成File对象直接操作,这必然触发权限拒绝。
  • MIME类型要匹配createFile()的MIME类型尽量和文件扩展名对应,不确定时用application/octet-stream(通用二进制类型)即可。
  • 权限持久化:通过SAF获取的目录权限会被系统持久保存,除非用户手动在应用设置中撤销,无需每次操作都重新申请。

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

火山引擎 最新活动