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

Android外部写入权限问题:读写文本文件遇权限拒绝异常

解决Android读写文件时的"Permission denied"问题

嘿,我之前也踩过这个权限坑,折腾了好一会儿才理顺,给你几个核心的排查和解决步骤:

1. 先确认清单文件的权限声明

首先,你需要在AndroidManifest.xml里添加必要的存储权限,还要注意不同Android版本的特殊配置:

<!-- 针对Android 10以下版本的写入权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 如果你的targetSdkVersion >= 30(Android 11+),需要添加这个来兼容旧存储模式 -->
<application
    ...
    android:requestLegacyExternalStorage="true">
    ...
</application>

注意:从Android 13开始,WRITE_EXTERNAL_STORAGE已经被废弃,改用更细分的权限,但如果是兼容旧版本,还是需要保留上面的配置。

2. 动态申请危险权限(Android 6.0+)

Android 6.0(API 23)之后,存储权限属于危险权限,只在清单里声明是不够的,必须在代码里动态请求用户授权:

// 在你的Activity里添加权限检查逻辑
private static final int REQUEST_STORAGE_PERMISSION = 100;

private void checkStoragePermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        // 如果没有权限,发起申请
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_STORAGE_PERMISSION);
    } else {
        // 权限已授予,执行文件读写操作
        buttonSave(null);
    }
}

// 处理权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_STORAGE_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 用户同意权限,执行保存操作
            buttonSave(null);
        } else {
            // 用户拒绝权限,提示或者做其他处理
            Toast.makeText(this, "需要存储权限才能保存文件", Toast.LENGTH_SHORT).show();
        }
    }
}

然后你需要修改按钮的点击逻辑,先调用checkStoragePermission(),而不是直接执行buttonSave。

3. 更推荐的文件存储路径(避开权限问题)

其实如果这个文件是你的应用专属的(比如只给你的应用用,卸载后可以删除),完全不需要申请外部存储权限,改用应用专属的外部存储路径:

public void buttonSave(View view) {
    // 获取应用专属的外部存储目录,不需要额外权限
    File directoryFile = getExternalFilesDir(null);
    // 如果目录不存在会自动创建,不用手动mkdirs()
    File file = new File(directoryFile, "savefile.txt");
    try {
        if (!file.exists()) {
            file.createNewFile();
        }
        // 这里添加写入文件的逻辑,比如用FileWriter
        FileWriter writer = new FileWriter(file);
        writer.write("你要保存的内容");
        writer.close();
        Toast.makeText(this, "文件保存成功", Toast.LENGTH_SHORT).show();
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(this, "保存失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
    }
}

这个路径的好处是不需要任何权限,而且系统会自动管理,卸载应用时会一起删除这个目录下的文件,更符合Android的存储规范。

4. 排查异常细节

如果还是报错,一定要把异常的完整堆栈信息打出来,比如在catch块里加e.printStackTrace(),这样能看到具体是哪一行出错,比如目录创建失败还是文件写入失败,有助于精准定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:08:43