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

Android 13及以上READ_EXTERNAL_STORAGE权限请求不显示问题求助

Android 13+ WebView文件上传权限问题解决方法

问题根源拆解

  1. Android 13权限规则变更:READ_EXTERNAL_STORAGE在Android 13(API 33)及以上被废弃,系统会自动将该权限标记为"已授予",不会触发弹窗请求。此时应使用READ_MEDIA_IMAGES/READ_MEDIA_VIDEO等细分媒体权限。
  2. 权限请求与结果的索引对应错误:你请求权限的数组顺序是[READ_EXTERNAL_STORAGE, CAMERA],但在onRequestPermissionsResult里错误地将grantResults[0]判定为相机权限、grantResults[1]判定为存储权限,完全搞反了顺序。
  3. 权限判断逻辑未适配版本:没有针对Android 13+调整权限检查的条件,导致错误判断权限状态,进而触发错误的Toast提示。

修复后的代码实现

1. 权限请求方法修正

private boolean file_permission(){
    if(Build.VERSION.SDK_INT >= 23){
        // 区分Android版本处理权限检查
        boolean hasCameraPerm = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
        boolean hasStoragePerm;

        if(Build.VERSION.SDK_INT >= 33){
            // Android 13+ 使用媒体权限替代READ_EXTERNAL_STORAGE
            hasStoragePerm = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) == PackageManager.PERMISSION_GRANTED
                    && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_VIDEO) == PackageManager.PERMISSION_GRANTED;
        } else {
            // Android 12及以下 使用READ_EXTERNAL_STORAGE
            hasStoragePerm = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
        }

        if(!hasCameraPerm || !hasStoragePerm){
            // 根据版本构建请求权限数组
            ArrayList<String> permList = new ArrayList<>();
            if(!hasCameraPerm) permList.add(Manifest.permission.CAMERA);
            if(Build.VERSION.SDK_INT >=33){
                if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED){
                    permList.add(Manifest.permission.READ_MEDIA_IMAGES);
                }
                if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_VIDEO) != PackageManager.PERMISSION_GRANTED){
                    permList.add(Manifest.permission.READ_MEDIA_VIDEO);
                }
            } else {
                if(!hasStoragePerm) permList.add(Manifest.permission.READ_EXTERNAL_STORAGE);
            }

            ActivityCompat.requestPermissions(MainActivity.this, permList.toArray(new String[0]), 1);
            return false;
        } else {
            return true;
        }
    } else {
        return true;
    }
}

2. 权限结果回调修正

@Override
public void onRequestPermissionsResult(int permsRequestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(permsRequestCode, permissions, grantResults);
    if(permsRequestCode != 1) return;

    boolean allGranted = true;
    boolean cameraDeniedPermanently = false;
    boolean mediaDeniedPermanently = false;

    // 遍历所有请求的权限,逐个检查状态
    for(int i=0; i<permissions.length; i++){
        String perm = permissions[i];
        int result = grantResults[i];

        if(result == PackageManager.PERMISSION_GRANTED){
            if(perm.equals(Manifest.permission.CAMERA)){
                Log.d("Permissions", "Camera permission granted");
            } else if(perm.equals(Manifest.permission.READ_EXTERNAL_STORAGE)){
                Log.d("Permissions", "Read external storage permission granted");
            } else if(perm.equals(Manifest.permission.READ_MEDIA_IMAGES)){
                Log.d("Permissions", "Read media images permission granted");
            } else if(perm.equals(Manifest.permission.READ_MEDIA_VIDEO)){
                Log.d("Permissions", "Read media video permission granted");
            }
        } else {
            allGranted = false;
            // 判断是否永久拒绝
            if(!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, perm)){
                if(perm.equals(Manifest.permission.CAMERA)){
                    cameraDeniedPermanently = true;
                } else {
                    mediaDeniedPermanently = true;
                }
            }
        }
    }

    // 根据权限状态显示对应提示
    if(allGranted){
        Toast.makeText(getApplicationContext(), "You can now upload images/files.", Toast.LENGTH_LONG).show();
    } else {
        if(cameraDeniedPermanently || mediaDeniedPermanently){
            Toast.makeText(getApplicationContext(), "You have permanently blocked image/file upload.", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(getApplicationContext(), "Your permission is required to upload images/files.", Toast.LENGTH_LONG).show();
        }
    }
}

关键修复说明

  • 版本适配:Android 13+不再请求READ_EXTERNAL_STORAGE,转而请求对应的媒体权限,避免系统自动标记该权限为已授予的问题。
  • 索引对应:遍历权限数组和结果数组,直接通过权限字符串匹配,彻底解决索引顺序错误的问题。
  • 状态判断:分别检查每个权限的授予状态和是否永久拒绝,避免单一权限判断导致的错误提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:46:39