FusedLocationProviderClient前台服务停止接收位置更新问题求助
问题排查方向与解决思路
1 权限验证类排查
- 确认应用是否申请了
ACCESS_BACKGROUND_LOCATION权限(Android 10及以上强制要求后台运行的应用获取位置时申请该权限,且用户必须手动选择「始终允许」位置权限,选「仅使用期间允许」的话,应用退到后台、服务被重启后就拿不到位置更新,和你描述的手动点击图标启动才恢复的现象完全吻合) - 检查小米、华为、vivo等国产厂商的定制权限管控:是否给应用开放了「自启动权限」、「后台运行权限」、「位置信息耗电白名单」,部分厂商会在应用退后台10~30分钟后强制切断位置更新的回调,只有前台启动应用时才会临时放开限制
- 服务重启、开机广播触发时,主动调用权限检查接口,不要只靠catch
SecurityException,因为部分厂商的权限管控不会抛出该异常,只是静默拦截位置回调,你当前的代码里没有主动校验权限的逻辑,isRequestingUpdates会被错误标记为true,后续即使权限恢复也不会重新请求位置更新
2 Fused Location API使用逻辑排查
- 你的代码里
isRequestingUpdates标记一旦设为true,哪怕位置请求实际被系统拦截、回调失效,也不会再重新发起请求,建议每次服务启动(包括远程重启、开机自启的场景)时,强制重置isRequestingUpdates为false,再重新调用requestLocationUpdates,避免标记位异常导致请求不触发 - 确认
mLocationRequest的配置:interval、fastestInterval不要设置过大,priority建议使用PRIORITY_HIGH_ACCURACY,如果设为低功耗模式,系统会大幅降低位置更新频率甚至完全停止回调 - 每次发起位置请求前,先调用
LocationSettingsRequest校验设备的位置开关是否开启、定位模式是否满足要求,部分场景下系统会自动关闭位置开关,或者用户修改定位模式为仅网络/仅GPS,不符合请求要求时也会静默失败,你当前的代码没有做配置校验,看不到这类异常 - 给
mFusedLocationClient.requestLocationUpdates返回的Task添加失败回调,不要只catchSecurityException,系统返回的其他错误(比如Google Play服务版本过低、位置服务不可用)都会导致请求失败,你当前的代码没有捕获这类异常,也没有重置isRequestingUpdates标记 - 确认
Looper.myLooper()对应的线程是否是长期存活的线程,如果是子线程的Looper,线程销毁后位置回调就会停止,建议使用Looper.getMainLooper()来接收位置回调,避免线程销毁导致回调丢失
3 前台服务生命周期相关排查
- 确认前台服务的通知是否符合Android 12及以上的要求:必须设置正确的通知渠道、调用
startForeground的时机不能晚于服务启动后5秒,否则系统会强制杀死服务,连带位置回调也会被清理 - 远程杀死服务再重启的场景,确认重启后的服务确实成功走到了前台服务的逻辑,没有被系统判定为后台服务而被拦截,建议在服务的
onCreate、onStartCommand里加埋点日志,确认位置请求的代码确实被执行到了 - 开机广播触发后,部分Android版本会有1030秒的后台启动限制,这时候启动的服务如果还没走到`startForeground`就发起位置请求,会被系统拦截,建议延迟510秒再发起位置更新请求
- 确认应用没有被系统加入电池优化名单,加入后系统会限制后台的位置更新频率,甚至停止回调,建议引导用户把应用加入电池优化白名单
内容的提问来源于stack exchange,提问作者Jônatas David Hübner
相关产品推荐
相关产品推荐

