应用关闭时使用FusedLocationProviderClient获取位置无回调问题排查
问题分析与解决方案
核心问题1:每次回调后主动终止了位置更新
你的doInBackground方法里调用了removeLocationUpdates(locationCallback),这会在第一次收到位置结果后,直接取消后续的位置更新请求。前台时你可能重启了服务或重新发起请求,但后台后没有触发新的请求,自然不会再收到onLocationResult回调。
修复方案:删除这行移除位置更新的代码,仅在用户关闭提醒、服务销毁等真正不需要监听位置的场景下,再调用removeLocationUpdates。
核心问题2:主线程被同步阻塞
在onLocationResult中调用task.execute().get(),get()方法会同步等待AsyncTask执行完成,而onLocationResult本身运行在主线程(你指定了Looper.getMainLooper()),这会导致主线程长时间阻塞。Android系统对后台服务的主线程阻塞有严格限制,一旦检测到无响应,可能暂停服务回调甚至回收资源,直接导致后续位置更新无法触发。
修复方案:
- 移除不必要的AsyncTask,提取经纬度的逻辑直接在
onLocationResult中完成,无需异步操作。 - 如果后续有耗时处理需求,使用
execute()而非execute().get(),避免阻塞主线程。
优化后的代码示例
修改后的onLocationResult逻辑:
LocationServices.getFusedLocationProviderClient(ServiceLocationNotification.this) .requestLocationUpdates(locationRequest, new LocationCallback() { @Override public void onLocationResult(@NonNull LocationResult locationResult) { // 直接在主线程处理位置结果,无需AsyncTask if (locationResult != null && !locationResult.getLocations().isEmpty()) { // 获取最新位置 Location latestLocation = locationResult.getLocations().get(locationResult.getLocations().size() - 1); currentLatLng = new LatLng(latestLocation.getLatitude(), latestLocation.getLongitude()); // 执行位置对比与通知推送逻辑 checkAndSendNotification(currentLatLng); } } }, Looper.getMainLooper());
同时可直接删除自定义的GetCurrentLocationAsyncTaskServiceLocationNotification类,该类的功能完全可以通过上述代码替代。
额外检查点
- 确认
locationRequest配置:检查setInterval、setFastestInterval是否设置合理的时间间隔,setPriority是否为PRIORITY_HIGH_ACCURACY(若需高精度定位),后台时系统可能降低定位频率,但不会完全停止。 - 确认前台服务状态:确保前台服务的通知持续显示,若通知被意外取消,服务会转为后台服务,Android 8.0+对后台服务的定位权限有严格限制,可能导致无法获取位置。
- 确认权限完整性:除
ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION外,Android 10+还需ACCESS_BACKGROUND_LOCATION权限,否则后台无法获取位置更新。
内容的提问来源于stack exchange,提问作者preno1221
相关产品推荐
相关产品推荐

