Android 12授予近似位置权限时FusedLocationProviderClient无法返回位置
这个问题由Android 12新增的精确/近似位置权限机制与FusedLocationProviderClient的权限校验逻辑共同导致,对应解决方案如下:
- 权限与优先级适配:Android 12及以上版本中,若仅持有近似位置权限(即仅获得
ACCESS_COARSE_LOCATION权限)时,FusedLocationProviderClient会拒绝响应优先级为PRIORITY_HIGH_ACCURACY的位置请求,该优先级强制要求精确定位权限才可返回结果。即使设置为PRIORITY_BALANCED_POWER_ACCURACY`仍无返回的核心原因是优先级写死未根据当前持有的权限类型动态调整,固定的优先级参数会被系统拦截。 - 位置更新频率节流:Android 12对仅授予近似位置权限的应用会强制节流位置更新频率,你代码中设置的1s最快间隔、10s普通间隔过于密集,会被系统直接忽略,导致长时间无回调返回。
- 旧版本服务兼容问题:如果使用的Google Play服务定位库版本低于21.0.0,存在已知的近似权限适配bug,会导致近似权限下无法返回位置。
具体修改方案
- 动态调整位置请求参数,权限授予后先校验当前持有的权限类型,动态设置优先级和间隔,参考修改代码如下:
private fun onLocationPermissionGranted() { if (!requireContext().isLocationEnabled()) { requireContext().showLocationPermissionRequiredDialog { onBackPressed() } return } // 动态判断当前持有的权限类型 val hasFineLocation = ContextCompat.checkSelfPermission( requireContext(), Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED // 根据权限动态调整请求优先级 val requestPriority = if (hasFineLocation) { LocationRequest.PRIORITY_HIGH_ACCURACY } else { LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY } // 重新配置locationRequest参数 locationRequest.setPriority(requestPriority) if (!hasFineLocation) { // 近似权限下调整间隔适配系统节流规则 locationRequest.setFastestInterval(5000) // 最快5秒 locationRequest.setInterval(30000) // 普通间隔30秒 } try { getCurrentLocation(requestPriority) fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()) } catch (t: Throwable) { onBackPressed() } } // 修改getCurrentLocation支持传入动态优先级 private fun getCurrentLocation(priority: Int) { fusedLocationClient.getCurrentLocation( priority, cts.token ).addOnSuccessListener { location: Location? -> location?.let { userLocation = it onUserLocationUpdated() } }.addOnFailureListener { // 近似权限下getCurrentLocation超时属于正常情况,后续依赖locationCallback返回结果即可 } }
- 升级Google Play服务定位依赖到21.0.0及以上版本,在模块级build.gradle中修改依赖配置:
implementation 'com.google.android.gms:play-services-location:21.0.1'
内容的提问来源于stack exchange,提问作者Myroslav
相关产品推荐
相关产品推荐

