调用GoogleMap.setMyLocationEnabled缺定位权限 闪退无权限弹窗
运行时报错信息
Missing permissions required by GoogleMap.setMyLocationEnabled: android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION
问题场景
调用地理围栏定位功能,选择地理围栏区域时应用闪退。已在AndroidManifest.xml中声明ACCESS_COARSE_LOCATION、ACCESS_FINE_LOCATION相关权限,但应用启动时从未弹出权限授权申请弹窗。

问题原因
当前动态权限申请逻辑存在两处致命问题:
- 重复嵌套了两层完全一致的
ActivityCompat.shouldShowRequestPermissionRationale判断,该方法仅在用户曾经拒绝过权限申请、且未勾选“不再询问”选项时才会返回true。应用首次安装启动时该方法返回值为false,导致现有逻辑永远不会在首次启动时触发权限申请流程,自然不会弹出授权弹窗。 - 代码逻辑错误地将
shouldShowRequestPermissionRationale作为发起权限申请的前置条件,完全没有覆盖首次安装启动的权限申请场景,调用mMap.setMyLocationEnabled(true)时没有获得对应权限,直接触发闪退。
注:Android 6.0(API 23)及以上版本的危险权限,仅在清单文件声明不会自动授予,必须通过动态申请流程获得用户授权后才能调用相关接口。
修复步骤
- 修正
enableUserLocation方法逻辑,移除无意义的重复判断,未获得权限时直接发起申请:
// 定位权限请求码,可自行定义取值 private static final int FINE_LOCATION_ACCESS_REQUEST_CODE = 1001; private void enableUserLocation(){ if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){ // 已获得权限再开启位置图层 mMap.setMyLocationEnabled(true); } else { // 未获得权限时直接发起申请,无需等shouldShowRequestPermissionRationale返回true // 该方法仅用于判断是否需要向用户展示权限用途说明,不是申请权限的前置条件 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, FINE_LOCATION_ACCESS_REQUEST_CODE); } }
- 重写权限申请结果回调,用户授权完成后再执行开启位置图层的逻辑:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == FINE_LOCATION_ACCESS_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 校验权限确实授予后再开启位置图层 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { mMap.setMyLocationEnabled(true); } } else { // 用户拒绝权限时给出提示 Toast.makeText(this, "定位权限是使用地理围栏功能的必要权限,请在应用设置中手动开启", Toast.LENGTH_LONG).show(); } } }
额外注意事项
- 如果你的应用适配Android 10(API 29)及以上版本用到
ACCESS_BACKGROUND_LOCATION后台定位权限,不能和前台定位权限同时申请,必须等用户同意前台定位权限后,再单独发起后台定位权限的申请,否则系统会直接拒绝该权限请求。 - 如果需要给用户解释权限用途,可以在
shouldShowRequestPermissionRationale返回true的时候先弹一个说明弹窗,用户确认后再调用requestPermissions,不要把这个判断作为拦截权限申请的条件。
内容的提问来源于stack exchange,提问作者ken
相关产品推荐
相关产品推荐

