Как реализовать onConnectionFailed() и onDisconnected() для службы определения местоположения

Я использую Service, который реализует com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks и com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener

Служба должна загружать обновления местоположения на сервер каждую минуту при ее запуске. Я искал учебники для Google, но не могу найти хороших для своего сценария.

Методы, которые я не знаю, как реализовать:

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

    ...
}

Есть несколько руководств, предлагающих начать работу с connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);, но поскольку это Service (а не Activity), я не могу использовать этот метод. Я думал о передаче connectionResult в Intent в действие, но connectionResult не сериализуем.

и

@Override
public void onDisconnected() {

    ...
}

Можно ли снова вызвать LocationClient#connect() здесь?

Ответ 1

1. В onConnectionFailed():
Для "Я думал отправить connectionResult в Intent в действие, но connectionResult не сериализуем". Я думаю, что это может работать без этого следующим образом:

Вы можете вернуть int; ErrorCodes или Constants значение connectionResult и в зависимости от этого значения вы можете назначить дополнительные действия, просто передайте элемент управления своей активности/приложению.
От:
 http://developer.android.com/reference/com/google/android/gms/common/ConnectionResult.html

2. В onDisconnected(),
Вы можете уведомить пользователя о том, что "вы больше не получаете обновления местоположения" или другое настраиваемое сообщение в зависимости от вашего приложения, которое побуждает пользователя принять меры.
Если ваша служба входит onDisconnected() по какой-то причине, о которой мы не знаем, вызов locationClient.connect() снова может не помочь.

В обоих сценариях идея состоит в том, чтобы передать управление вашему приложению так где-то в вашей деятельности, оно может работать как точка принятия решения для потока управления.

Кроме того, вы упомянули "... но я не могу найти никаких хороших для моего сценария". так что описание вашего требования немного поможет вам больше. Соответственно отредактирует мой ответ.

Если его местоположение отправки будет обновлено до сервера, то также будет передано управление вашим агентом активности/приложения и подсказки для действий. (например, проверьте Settings на Location службы доступа)


Текущий сценарий для любого, кто смотрит этот вопрос/ответ
LocationClient больше не находится под com.google.android.gms.location, см.

Службы Android для Android 6.5: LocationClient отсутствует

Ответ 2

Я не уверен, как это было в прошлом, но прямо сейчас (Marshmallow) ConnectionResult является логичным:

public final class ConnectionResult implements SafeParcelable

Зная это, вы можете отправить его в дополнение к Intent:

@Override
public void onConnectionFailed(final ConnectionResult result) {
    Log.w(LOG_TAG, "Connecting to Google Play Services failed. Result=" + result);
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        @Override
        public void run() {
            Intent intent = new Intent(context, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtra(INTENT_EXTRA_CONNECTION_RESULT, connectionResult);
            context.startActivity(intent);
        }
    });
}

Затем MainActivity (или любое другое действие) может показывать пользователю правильные разрешения или диалоговые сообщения:

Parcelable connectionResultExtra = activity.getIntent().getParcelableExtra(INTENT_EXTRA_CONNECTION_RESULT);
    if (connectionResultExtra != null) {
        ConnectionResult connectionResult = (ConnectionResult) connectionResultExtra;
        if (connectionResult.hasResolution()) {
            try {
                connectionResult.startResolutionForResult(activity, 1234567890);
            } catch (IntentSender.SendIntentException e) {
                Log.e(LOG_TAG, "Unable to resolve ConnectionResult", e);
            }
        } else {
            int availabilityCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(activity);
            if (availabilityCode != 0) {
                Dialog errorDialog = GoogleApiAvailability.getInstance().getErrorDialog(activity, availabilityCode, 123);
                errorDialog.show();
        }
    }

Надеюсь, это поможет.

Ответ 3

  • Метод "OnConnectionFailed()" вызывается, когда вы вызываете "yourLocationClient.connect()" и LocationClient не удается подключиться к службам местоположения Google Play.

  • В методе "startResolutionForResult (Activity activity, int requestCode)" первый параметр является классом Activity, поэтому материал, связанный с пользовательским интерфейсом, должен всплывать по самой активности. Вам следует попробовать указать имя класса Activity, где вы хотите показать результат разрешения. (Я не уверен, но вы можете попробовать)

  • Если точка 2 не работает, вы всегда можете отправить трансляцию активности с помощью "int" в качестве дополнительной. Здесь int означает тип ошибки, который вы получаете внутри 'connectionResult'.

  • Если вы хотите, чтобы ваш клиент был подключен все это время, вы можете вызвать 'onConnected()' внутри 'onDisconnected()', хотя он не отключается, пока вы явно не вызовете 'disconnect()'.

  • Если вы хотите, чтобы ваша служба работала все время, даже если пользователь закрывает приложение из лотка приложения, обязательно проверьте эту ссылку.

Самое главное:

Если вы используете Google Play Services в своем приложении, вы должны проверить наличие услуг, когда приложение запускается в первый раз. Даже до того, как начнется какая-либо услуга или вы перейдете к основной деятельности. Вы можете сделать это при любой пустой активности/активности после регистрации/после всплеска.

Ответ 4

Вот лучший ответ:

ConnectionResult не является исчерпывающим, но он имеет конструктор, который принимает код errorCode и pendingIntent. Оба эти варианта являются обоснованными.

Итак, в вашем сервисе:

private void notifyUiFailedConnection(ConnectionResult result) {
    Intent intent = new Intent(FIT_NOTIFY_INTENT);
    intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE, result.getErrorCode());
    intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_INTENT, result.getResolution());
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

В вашей деятельности:

private BroadcastReceiver mFitStatusReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Get extra data included in the Intent
        if (intent.hasExtra(GoogleFitService.FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE) &&
                intent.hasExtra(GoogleFitService.FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE)) {
            //Recreate the connection result
            int statusCode = intent.getIntExtra(GoogleFitService.FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE, 0);
            PendingIntent pendingIntent = intent.getParcelableExtra(GoogleFitService.FIT_EXTRA_NOTIFY_FAILED_INTENT);
            ConnectionResult result = new ConnectionResult(statusCode, pendingIntent);
            fitHandleFailedConnection(result);
        }
    }
};

Ответ 5

реализовать недействительный список подключений в вашей службе и переопределить его метод, например:

public class yourService extends Service implements 
    LocationListener, OnConnectionFailedListener {

@Override
public void onConnectionFailed(ConnectionResult arg0) {

}

}