Mit GoogleApiClient auf Google APIs zugreifen (eingestellt)

Sie können den GoogleApiClient („Google API-Client“) verwenden -Objekt, um auf die in der Bibliothek der Google Play-Dienste bereitgestellten Google APIs zuzugreifen (z. B. Google Log-in, Spiele und Drive). Der Google API-Client bietet eine gemeinsamen Einstiegspunkt für Google Play-Dienste und verwaltet das Netzwerk Verbindung zwischen dem Gerät des Nutzers und den einzelnen Google-Diensten.

Die neuere GoogleApi-Schnittstelle und ihre Implementierungen sind jedoch einfacher und sind die bevorzugte Methode für den Zugriff auf Play-Dienste-APIs. Siehe Auf Google APIs zugreifen.

In diesem Leitfaden erfahren Sie, wie Sie:

  • Verwalte deine Verbindung zu Google Play-Diensten automatisch.
  • Synchrone und asynchrone API-Aufrufe an beliebige Google Play-Dienste ausführen
  • Verwalten Sie Ihre Verbindung zu Google Play-Diensten manuell, wenn dies notwendig ist. Weitere Informationen finden Sie unter Manuell verwaltete Verbindungen.
<ph type="x-smartling-placeholder">
</ph>
Abbildung 1: Eine Abbildung, die zeigt, wie der Google API-Client ein Schnittstelle für die Verbindung mit den verfügbaren Google Play-Diensten und für Aufrufe von diesen Diensten, z. B. Google Play Spiele und Google Drive

Installieren Sie zuerst die Bibliothek der Google Play-Dienste (Version 15 oder höher). für Ihr Android SDK. Falls Sie dies noch nicht getan haben, folgen Sie der Anleitung unter Google Play Services SDK einrichten

Automatisch verwaltete Verbindung herstellen

Nachdem Ihr Projekt mit der Bibliothek der Google Play-Dienste verknüpft wurde, erstellen Sie eine Instanz von GoogleApiClient mit dem GoogleApiClient.Builder APIs in der onCreate() . Die GoogleApiClient.Builder -Klasse bietet Methoden, mit denen Sie die Google APIs, die Sie verwenden möchten, und die OAuth 2.0-Bereiche. Hier ist ein Codebeispiel, das ein GoogleApiClient-Instanz, die eine Verbindung zum Google Drive-Dienst herstellt:

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
    .enableAutoManage(this /* FragmentActivity */,
                      this /* OnConnectionFailedListener */)
    .addApi(Drive.API)
    .addScope(Drive.SCOPE_FILE)
    .build();

Sie können einem und demselben Nutzer mehrere APIs und Bereiche hinzufügen. GoogleApiClient durch Anhängen zusätzlicher Anrufe an addApi() und addScope().

Wichtig:Wenn Sie die Wearable API zusammen mit anderen APIs zu einem GoogleApiClient können Client-Verbindungsfehler auf Geräten auftreten, auf denen die Wear OS App nicht installiert ist. Bis vermeiden Sie Verbindungsfehler, rufen Sie die Methode addApiIfAvailable() auf und übergeben Sie Wearable-API, damit Ihr Client die fehlenden der API erstellen. Weitere Informationen findest du unter Auf die Wearable API zugreifen.

Zum Starten einer automatisch verwalteten Verbindung müssen Sie eine Implementierung für die OnConnectionFailedListener um nicht auflösbare Verbindungsfehler zu empfangen. Wenn Ihre automatisch verwalteten GoogleApiClient-Instanz versucht, eine Verbindung zu Google APIs herzustellen. Dies erfolgt automatisch. UI verwenden, um auflösbare Verbindungsfehler zu beheben (z. B. Google Play-Dienste aktualisiert werden muss. Wenn ein Fehler auftritt, der nicht erhalten Sie einen Anruf an onConnectionFailed()

Sie können auch eine optionale Implementierung für die ConnectionCallbacks-Schnittstelle angeben, wenn Ihre App wissen muss, wann die automatisch verwaltete Verbindung hergestellt oder unterbrochen wird. Beispiel: Ihre App ruft zum Schreiben von Daten in Google APIs auf. Diese sollten aufgerufen werden, nachdem die Methode onConnected() aufgerufen wurde.

Hier ist eine Beispielaktivität, bei der die Callback-Oberflächen implementiert und an den Google API-Client:

import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import gms.drive.*;
import android.support.v4.app.FragmentActivity;

public class MyActivity extends FragmentActivity
        implements OnConnectionFailedListener {
    private GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create a GoogleApiClient instance
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */,
                                  this /* OnConnectionFailedListener */)
                .addApi(Drive.API)
                .addScope(Drive.SCOPE_FILE)
                .build();

        // ...
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        // An unresolvable error has occurred and a connection to Google APIs
        // could not be established. Display an error message, or handle
        // the failure silently

        // ...
    }
}

