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

Android SDK 33下ActivityCompat.requestPermissions不显示权限弹窗问题

Android 权限申请弹窗不显示直接返回拒绝问题排查与解决

问题背景

项目目标SDK版本为33,需申请READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE和CAMERA权限。在Activity的onCreate中调用ActivityCompat.requestPermissions发起申请,但权限请求弹窗始终不显示,直接触发onRequestPermissionsResult并弹出权限被拒绝的Toast。已在Manifest中声明对应权限。

相关代码

onCreate方法代码

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_profile);

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        getWindow().setNavigationBarColor(mContext.getResources().getColor(R.color.water_color));
    }

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        requestStoragePermission();
    }
}

权限申请方法及回调代码

@RequiresApi(api = Build.VERSION_CODES.M)
private void requestStoragePermission() {

    if (ContextCompat.checkSelfPermission(this,
            android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
        && ContextCompat.checkSelfPermission(this,
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
        && ContextCompat.checkSelfPermission(this,
            android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)
        return;

    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
            android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
    }

    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
    }
    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
            android.Manifest.permission.CAMERA)) {
    }

    ActivityCompat.requestPermissions(this, new String[]
            {
                    android.Manifest.permission.READ_EXTERNAL_STORAGE,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    android.Manifest.permission.CAMERA
            }, STORAGE_PERMISSION);
}

@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {


    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == STORAGE_PERMISSION) {
        //If permission is granted
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(mContext, mContext.getString(R.string.permission_granted), Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(mContext, mContext.getString(R.string.permission_denied), Toast.LENGTH_SHORT).show();
        }
    }
}

Manifest文件权限声明

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

问题原因及解决方案

1. Android 13(SDK33)存储权限变更

Android 13及以上版本中,WRITE_EXTERNAL_STORAGE权限已被废弃,系统不会处理该权限的申请请求,直接返回PERMISSION_DENIED且不弹窗。针对媒体文件访问,需使用细分权限:

  • 访问图片/照片:READ_MEDIA_IMAGES
  • 访问视频:READ_MEDIA_VIDEO
  • 访问音频:READ_MEDIA_AUDIO

根据业务需求替换原有存储权限,并在Manifest中声明对应权限。

2. 用户已勾选“不再询问”

若用户之前拒绝权限时勾选了“不再询问”,后续调用requestPermissions时系统不会弹窗,直接返回拒绝。可通过shouldShowRequestPermissionRationale判断:返回false时说明用户勾选了该选项,需引导用户到应用设置页手动开启权限。

修改权限申请方法,添加引导逻辑:

@RequiresApi(api = Build.VERSION_CODES.M)
private void requestStoragePermission() {
    // 适配Android13存储权限
    String[] permissions;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        permissions = new String[]{
                Manifest.permission.READ_MEDIA_IMAGES, // 按需替换为对应媒体权限
                Manifest.permission.CAMERA
        };
    } else {
        permissions = new String[]{
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.CAMERA
        };
    }

    // 检查所有权限是否已授予
    boolean allGranted = true;
    for (String perm : permissions) {
        if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
            allGranted = false;
            break;
        }
    }
    if (allGranted) return;

    // 判断是否需要显示权限说明
    boolean needShowRationale = false;
    for (String perm : permissions) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, perm)) {
            needShowRationale = true;
            break;
        }
    }

    if (needShowRationale) {
        // 弹窗告知用户权限用途
        new AlertDialog.Builder(this)
                .setTitle("权限申请")
                .setMessage("需要存储/相机权限以完成相关功能,请允许")
                .setPositiveButton("确定", (dialog, which) -> ActivityCompat.requestPermissions(this, permissions, STORAGE_PERMISSION))
                .setNegativeButton("取消", null)
                .show();
    } else {
        // 检测是否是用户勾选了不再询问
        boolean isNeverAskAgain = false;
        for (String perm : permissions) {
            if (!ActivityCompat.shouldShowRequestPermissionRationale(this, perm) &&
                    ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
                isNeverAskAgain = true;
                break;
            }
        }
        if (isNeverAskAgain) {
            // 引导用户前往设置页开启权限
            new AlertDialog.Builder(this)
                    .setTitle("权限被拒绝")
                    .setMessage("权限已被拒绝且不再询问,请前往设置页面手动开启")
                    .setPositiveButton("去设置", (dialog, which) -> {
                        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                        Uri uri = Uri.fromParts("package", getPackageName(), null);
                        intent.setData(uri);
                        startActivity(intent);
                    })
                    .setNegativeButton("取消", null)
                    .show();
        } else {
            // 正常发起权限申请
            ActivityCompat.requestPermissions(this, permissions, STORAGE_PERMISSION);
        }
    }
}

3. 权限回调逻辑缺陷

原回调仅判断第一个权限的授予状态,忽略了其他权限的结果。修改回调逻辑,检查所有权限:

@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == STORAGE_PERMISSION) {
        boolean allGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allGranted = false;
                break;
            }
        }
        if (allGranted) {
            Toast.makeText(mContext, mContext.getString(R.string.permission_granted), Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(mContext, mContext.getString(R.string.permission_denied), Toast.LENGTH_SHORT).show();
        }
    }
}

4. Manifest权限声明适配

针对Android13更新Manifest权限声明,避免无效权限请求:

<!-- Android 13及以上媒体权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:maxSdkVersion="33" />
<!-- Android 12及以下存储权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- 相机权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 可选:声明相机硬件依赖 -->
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />

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

相关产品推荐
方舟 Agent Plan

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

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