Android LocationServices.checkLocationSettings部分机型假阴性问题咨询
问题根因
你遇到的问题是定制ROM对Google Location Service API的魔改导致的,结合你给出的LocationSettingsStates参数可以直接定位问题:
- 你的
LocationRequest设置的优先级是PRIORITY_HIGH_ACCURACY,该模式要求GPS硬件处于可用状态,但返回结果里isGpsUsable: false,所以API会判定当前设置不满足要求,返回ResolvableApiException - 小米MIUI、索尼Xperia的部分旧版本ROM对
ResolvableApiException的弹出逻辑做了定制修改,不会弹出系统级的切换定位模式弹窗,直接返回RESULT_OK,但实际上定位模式/ GPS状态没有变化,导致你重试检查时再次触发异常,形成死循环。
修复方案
1. 前置原生位置状态检查
不要完全依赖Google Service的检查结果,先用系统原生LocationManager判断位置服务的实际开启状态,只要确认位置服务已开启,可以优先跳过Google的配置检查直接发起定位请求:
fun isLocationEnabled(context: Context): Boolean { val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { lm.isLocationEnabled } else { lm.isProviderEnabled(LocationManager.GPS_PROVIDER) || lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) } }
在调用checkLocationSettings之前先执行上述检查,如果已经返回true,可以直接走正常定位逻辑,不需要走配置校验流程。
2. 调整检查配置与异常处理逻辑
- 如果你的业务不需要高精度定位,直接把
LocationRequest的优先级改为PRIORITY_BALANCED_POWER_ACCURACY,即可规避GPS可用性检查的问题 - 必须使用高精度的场景,不要用系统自带的
ResolvableApiException弹窗,自己实现自定义提示框引导用户手动切换定位模式到高精度 - 给
LocationSettingsRequest.Builder追加setNeedBle(false)配置,部分定制ROM的蓝牙定位检查逻辑存在误判,关闭后可以减少异常返回的概率
3. 增加循环防护
在定位配置检查的回调里加重试次数限制,同一轮请求最多重试2次,超过上限后直接走降级逻辑,比如切换低优先级定位请求,避免出现无限循环:
// 类成员变量,记录重试次数 private var locationCheckRetryCount = 0 private val locationServiceContract = registerForActivityResult( ActivityResultContracts.StartIntentSenderForResult() ) { activityResult -> lifecycleScope.launchWhenResumed { if (activityResult.resultCode == Activity.RESULT_OK) { if (locationCheckRetryCount < 2) { locationCheckRetryCount++ enableLocationSettings(...) } else { // 重试超限,走降级逻辑,比如切换定位优先级或者提示用户 locationCheckRetryCount = 0 } } else { locationCheckRetryCount = 0 // 用户取消操作的处理逻辑 } } }
内容的提问来源于stack exchange,提问作者JacksOnF1re
相关产品推荐
相关产品推荐