Ihre GoogleApiClient-Instanz wird nach Ihrer Aktivität automatisch verbunden Anrufe bei onStart() und die Verbindung nach dem Anruf bei onStop() wird getrennt. Ihre App kann sofort Leseanfragen an Google APIs nach der Erstellung von GoogleApiClient, ohne Warten auf den Verbindungsaufbau.

Mit Google-Diensten kommunizieren

Nach der Verbindung kann Ihr Client Lese- und Schreibaufrufe mit den dienstspezifischen APIs für wie von den APIs und Bereichen angegeben, die Sie Ihrem GoogleApiClient-Instanz.

Hinweis:Bevor Sie bestimmte Google-Dienste anrufen können, müssen Sie möglicherweise zuerst Ihre in der Google Developers Console. Anweisungen finden Sie in den entsprechenden Anleitung für die von Ihnen verwendete API wie Google Drive oder Google Log-in:

Wenn Sie mit GoogleApiClient eine Lese- oder Schreibanfrage ausführen, gibt der API-Client ein PendingResult-Objekt zurück, das die Anfrage darstellt. Dies geschieht unmittelbar, bevor die Anfrage an den Google-Dienst gesendet wird, den Ihre App aufruft.

Hier ist z. B. eine Anfrage zum Lesen einer Datei aus Google Drive, die eine Objekt PendingResult:

Query query = new Query.Builder()
        .addFilter(Filters.eq(SearchableField.TITLE, filename));
PendingResult<DriveApi.MetadataBufferResult> result = Drive.DriveApi.query(mGoogleApiClient, query);

Nachdem Ihre App ein PendingResult-Objekt hat, Ihre Anwendung kann dann angeben, ob die Anfrage als asynchroner oder synchroner Aufruf verarbeitet werden soll.

Tipp:Ihre App kann Leseanfragen in die Warteschlange stellen, wenn sie nicht mit den Google Play-Diensten verbunden ist. Für Ihre App kann beispielsweise Methoden zum Lesen einer Datei aus Google Drive aufrufen, unabhängig davon, ob Ihre GoogleApiClient-Instanz noch verbunden ist. Nachdem eine Verbindung hergestellt wurde, werden Leseanfragen in der Warteschlange ausgeführt. Schreibanfragen erzeugen einen Fehler, wenn Ihre Anwendung aufruft Google Play-Dienste schreiben Methoden, während Ihr Google API-Client nicht verbunden ist.

Asynchrone Aufrufe verwenden

Um die Anfrage asynchron zu machen, rufen Sie setResultCallback() in der PendingResult und geben Sie Implementierung der ResultCallback-Oberfläche. Für Beispiel für die asynchron ausgeführte Anfrage:

private void loadFile(String filename) {
    // Create a query for a specific filename in Drive.
    Query query = new Query.Builder()
            .addFilter(Filters.eq(SearchableField.TITLE, filename))
            .build();
    // Invoke the query asynchronously with a callback method
    Drive.DriveApi.query(mGoogleApiClient, query)
            .setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() {
        @Override
        public void onResult(DriveApi.MetadataBufferResult result) {
            // Success! Handle the query result.
            // ...
        }
    });
}

