Android后台Location Service获取当前位置失效问题咨询
问题根因排查与修复方案
代码存在以下几个会导致后台/息屏后定位中断的问题:
- 前台服务通知构建逻辑缺失:
startForeground(LOCATION_SERVICE_id, builder.build());中的builder变量未做初始化,实际运行时这里会直接抛出异常,服务被系统回收 onStartCommand返回值错误:当前直接返回super.onStartCommand的默认值,前台定位服务需要返回START_STICKY,保证服务被意外杀掉后可以自动重启- 停止服务时未移除定位回调:
stopLocationService方法中没有执行removeLocationUpdates逻辑,会引发内存泄漏 - 权限与Manifest配置缺失:高版本Android系统需要额外配置后台定位权限、前台服务类型声明
- 定位请求配置问题:没有设置位置更新的最小位移阈值,部分系统会合并定位回调减少唤醒
具体修复步骤
- 补充前台服务通知构建逻辑,在
startLocationService方法中添加通知通道和通知实例构建代码 - 修改
onStartCommand返回值为START_STICKY - 修正
stopLocationService逻辑,添加移除定位回调的调用 - 检查Manifest配置:
- 确保添加了
ACCESS_BACKGROUND_LOCATION权限(Android 10及以上必填) - 在Service的注册节点中添加
android:foregroundServiceType="location"属性(Android 12及以上必填) - 如果targetSdk版本>=33,还需要动态申请
POST_NOTIFICATIONS权限,否则前台通知无法正常展示,服务会被系统回收
- 确保添加了
- 可按需设置定位请求的最小位移阈值,减少无效回调
修正后的完整代码参考
public class UpdateLocationService extends Service { private static final String TAG = "UpdateLocationService"; static final int LOCATION_SERVICE_id = 175; static final String ACTION_START_LOCATION_SERVICE = "startLocationService"; static final String ACTION_STOP_LOCATION_SERVICE = "stopLocationService"; private LocationCallback locationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult != null && locationResult.getLastLocation() != null) { double lat = locationResult.getLastLocation().getLatitude(); double lng = locationResult.getLastLocation().getLongitude(); Log.d(TAG, lat + ", " + lng); } super.onLocationResult(locationResult); } }; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @RequiresApi(api = Build.VERSION_CODES.O) private void startLocationService() { // 适配Android O及以上的通知通道 String channelId = "location_service_channel"; NotificationChannel channel = new NotificationChannel(channelId, "定位服务", NotificationManager.IMPORTANCE_LOW); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); Notification.Builder builder = new Notification.Builder(this, channelId) .setContentTitle("定位服务运行中") .setSmallIcon(R.mipmap.ic_launcher) // 替换为自身应用的图标 .setContentText("正在获取位置信息") .setPriority(Notification.PRIORITY_LOW); LocationRequest locationRequest = new LocationRequest(); locationRequest.setInterval(3000); locationRequest.setFastestInterval(2000); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // 最小位移1米才触发回调,可按需调整 locationRequest.setSmallestDisplacement(1); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } LocationServices.getFusedLocationProviderClient(this).requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()); startForeground(LOCATION_SERVICE_id, builder.build()); } private void stopLocationService() { LocationServices.getFusedLocationProviderClient(this).removeLocationUpdates(locationCallback); stopForeground(true); stopSelf(); } @RequiresApi(api = Build.VERSION_CODES.O) @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) { String action = intent.getAction(); if (action != null) if (action.equals(ACTION_START_LOCATION_SERVICE)){ startLocationService(); }else if (action.equals(ACTION_STOP_LOCATION_SERVICE)){ stopLocationService(); } } return START_STICKY; } }
内容的提问来源于stack exchange,提问作者vahid asghari
相关产品推荐
相关产品推荐

