Android - экземпляр GoogleApiClient потерян между .connect() и onConnected() в IntentService

Я пытаюсь управлять запуском и остановкой обновлений местоположения (и других связанных операций) из IntentService, вызванного изменениями включенного состояния GPS. Проблема возникает из-за того, что метод .connect() в GoogleApiClient выполняется асинхронно, что позволяет службе «умирать». К моменту получения обратного вызова для onConnected() статическая глобальная переменная mGoogleApiClient уже стерта. Для removeLocationUpdates() я получаю:

java.lang.NullPointerException: GoogleApiClient must not be null

и для requestLocationUpdates() я получаю:

java.lang.IllegalStateException: GoogleApiClient is not connected yet.

Как правильно сохранить экземпляр GoogleApiClient (который является обязательным параметром как для методов запроса, так и для методов удаления) между смертью и возрождением IntentService? Или, если это неправильный вопрос, как правильно выполнить то, что я пытаюсь сделать?

EDIT (19APR15): Вот соответствующие разделы кода...

Из моего класса, расширяющего WakefulBroadcastReceiver, который прослушивает события GPS:

public void onReceive(Context context, Intent intent) {
    // If user enables or disables GPS
    if(intent.getAction().equals(LocationManager.MODE_CHANGED_ACTION) || intent.getAction().equals(LocationManager.PROVIDERS_CHANGED_ACTION)) {
        Intent mIntent = new Intent(context, ActivationIntentService.class);
        mIntent.putExtra("enabled", isGPSEnabled(context));
        startWakefulService(context, mIntent);
    }
}

Из класса ActivationIntentService, который получает намерение, переданное от startWakefulService:

@Override
protected void onHandleIntent(Intent intent) {
    if (intent != null) {
        this.intent = intent;
        if(intent.hasExtra("enabled")) {
            if(intent.getBooleanExtra("enabled", false)) {
                buildGoogleApiClient();
            }
            else {
                stopUpdates();
            }
        }
    }
}

protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .addApi(ActivityRecognition.API)
            .build();
    mGoogleApiClient.connect();
}

protected LocationRequest getLocationRequest() {
    LocationRequest mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(5000);
    mLocationRequest.setFastestInterval(1000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    return mLocationRequest;
}

@Override
public void onConnected(Bundle bundle) {
    startLocationUpdates();
    startActivityRecognitionUpdates();
    ActivationReceiver.completeWakefulIntent(intent);
}

public void stopUpdates() {
    PendingIntent locationPendingIntent = PendingIntent.getService(this, 1, new Intent(this, LocationIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
    LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,locationPendingIntent);
    PendingIntent activityRecognitionPendingIntent = PendingIntent.getService(this, 2, new Intent(this, ActivityRecognitionIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
    ActivityRecognition.ActivityRecognitionApi.removeActivityUpdates(mGoogleApiClient,activityRecognitionPendingIntent);
}

public void startLocationUpdates() {
    PendingIntent locationPendingIntent = PendingIntent.getService(this, 1, new Intent(this, LocationIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, getLocationRequest(), locationPendingIntent);
}

public void startActivityRecognitionUpdates() {
    PendingIntent activityRecognitionPendingIntent = PendingIntent.getService(this, 2, new Intent(this, ActivityRecognitionIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
    ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGoogleApiClient, 5000, activityRecognitionPendingIntent);
}

person Phyxius81    schedule 19.04.2015    source источник
comment
Можете ли вы показать свой код? Я только что завершил проект с использованием API плавного определения местоположения сервисов Google Play. Один ключ заключается в том, что перед вызовом requestLocationUpdates() и removeLocationUpdates() я проверил, что GoogleApiClient не равно нулю и подключено.   -  person Daniel Nugent    schedule 19.04.2015
comment
Я добавлю соответствующие части кода, чтобы вы могли его увидеть. Однако на данном этапе было бы бессмысленно проверять, является ли клиент нулевым. В этой текущей настройке он всегда будет нулевым, поэтому мне не нужно его проверять.   -  person Phyxius81    schedule 19.04.2015


Ответы (1)


Мое первое подозрение было правильным. Я пытался решить неправильную проблему.

После подробной отладки путем отслеживания почти каждого вызова метода я понял, что система по какой-то причине дважды транслировала изменение режима GPS, так что второй экземпляр GoogleApiClient был создан (перезаписывая первый экземпляр) к тому времени, когда был запущен первый обратный вызов onConnected из первый вызов .connect(). Вторая (не подключенная) клиентская переменная использовалась вместо первой для моих методов запуска или остановки обновлений, что вызывало исключение. Поскольку система запускает две трансляции КАЖДЫЙ раз, когда пользователь включает или отключает GPS (мне это кажется глупым), я устанавливаю флаг в BroadcastReceiver, чтобы игнорировать вторую. Проблема решена.

person Phyxius81    schedule 20.04.2015
comment
С тех пор я нашел лучший способ. Единственная причина для асинхронного подключения клиента — предотвращение блокировки потока пользовательского интерфейса. Однако я изначально не выполнял эту задачу в потоке пользовательского интерфейса, поэтому нет причин беспокоиться об этом. Чтобы упростить задачу, я переключился на синхронный метод blockingConnect(), о существовании которого изначально даже не подозревал. Описание метода здесь: Developers.google.com/android/reference/com/google/android/gms/ - person Phyxius81; 08.06.2015