Wenn Ihre App ein Result-Objekt empfängt, den onResult()-Callback Sie wird als Instanz der entsprechenden Unterklasse bereitgestellt, wie von der von Ihnen verwendeten API angegeben. zum Beispiel DriveApi.MetadataBufferResult

Synchrone Aufrufe verwenden

Wenn Ihr Code in einer streng definierten Reihenfolge ausgeführt werden soll, z. B. weil das Ergebnis einer -Aufruf als Argument für einen anderen erforderlich ist, können Sie Ihre Anfrage synchron machen, indem Sie Folgendes aufrufen: await() im PendingResult Dadurch wird der Thread blockiert und gibt das Result-Objekt zurück, wenn der abgeschlossen ist. Dieses Objekt wird als Instanz der entsprechenden Unterklasse geliefert, wie durch die Sie verwenden, um z. B. DriveApi.MetadataBufferResult

Weil beim Aufrufen von await() den Thread blockiert, bis das Ergebnis eintrifft, sollte Ihre Anwendung niemals synchrone Anfragen an Google APIs auf der UI-Thread. Ihre Anwendung kann mithilfe eines AsyncTask-Objekts einen neuen Thread erstellen und diesen Thread für die synchrone Anfrage verwenden.

Das folgende Beispiel zeigt, wie Sie einen synchronen Aufruf an Google Drive senden:

private void loadFile(String filename) {
    new GetFileTask().execute(filename);
}

private class GetFileTask extends AsyncTask {
    protected void doInBackground(String filename) {
        Query query = new Query.Builder()
                .addFilter(Filters.eq(SearchableField.TITLE, filename))
                .build();
        // Invoke the query synchronously
        DriveApi.MetadataBufferResult result =
                Drive.DriveApi.query(mGoogleApiClient, query).await();

        // Continue doing other stuff synchronously
        // ...
    }
}

Auf die Wearable API zugreifen

Die Wearable API bietet einen Kommunikationskanal für Apps, die auf Handheld- und Wearable-Geräten ausgeführt werden. Die API besteht aus einer Reihe von Datenobjekten, die das System senden und synchronisieren kann, und Listener, die Ihre Apps mithilfe einer Datenschicht über wichtige Ereignisse informieren. Die Die Wearable API ist auf Geräten mit Android 4.3 (API-Level 18) oder höher verfügbar, wenn ein Wearable-Gerät verbunden ist und die Wear OS-Companion-App auf dem Gerät installiert ist.

Eigenständige Wearable API verwenden

Wenn deine App die Wearable API, aber keine anderen Google APIs verwendet, kannst du diese API hinzufügen, indem du die Methode addApi() aufrufen. Das folgende Beispiel zeigt, wie Sie den Parameter Wearable API zu Ihrer GoogleApiClient-Instanz:

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
    .enableAutoManage(this /* FragmentActivity */,
                      this /* OnConnectionFailedListener */)
    .addApi(Wearable.API)
    .build();

Wenn die Wearable API nicht verfügbar ist, werden Verbindungsanfragen, Fehler beim Einbinden der Wearable API mit dem API_UNAVAILABLE Fehlercode angezeigt.

Das folgende Beispiel zeigt, wie Sie feststellen können, ob die Wearable API verfügbar ist:

// Connection failed listener method for a client that only
// requests access to the Wearable API
@Override
public void onConnectionFailed(ConnectionResult result) {
    if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) {
        // The Wearable API is unavailable
    }
    // ...
}

Wearable API mit anderen Google APIs verwenden

Wenn in deiner App die Wearable API zusätzlich zu anderen Google APIs verwendet wird, rufe die Methode addApiIfAvailable() und übergeben Sie die Wearable API, um zu prüfen, ob sie verfügbar ist. Mit dieser Prüfung kannst du dafür sorgen, dass deine App in Fällen, in denen die API nicht verfügbar ist, korrekt reagieren kann.

Das folgende Beispiel zeigt, wie Sie auf die Wearable API zusammen mit der Drive API:

