You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android无网络环境下后台持续获取经纬度更新异常问题

Android后台位置追踪无网络/无离线地图时停止更新的问题

我开发了一款Android位置追踪应用,要求后台每分钟保存用户坐标。在装有谷歌离线地图的设备上运行正常,但在既无离线地图也无网络的设备上,运行一段时间后会停止接收位置更新。我尝试了Google Fused API和基于GPS_Provider的LocationManager两种方案,都出现了相同问题。

以下是我的代码:

public class BackgroundLocationService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        initData();

    }


    //Location Callback
    private LocationCallback locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            super.onLocationResult(locationResult);

            Location currentLocation = locationResult.getLastLocation();
            lat= Double.toString(currentLocation.getLatitude());
            longit=Double.toString(currentLocation.getLongitude());

        }
    };


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {


        prepareForegroundNotification("");
        startLocationUpdates();

        return START_STICKY;
    }

    @SuppressLint("MissingPermission")
    private void startLocationUpdates() {
        mFusedLocationClient.requestLocationUpdates(this.locationRequest,
                this.locationCallback, Looper.myLooper());
    }

    private void prepareForegroundNotification(String msg) {

        if(msg.length()==0)
        {
            msg="HCM Location Tracking";
        }
        else {
            msg="HCM, "+msg;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel serviceChannel = new NotificationChannel(
                    "1",
                    msg,
                    NotificationManager.IMPORTANCE_HIGH
            );
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(serviceChannel);
        }
        Intent notificationIntent = new Intent(this, SplashActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,
                121,
                notificationIntent, PendingIntent.FLAG_IMMUTABLE);

        Notification notification = new NotificationCompat.Builder(this, "1")
                .setContentTitle(getString(R.string.app_name))
                .setContentTitle(msg)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pendingIntent)
                .build();
        startForeground(1, notification);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void initData() {

         locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, UPDATE_INTERVAL_IN_MILLISECONDS)
                .setWaitForAccurateLocation(false)
                .setMinUpdateIntervalMillis(UPDATE_INTERVAL_IN_MILLISECONDS) 
                .setMaxUpdateDelayMillis(UPDATE_INTERVAL_IN_MILLISECONDS)
                .build();

         mFusedLocationClient =
                LocationServices.getFusedLocationProviderClient(Global.getInstance());

          gpsTracker = new GPSTracker( this);
          getCoordinatesFromMangerHandler();

 

        locationSettings();

    }

    private void getCoordinatesFromMangerHandler() {
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                getCoordinatesFromManger();
                mHandler.postDelayed(this, CHECK_INTERVAL);
            }
        }, CHECK_INTERVAL);
    }

 
     private void getCoordinatesFromManger() {
 
        if(gpsTracker==null){
            gpsTracker = new GPSTracker( this);
        }
        gpsTracker.getLocation();

        lat= Double.toString(gpsTracker.getLatitude());
        longit=Double.toString(gpsTracker.getLongitude());

 
    }

    private void locationSettings() {

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(locationRequest);

        SettingsClient client = LocationServices.getSettingsClient(this);
        Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
        task.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
            @Override
            public void onSuccess(LocationSettingsResponse locationSettingsResponse) {

            }
        });

        task.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                if (e instanceof ResolvableApiException) {
                      try {
                        ResolvableApiException resolvable = (ResolvableApiException) e;
                     prepareForegroundNotification("Kindly enable Wi-Fi scanning and location.");

                    } catch (Exception sendEx) {
                    }
                }
            }
        });

    }



    @Override
    public void onDestroy() {
        super.onDestroy();

        Intent broadcastIntent = new Intent();
        broadcastIntent.setAction("restartservice");
        broadcastIntent.setClass(this, RestartUserActivity.class);
        this.sendBroadcast(broadcastIntent);
    }
}

问题原因分析

  • GPS信号与节电策略:无网络时,设备可能触发节电模式关闭GPS模块;或GPS长时间无法锁定卫星后,系统自动停止扫描以节省电量。
  • Fused API的网络依赖:即使设置了PRIORITY_HIGH_ACCURACY,Fused Location Provider仍依赖网络基站/Wi-Fi热点辅助定位,无网络时可能降低定位频率甚至停止更新。
  • Service稳定性不足:START_STICKY无法保证服务不被系统回收,广播重启机制在部分系统版本或厂商定制ROM中可能失效。
  • 重复定位逻辑冲突:代码同时运行Fused API回调和Handler定时调用GPS Tracker,两种逻辑抢占定位资源,导致系统限制定位服务。

修复方案

1. 优化定位请求配置

调整LocationRequest参数,确保无网络时GPS持续工作:

locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 60000) // 1分钟更新间隔
        .setWaitForAccurateLocation(false)
        .setMinUpdateIntervalMillis(50000) // 最小间隔设为50秒,避免频繁请求
        .setMaxUpdateDelayMillis(65000)
        .build();

如果需要强制仅使用GPS,可通过LocationSettingsRequest配置强制开启GPS优先模式。

2. 处理GPS定位超时与重试

在GPSTracker类中添加超时重试逻辑,避免GPS长时间无响应后停止工作:

// GPSTracker类中新增方法
public void restartGPS() {
    if (locationManager != null) {
        locationManager.removeUpdates(locationListener);
        // 重新注册GPS监听
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 0, locationListener, Looper.getMainLooper());
    }
}

3. 强化后台存活能力

  • 优化前台服务:将通知优先级设为IMPORTANCE_DEFAULT或IMPORTANCE_LOW,避免被系统判定为高耗电应用;同时确保通知持续可见,维持前台状态。
  • 申请电池优化豁免:引导用户将应用加入电池优化白名单,Android 6.0+可通过ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS发起请求。
  • 替换重启机制:用WorkManager或JobScheduler替代广播重启,这两种组件更适配Android后台调度规则,能更可靠地重启定位任务。

4. 移除重复定位逻辑

选择Fused API或LocationManager其中一种方案,避免资源冲突:

  • 保留Fused API则删除getCoordinatesFromMangerHandler及相关GPS Tracker代码。
  • 保留LocationManager则监听GPS状态广播,在GPS启用/禁用时及时调整定位逻辑。

5. 添加GPS状态监控

注册广播接收器监听GPS状态变化,及时处理GPS关闭/开启事件:

private BroadcastReceiver gpsStatusReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (LocationManager.PROVIDER_DISABLED_ACTION.equals(action)) {
            prepareForegroundNotification("GPS已关闭,请重新开启");
        } else if (LocationManager.PROVIDER_ENABLED_ACTION.equals(action)) {
            startLocationUpdates();
        }
    }
};

// 在onCreate中注册接收器
@Override
public void onCreate() {
    super.onCreate();
    initData();
    IntentFilter filter = new IntentFilter();
    filter.addAction(LocationManager.PROVIDER_ENABLED_ACTION);
    filter.addAction(LocationManager.PROVIDER_DISABLED_ACTION);
    registerReceiver(gpsStatusReceiver, filter);
}

// 在onDestroy中注销接收器
@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(gpsStatusReceiver);
    // 原有销毁逻辑...
}

内容的提问来源于stack exchange,提问作者Umair Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 01:36:00