Android targetSDKVersion 30 定位权限不弹出申请直接自动拒绝问题求助
问题根因
针对你targetSDKVersion=30(对应Android 11)的场景,权限申请不弹窗主要由以下几个问题导致:
- Android 11对定位权限申请做了限制,不允许同时申请前台定位(
ACCESS_COARSE_LOCATION/ACCESS_FINE_LOCATION)和后台定位(ACCESS_BACKGROUND_LOCATION)权限,你把三类权限放在同一次请求里触发,系统会直接驳回申请,不会弹出授权窗口。 - 你的权限校验逻辑要求三类权限同时授予才判定为通过,即使用户第一次授权了前台定位,没有授予后台定位的情况下,你仍然会重新触发权限申请,而重复申请被系统驳回的权限时,不会再弹出弹窗。
- 权限回调逻辑只判断了第一个申请权限的授权结果,没有校验所有申请的权限,逻辑存在漏洞。
- 如果用户之前点击过「拒绝且不再询问」,后续调用权限申请接口时系统会直接返回拒绝,不会弹窗。
修复方案
1. 调整权限申请逻辑
分两步申请权限,先申请前台定位权限,用户授权通过后再申请后台定位权限:
// 先校验前台定位权限是否已授予 private boolean checkForegroundLocationPermissions() { return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; } // 校验后台定位权限是否已授予 private boolean checkBackgroundLocationPermission() { return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED; } // 第一步:申请前台定位权限 private void requestForegroundLocationPermissions() { ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_FOREGROUND_ID); } // 第二步:申请后台定位权限,仅在前台定位权限已授予后调用 private void requestBackgroundLocationPermission() { // 申请前可以先弹自定义说明,告知用户需要后台定位的原因 ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.ACCESS_BACKGROUND_LOCATION}, PERMISSION_BACKGROUND_ID); }
2. 修复权限回调逻辑
遍历所有权限的授权结果,同时处理「拒绝且不再询问」的场景:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_FOREGROUND_ID) { boolean allForegroundGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allForegroundGranted = false; break; } } if (allForegroundGranted) { // 如果不需要后台定位,直接调用getCurrentLocation() // 如果需要后台定位,继续申请后台权限 if (checkBackgroundLocationPermission()) { getCurrentLocation(); } else { requestBackgroundLocationPermission(); } } else { // 判断用户是否点了不再询问 if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { // 弹提示引导用户去设置页开启前台定位权限 showGuideToSettingsDialog(); return; } // 跳手动输入页 gotoManualInputPage(); } } else if (requestCode == PERMISSION_BACKGROUND_ID) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { getCurrentLocation(); } else { // 后台定位不是必须的话可以继续用前台定位,否则引导用户去设置或者跳手动输入页 getCurrentLocation(); } } }
3. 可选优化
如果你的业务不需要后台定位能力,直接移除清单文件里的ACCESS_BACKGROUND_LOCATION权限声明,同时删掉代码里的后台权限校验和申请逻辑即可,不需要分两步申请。
内容的提问来源于stack exchange,提问作者bababoo
相关产品推荐
相关产品推荐