// Create a GoogleApiClient instance
mGoogleApiClient = new GoogleApiClient.Builder(this)
        .enableAutoManage(this /* FragmentActivity */,
                          this /* OnConnectionFailedListener */)
        .addApi(Drive.API)
        .addApiIfAvailable(Wearable.API)
        .addScope(Drive.SCOPE_FILE)
        .build();

Im Beispiel oben kann der GoogleApiClient eine Verbindung zu Google Drive, ohne eine Verbindung zur Wearable API herzustellen, wenn sie nicht verfügbar ist. Nachher Sie verbinden Ihr GoogleApiClient Sorgen Sie dafür, dass die Wearable API verfügbar ist, bevor Sie die API-Aufrufe ausführen:

boolean wearAvailable = mGoogleApiClient.hasConnectedApi(Wearable.API);

API-Verbindungsfehler ignorieren

Wenn Sie addApi() anrufen und GoogleApiClient nicht Verbindung zu dieser API herstellen, schlägt der gesamte Verbindungsvorgang für diesen Client fehl und löst den onConnectionFailed()-Callback aus.

Sie können einen API-Verbindungsfehler so registrieren, dass er ignoriert wird. Verwenden Sie dazu addApiIfAvailable() Wenn eine API mit addApiIfAvailable() kann aufgrund eines nicht behebbaren Fehlers keine Verbindung herstellen (z. B. API_UNAVAILABLE für Wear), wird diese API aus dem GoogleApiClient entfernt und der Client fährt mit eine Verbindung zu anderen APIs herstellen. Schlägt jedoch eine API-Verbindung aufgrund eines behebbaren Fehlers (z. B. OAuth-Zustimmungs-Auflösungs-Intent), schlägt der Client-Verbindungsvorgang fehl. Wann? über eine automatisch verwaltete Verbindung vom GoogleApiClient um diese Fehler zu beheben. Bei Verwendung einer manuell verwalteten Verbindung Ein ConnectionResult mit einem Auflösungszweck ist an den onConnectionFailed()-Callback übergeben wurde. API Verbindungsfehler werden nur ignoriert, wenn es keine Lösung für den Fehler gibt. und die API wurde hinzugefügt mit addApiIfAvailable(). Informationen zum Implementieren eines manuellen Verbindungsfehlers finden Sie unter Verbindungsfehler beheben.

Da APIs mit addApiIfAvailable() ist möglicherweise nicht immer in der verbundenen GoogleApiClient-Instanz sollten Sie Aufrufe an diese APIs schützen, indem Sie eine Prüfung mit hasConnectedApi(). Um herauszufinden, warum ein bestimmte API konnte keine Verbindung herstellen, obwohl der gesamte Verbindungsvorgang für den Client erfolgreich war. Rufen Sie getConnectionResult() und rufen Sie den Fehlercode aus dem ConnectionResult-Objekt. Wenn Ihr Client eine API aufruft, obwohl dies nicht der Fall ist verbunden ist, schlägt der Aufruf mit dem Fehlercode API_NOT_AVAILABLE Statuscode enthalten.

Wenn für die API, die Sie über addApiIfAvailable() hinzufügen, ein oder Bereiche hinzufügen, fügen Sie diese als Parameter in der addApiIfAvailable() aufrufen, anstatt den Parameter addScope()-Methode. Bereiche, die mit diesem Ansatz hinzugefügt werden, werden möglicherweise nicht angefordert, Verbindung schlägt fehl, bevor die OAuth-Zustimmung eingeholt wird. Bereiche, die mit addScope() werden immer angefordert.

Manuell verwaltete Verbindungen

Im größten Teil dieses Leitfadens wird beschrieben, wie Sie die enableAutoManage-Methode zum Initiieren eines automatisch verwaltete Verbindung mit automatisch behobenen Fehlern. In fast Dies ist in jedem Fall die beste und einfachste Möglichkeit, über Ihr Konto eine Verbindung zu Google APIs herzustellen. Android-App Es gibt jedoch Situationen, in denen Sie ein manuell verwaltete Verbindung zu Google APIs in Ihrer App:

  • Um außerhalb einer Aktivität auf Google APIs zuzugreifen oder die Kontrolle über die API zu behalten Verbindung
  • So passen Sie die Behandlung und Lösung von Verbindungsfehlern an:

