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
相关产品推荐
相关产品推荐

