Android 13权限适配异常求助:已授权仍提示手动修改权限
问题分析与修复方案
核心问题点
- 权限请求结果判断逻辑错误:当前代码仅判断
grantResults.length == 1,如果同时请求多个权限,该条件不满足会直接进入拒绝分支触发提示,即便部分权限已授予。 - Android 13权限处理不完整:
- 仅针对Android 13处理
shouldShowRequestPermissionRationale,但该API是区分用户「暂时拒绝」和「永久拒绝(不再询问)」的核心判断逻辑,需覆盖所有版本场景。 - 未针对每个权限单独判断拒绝状态,直接取第一个权限处理导致误判。
- 仅针对Android 13处理
- Manifest冗余/无效权限:
- 重复添加
READ_PRIVILEGED_PHONE_STATE,该权限仅系统应用可申请,普通应用无需配置。 WRITE_INTERNAL_STORAGE、READ_INTERNAL_STORAGE为系统级权限,普通应用无法获取,应移除。- Android 13及以上,
READ_EXTERNAL_STORAGE已被媒体权限替代,需添加maxSdkVersion限制仅在低版本生效。
- 重复添加
修复后的代码实现
权限请求逻辑(支持多权限校验)
// 按需整理需要申请的权限数组 String[] requiredPermissions = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_CALENDAR }; // 检查所有权限是否已授予 boolean allPermissionsGranted = true; for (String perm : requiredPermissions) { if (ActivityCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) { allPermissionsGranted = false; break; } } if (!allPermissionsGranted) { ActivityCompat.requestPermissions(this, requiredPermissions, Datafields.REQUEST_CODE_PERMISSION); } else { Intent intent = new Intent(this, FileLeave.class); startActivity(intent); }
权限请求结果回调(修正多权限与拒绝判断)
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == Datafields.REQUEST_CODE_PERMISSION) { boolean allGranted = true; boolean hasPermanentDenial = false; // 遍历所有权限逐一校验授予状态 for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { allGranted = false; // 判断该权限是否被永久拒绝(用户勾选「不再询问」) if (!shouldShowRequestPermissionRationale(permissions[i])) { hasPermanentDenial = true; break; } } } if (allGranted) { // 所有权限通过,跳转目标页面 Intent intent = new Intent(this, FileLeave.class); startActivity(intent); } else { if (hasPermanentDenial) { Toast.makeText(this, "请从手机设置手动修改权限", Toast.LENGTH_SHORT).show(); } else { // 用户暂时拒绝,可提示权限必要性引导再次申请 Toast.makeText(this, "需要相关权限才能正常使用功能", Toast.LENGTH_SHORT).show(); } } } }
修复后的Manifest权限配置
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.wifi" /> <!-- Android 13+ 媒体权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/> <!-- 位置权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 日历权限 --> <uses-permission android:name="android.permission.READ_CALENDAR" /> <!-- 电话状态权限(普通应用仅能获取基础状态) --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 自定义权限 --> <uses-permission android:name="in.globalspace.android.gst_communicator_permission" /> <!-- Android 12及以下存储权限,Android 13+自动忽略 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
额外注意事项
- 遵循按需申请原则,不要一次性请求所有权限,分场景申请可提升用户授权率。
- Android 13媒体权限可按需申请,比如仅需访问图片时无需申请
READ_MEDIA_AUDIO。 shouldShowRequestPermissionRationale返回false时,说明用户已勾选「不再询问」,此时只能引导用户前往设置页开启权限。
内容的提问来源于stack exchange,提问作者Abm
相关产品推荐
相关产品推荐