Dieser Abschnitt enthält Beispiele für diese und andere erweiterte Anwendungsfälle.

Manuell verwaltete Verbindung starten

Wenn Sie eine manuell verwaltete Verbindung zu GoogleApiClient herstellen möchten, müssen Sie eine Implementierung für die Callback-Schnittstellen angeben, ConnectionCallbacks und OnConnectionFailedListener. Diese Schnittstellen empfangen Callbacks als Antwort auf die asynchrone connect()-Methode, wenn der die Verbindung zu den Google Play-Diensten hergestellt wird, fehlschlägt oder unterbrochen wird.

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Drive.API)
            .addScope(Drive.SCOPE_FILE)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build()

Wenn Sie eine Verbindung manuell verwalten, müssen Sie die Methode connect() und disconnect() an den richtigen Stellen im Lebenszyklus Ihrer App. In einer Aktivität -Kontext wird empfohlen, connect() im onStart() Ihrer Aktivität aufzurufen und disconnect() in der onStop()-Methode Ihrer Aktivität. Die connect() und disconnect() Methoden werden bei Verwendung einer automatisch verwalteten Verbindung automatisch aufgerufen.

Wenn Sie GoogleApiClient verwenden, um eine Verbindung zu APIs herzustellen, für die Folgendes erforderlich ist: wie Google Drive oder Google Play Spiele, ist es wahrscheinlich, schlägt der erste Verbindungsversuch fehl und deine App erhält einen Anruf an onConnectionFailed() mit SIGN_IN_REQUIRED da das Nutzerkonto nicht angegeben wurde.

Verbindungsfehler beheben

Wenn deine App einen Anruf an die onConnectionFailed() empfängt sollten Sie hasResolution() anrufen. am angegebenen ConnectionResult -Objekt enthält. Wenn der Rückgabewert „true“ lautet, kann Ihre Anwendung den Nutzer auffordern, sofortige Maßnahmen zur Behebung des Fehlers zu ergreifen. startResolutionForResult() wird angerufen für das ConnectionResult-Objekt. Methode startResolutionForResult() sich in dieser Situation genauso verhält wie startActivityForResult(), und startet eine dem Kontext entsprechende Aktivität, die dem Nutzer hilft, den Fehler zu beheben (z. B. eine Aktivität, die dem Nutzer hilft, Konto auswählen).

Wenn hasResolution() gibt "false" zurück, sollte Ihre App GoogleApiAvailability.getErrorDialog() Fehlercode an diese Methode übergeben. Dadurch wird ein Dialog von Google Play zur Verfügung gestellt die für den Fehler relevant sind. Im Dialogfeld wird möglicherweise einfach eine Meldung angezeigt, oder eine Aktion zum Starten einer Aktivität enthalten, mit der der Fehler behoben werden kann. z. B. wenn der Nutzer eine neuere Version der Google Play-Dienste installieren muss.

Beispiel: Ihre onConnectionFailed() sollte jetzt so aussehen:

public class MyActivity extends Activity
        implements ConnectionCallbacks, OnConnectionFailedListener {

    // Request code to use when launching the resolution activity
    private static final int REQUEST_RESOLVE_ERROR = 1001;
    // Unique tag for the error dialog fragment
    private static final String DIALOG_ERROR = "dialog_error";
    // Bool to track whether the app is already resolving an error
    private boolean mResolvingError = false;

    // ...

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        if (mResolvingError) {
            // Already attempting to resolve an error.
            return;
        } else if (result.hasResolution()) {
            try {
                mResolvingError = true;
                result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
            } catch (SendIntentException e) {
                // There was an error with the resolution intent. Try again.
                mGoogleApiClient.connect();
            }
        } else {
            // Show dialog using GoogleApiAvailability.getErrorDialog()
            showErrorDialog(result.getErrorCode());
            mResolvingError = true;
        }
    }

    // The rest of this code is all about building the error dialog

    /* Creates a dialog for an error message */
    private void showErrorDialog(int errorCode) {
        // Create a fragment for the error dialog
        ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
        // Pass the error that should be displayed
        Bundle args = new Bundle();
        args.putInt(DIALOG_ERROR, errorCode);
        dialogFragment.setArguments(args);
        dialogFragment.show(getSupportFragmentManager(), "errordialog");
    }

    /* Called from ErrorDialogFragment when the dialog is dismissed. */
    public void onDialogDismissed() {
        mResolvingError = false;
    }

    /* A fragment to display an error dialog */
    public static class ErrorDialogFragment extends DialogFragment {
        public ErrorDialogFragment() { }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            // Get the error code and retrieve the appropriate dialog
            int errorCode = this.getArguments().getInt(DIALOG_ERROR);
            return GoogleApiAvailability.getInstance().getErrorDialog(
                    this.getActivity(), errorCode, REQUEST_RESOLVE_ERROR);
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            ((MyActivity) getActivity()).onDialogDismissed();
        }
    }
}

