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

使用Google Fused Location API切换服务时App崩溃求助

问题:切换Google Fused Location API服务时App崩溃

我在App中使用Google Fused Location API,包含两个核心Service:

  • BackgroundService:每2分钟追踪一次位置,用于检测用户是否移动50米以识别行程;
  • TripStartedService:每10秒追踪一次位置,当用户移动超过50米时启用。

目前服务启动和位置获取均正常,但关闭TripStartedService并重新启动BackgroundService以检测新行程时,App崩溃,抛出如下异常:

FATAL EXCEPTION: main
Process: com.com.xxxxx.xxxxxxx, PID: 31551
java.lang.RuntimeException: Unable to stop service com.com.xxxxx.xxxxxxx.services.BackgroundLocationService@74441c6: java.lang.IllegalStateException: GoogleApiClient is not connected yet.
at android.app.ActivityThread.handleStopService(ActivityThread.java:3060)
at android.app.ActivityThread.-wrap21(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5438)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:762)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)
Caused by: java.lang.IllegalStateException: GoogleApiClient is not connected yet.
at com.google.android.gms.internal.zzaaj.zzb(Unknown Source)
at com.google.android.gms.internal.zzaan.zzb(Unknown Source)
at com.google.android.gms.internal.zzaal.zzb(Unknown Source)
at com.google.android.gms.internal.zzarl.removeLocationUpdates(Unknown Source)
at com.xxxxx.xxxxxxx.services.BackgroundLocationService.stopLocationUpdates(BackgroundLocationService.java:103)
at com.xxxxx.xxxxxxx.services.BackgroundLocationService.onDestroy(BackgroundLocationService.java:134)
at android.app.ActivityThread.handleStopService(ActivityThread.java:3041)
at android.app.ActivityThread.-wrap21(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5438)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:762)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)

异常明确出现在BackgroundLocationService的onDestroy方法调用stopLocationUpdates()时。

BackgroundService代码

public class BackgroundLocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
protected static final String TAG = "BackService";
public static long UPDATE_INTERVAL_IN_MILLISECONDS = 1000*2;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
public GoogleApiClient mGoogleApiClient;
public LocationRequest mLocationRequest;
private PendingIntent mPendingIntent;
IBinder mBinder = new LocalBinder();
private class LocalBinder extends Binder {
public BackgroundLocationService getServerInstance() {
return BackgroundLocationService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate()");
Intent mIntentService = new Intent(this, LocationUpdates.class);
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, PendingIntent.FLAG_UPDATE_CURRENT);
buildGoogleApiClient();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (mGoogleApiClient.isConnected()) {
Log.i(TAG + " onStartCmd", "Connected");
return START_STICKY;
}
if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting()) {
Log.i(TAG + " onStartCmd", "GoogleApiClient not Connected");
mGoogleApiClient.connect();
}
return START_STICKY;
}
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
createLocationRequest();
}
protected void createLocationRequest() {
Log.i(TAG, "createLocationRequest()");
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
protected void startLocationUpdates() {
Log.i(TAG, "Started Location Updates");
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.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mPendingIntent);
}
public void stopLocationUpdates() {
Log.i(TAG, "Stopped Location Updates");
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mPendingIntent);
}
@Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "Connected to GoogleApiClient");
startLocationUpdates();
}
@Override
public void onLocationChanged(Location location) {
String message = "Latitude : " + location.getLatitude() + "\n Longitude : " + location.getLongitude() + "\n location Accuracy: " + location.getAccuracy() + "\n speed: " + location.getSpeed();
Log.d(TAG, "onLocationChanged: " + message);
}
@Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
@Override
public void onDestroy() {
super.onDestroy();
stopLocationUpdates();
}
}

切换服务的逻辑代码

//This Code clock will return true if Trip completed Successfully.
if (trip_counts > (TRIP_COMPLETION_CHECK_INTERVAL * NUMBER_OF_LOCATION_FETCH_IN_MINUTE) && trip_counts % NUMBER_OF_LOCATION_FETCH_IN_MINUTE == 0) {
float total_distance = database.getTotalDistance();
Log.e("Distance", "calculateTrip: " + total_distance);
if (total_distance < ACTIVE_TRIP_MIN_DISTANCE) {
Log.d("TRIP STATUS", "calculateTrip: Trip Stopped !!!");
Date date_local = new Date();
SimpleDateFormat sdf_format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
sdf_format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date gmt = new Date(sdf_format.format(date_local));
String utc_time = sdf_format.format(gmt);
database.updateTripHistory("", MethodUtils.epochTimeConvert(utc_time), TripStatus.TRIP_COMPLETED);
NotificationManager notificationManager = (NotificationManager) activity.getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder notification = new NotificationCompat.Builder(activity);
notification.setContentTitle("TITLE");
notification.setContentText("\n Trip Completed...");
notification.setSmallIcon(R.drawable.big_marker);
notificationManager.notify(4321, notification.build());
activity.stopService(new Intent(activity, TripStartedService.class));
Log.i("Stoped Trip Srvce ", "calculateTrip: ");
Log.i("Stoped Trip Srvce ", "================== Started BackGroundService Again: ============ ");
activity.startService(new Intent(activity, BackgroundLocationService.class));
Log.i("Started BG Track Srvce", "calculateTrip: ");
//Delete extra rows
//SELECT _id FROM trip_started order by _id desc limit 1 offset 5-1;
}
}
Log.e("Trip Database Rows Size", "" + trip_counts + "\t \tBackGroundTable Rows : " + back_counts + "\tGPS>>>;: " + Boolean.toString(isGpsEnabled));
activity.stopService(new Intent(activity, BackgroundLocationService.class));
} catch (Exception e) {
e.printStackTrace();
}

问题分析与解决方案

问题根源

崩溃的核心原因是:当你调用stopService销毁BackgroundLocationService时,onDestroy方法直接调用了stopLocationUpdates(),但此时mGoogleApiClient可能处于未连接状态(比如连接异步未完成、之前连接已断开),直接调用LocationServices.FusedLocationApi.removeLocationUpdates()就会触发IllegalStateException。

解决方案1:在stopLocationUpdates中添加连接状态检查

修改stopLocationUpdates()方法,先判断mGoogleApiClient的连接状态,仅在已连接时执行移除操作:

public void stopLocationUpdates() {
    Log.i(TAG, "Stopped Location Updates");
    // 先验证GoogleApiClient的有效性和连接状态
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mPendingIntent);
    }
}

解决方案2:完善Service生命周期中的GoogleApiClient管理

在onDestroy中不仅停止位置更新,还要妥善断开GoogleApiClient的连接,避免资源泄漏:

@Override
public void onDestroy() {
    super.onDestroy();
    stopLocationUpdates();
    // 断开GoogleApiClient连接(如果存在且已连接)
    if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
        mGoogleApiClient.disconnect();
    }
}

额外优化:避免重复连接GoogleApiClient

你的buildGoogleApiClient()方法中直接调用了mGoogleApiClient.connect(),而onStartCommand中也有连接逻辑,这可能导致重复连接请求。可以移除buildGoogleApiClient()中的connect()调用,统一由onStartCommand管理连接:

protected synchronized void buildGoogleApiClient() {
    Log.i(TAG, "Building GoogleApiClient");
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    createLocationRequest();
    // 移除这里的mGoogleApiClient.connect(),交给onStartCommand处理
}

通过以上修改,就能避免在GoogleApiClient未连接时执行位置更新移除操作,解决崩溃问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:38:37