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

Android存储权限异常:Android 9无法保存文本至外部存储问题排查

问题分析与修复方案

嘿,我仔细看了你的代码和遇到的问题,核心问题其实是权限请求的逻辑完全写反了,另外还有几个小细节需要调整——和你担心的手动创建"My Files"文件夹没关系,你的文件夹创建逻辑是没问题的。

1. 最致命的错误:权限判断逻辑搞反了!

看你onCreate里的这段权限判断代码:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
    if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){
        String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
        requestPermissions(permissions,WRITE_EXTERNAL_STORAGE_CODE);
    }else {
        saveToTxtFile(mText);
    }
}

这段代码的逻辑完全颠倒了:已经有存储权限的时候,你反而去请求权限;没有权限的时候,却直接执行保存操作——这就导致在Android 9(API28)上,因为没有正确请求权限,直接触发了权限拒绝的问题。

修正后的正确逻辑应该是:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
    // 检查是否没有权限,没有的话才去请求
    if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
        String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
        requestPermissions(permissions,WRITE_EXTERNAL_STORAGE_CODE);
    }else {
        // 已经有权限,直接保存文件
        saveToTxtFile(mText);
    }
}

2. Android 9(API28)的存储权限细节

虽然Android 9还没强制分区存储,但你需要确保:

  • 你已经在AndroidManifest.xml里正确声明了读写权限,这部分你做的没问题
  • 别忘了定义WRITE_EXTERNAL_STORAGE_CODE常量,比如在MainActivity里加一行:
    private static final int WRITE_EXTERNAL_STORAGE_CODE = 100;
    
    否则请求权限的回调会识别不了请求码。

3. 关于"My Files"文件夹的创建

你的文件夹创建逻辑是对的:dir.mkdirs()会自动创建所有不存在的父目录,不管"My Files"之前有没有,都会帮你建好。不过可以优化一下路径拼接的方式,避免硬编码斜杠的问题:

// 用File的构造方法来拼接路径,更安全
File dir = new File(path, "My Files");

这样能适配不同系统的文件路径分隔符,不容易出错。

4. 额外的优化建议

  • saveToTxtFile方法里,建议用try-with-resources语法,它会自动帮你关闭流,避免资源泄漏:
    try (FileWriter fw = new FileWriter(file.getAbsoluteFile());
         BufferedWriter bw = new BufferedWriter(fw)) {
        bw.write(mText);
        Toast.makeText(this, fileName+" is saved to\n" + dir, Toast.LENGTH_SHORT).show();
    } catch (Exception e) {
        Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
    }
    
  • 如果之后要适配Android 10(API29)及以上版本,建议改用媒体存储API或者应用专属外部存储,因为Environment.getExternalStorageDirectory()从API29开始被弃用,而且分区存储会限制对公共目录的直接写入。

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

火山引擎 最新活动