Nachdem der Nutzer das vom startResolutionForResult() oder schließt die Meldung von GoogleApiAvailability.getErrorDialog(), erhält Ihre Aktivität die onActivityResult() mit dem RESULT_OK Ergebniscode. Ihre App kann dann connect() noch einmal. Beispiel:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_RESOLVE_ERROR) {
        mResolvingError = false;
        if (resultCode == RESULT_OK) {
            // Make sure the app is not already connected or attempting to connect
            if (!mGoogleApiClient.isConnecting() &&
                    !mGoogleApiClient.isConnected()) {
                mGoogleApiClient.connect();
            }
        }
    }
}

Im Code oben ist Ihnen wahrscheinlich der boolesche Wert mResolvingError aufgefallen. So wird erfasst, App-Status, während der Nutzer den Fehler behebt, um wiederholte Versuche zu vermeiden Fehler. Während das Dialogfeld für die Kontoauswahl angezeigt wird, kann der Nutzer SIGN_IN_REQUIRED Fehler enthält, kann der Nutzer den Bildschirm drehen. Dadurch werden Ihre Aktivitäten wiederhergestellt onStart()-Methode und ruft dann connect() noch einmal. Dieses zu einem weiteren Aufruf an startResolutionForResult(), Dadurch wird vor dem vorhandenen Dialogfeld für die Kontoauswahl ein weiteres Dialogfeld geöffnet.

Dieser boolesche Wert erfüllt nur dann seinen beabsichtigten Zweck, wenn er über Aktivitätsinstanzen hinweg bestehen bleibt. Im nächsten Abschnitt wird erläutert, wie du den Fehlerbehandlungsstatus deiner App trotz anderer Nutzeraktionen beibehalten kannst. oder Ereignisse, die auf dem Gerät auftreten.

Status beim Beheben eines Fehlers beibehalten

Um zu vermeiden, dass der Code onConnectionFailed() Während ein vorheriger Versuch zur Behebung eines Fehlers läuft, müssen Sie einen booleschen Wert beibehalten, verfolgt, ob Ihre App bereits versucht, einen Fehler zu beheben.

Wie im Codebeispiel oben gezeigt, sollte Ihre App bei jedem Aufruf einen booleschen Wert auf true festlegen. startResolutionForResult() oder zeigt das Dialogfeld vom GoogleApiAvailability.getErrorDialog() Wenn Ihre App dann RESULT_OK im onActivityResult() den booleschen Wert auf false fest.

Um den booleschen Wert bei Neustarts von Aktivitäten (z. B. wenn der Nutzer den Bildschirm dreht) zu verfolgen, Speichern Sie den booleschen Wert in den gespeicherten Instanzdaten der Aktivität mit onSaveInstanceState():

private static final String STATE_RESOLVING_ERROR = "resolving_error";

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(STATE_RESOLVING_ERROR, mResolvingError);
}

Stellen Sie dann den gespeicherten Zustand wieder her, onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // ...
    mResolvingError = savedInstanceState != null
            && savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false);
}

Jetzt können Sie Ihre App sicher ausführen und manuell eine Verbindung zu den Google Play-Diensten herstellen.