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

适配Android O及以上版本,如何解决targetApi=27后读写存储权限失效问题?

Android O(API 26+)外部存储读写权限适配指南

嘿,这个问题我太熟悉了!Android 8.0(API 26)开始,系统对存储权限的逻辑做了关键调整,这就是你之前的代码突然失效的原因,咱们一步步理清楚:

为什么旧代码不再生效?

在API 26及以上版本,WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE同属于「STORAGE」权限组,系统会自动关联这两个权限:

  • 当用户授予其中一个权限时,另一个权限会被系统自动授予;
  • 如果你同时申请两个权限,系统只会弹出一次授权弹窗(显示“允许应用访问设备上的照片、媒体和文件”),但在onRequestPermissionsResult()回调中,可能只会返回READ_EXTERNAL_STORAGE的授权结果,WRITE权限的结果看起来像是未被授予,但实际上系统已经自动给你了。

适配API 26+的正确做法

1. 简化权限申请代码

你只需要申请READ_EXTERNAL_STORAGE权限就足够了,系统会自动附带授予WRITE_EXTERNAL_STORAGE权限:

private static final int REQUEST_STORAGE_PERMISSION = 100;

// 检查并申请权限
public void checkStoragePermission(Context context) {
    if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) 
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions((Activity) context,
                new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                REQUEST_STORAGE_PERMISSION);
    } else {
        // 权限已授予,执行存储操作
        performStorageTasks();
    }
}

2. 正确处理权限回调

在onRequestPermissionsResult()中,只需要判断READ_EXTERNAL_STORAGE的授权结果即可,因为WRITE权限已经自动同步:

@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) {
            // READ权限已授予,WRITE权限也自动生效
            performStorageTasks();
        } else {
            // 权限被拒绝,提示用户开启权限
            Toast.makeText(this, "需要存储权限才能访问媒体文件", Toast.LENGTH_SHORT).show();
        }
    }
}

3. 权限检查的正确姿势

后续在使用存储功能前,只需要检查READ_EXTERNAL_STORAGE的权限状态,无需单独检查WRITE:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) 
    == PackageManager.PERMISSION_GRANTED) {
    // 可以放心读写外部存储
}

额外提醒(针对更高版本)

如果你的应用后续要适配Android 10(API 29)及以上,还会遇到「分区存储(Scoped Storage)」的限制,不过这是另一个话题了,当前针对API 26-28的场景,上面的方案完全够用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:44:14