Dostęp do interfejsów API Google za pomocą GoogleApiClient (wycofany)

GoogleApiClient („Klient interfejsu API Google”) dostęp do interfejsów API Google udostępnianych w bibliotece Usług Google Play (takich jak Logowanie przez Google, Gry czy Dysk). Klient interfejsów API Google zapewnia wspólny punkt wejścia do Usług Google Play i zarządza siecią między urządzeniem użytkownika a poszczególnymi usługami Google.

Jednak nowszy interfejs GoogleApi i jego implementacje są łatwiejsze do wdrożenia i są preferowanym sposobem dostępu do interfejsów API Usług Google Play. Zapoznaj się z artykułem Uzyskiwanie dostępu do interfejsów API Google.

Z tego przewodnika dowiesz się, jak:

  • Automatycznie zarządzaj połączeniem z Usługami Google Play.
  • Wykonywanie synchronicznych i asynchronicznych wywołań interfejsu API do dowolnych Usług Google Play.
  • ręcznie zarządzać połączeniem z Usługami Google Play w tych rzadkich przypadkach, niezbędną. Więcej informacji znajdziesz w artykule Połączenia zarządzane ręcznie.
Rysunek 1. Ilustracja pokazująca, jak klient API Google udostępnia interfejsu do łączenia się z usługami Google Play i nawiązywania połączeń z nimi, takich jak Gry Google Play i Dysk Google.

Na początek zainstaluj bibliotekę usług Google Play (wersja 15 lub nowsza) dla pakietu Android SDK. W razie potrzeby wykonaj czynności opisane w Skonfiguruj pakiet SDK Usług Google Play.

Uruchamianie połączenia zarządzanego automatycznie

Po połączeniu projektu z biblioteką Usług Google Play utwórz instancję usługi GoogleApiClient za pomocą GoogleApiClient.Builder Interfejsy API w Twoich aktywnościach onCreate() . GoogleApiClient.Builder klasa udostępnia metody umożliwiające określenie interfejsów API Google, których chcesz użyć, Zakresy protokołu OAuth 2.0. Oto przykładowy kod, który tworzy Instancja GoogleApiClient łącząca się z usługą Dysk Google:

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

Do jednego zestawu możesz dodać wiele interfejsów API i wiele zakresów. GoogleApiClient dołączając dodatkowe wywołania do addApi() i addScope().

Ważne: jeśli dodajesz interfejs API Wearable razem z innymi interfejsami API do GoogleApiClient na urządzeniach, które działają, mogą wystąpić błędy połączenia z klientem nie mają zainstalowanej aplikacji Wear OS. Do uniknąć błędów połączenia, wywołaj metodę addApiIfAvailable() i przekaż ją interfejs API Wearable, aby umożliwić klientowi sprawną obsługę brakujących API. Więcej informacji znajdziesz w artykule na temat uzyskiwania dostępu do interfejsu Wearable API.

Aby rozpocząć automatycznie zarządzane połączenie, musisz podać wdrożenie w narzędziu OnConnectionFailedListener może otrzymywać nierozwiązane błędy połączenia. Gdy Twoje konto będzie zarządzane automatycznie Instancja GoogleApiClient próbuje połączyć się z interfejsami API Google, automatycznie interfejsu wyświetlacza, aby spróbować naprawić możliwe błędy połączeń (na przykład Usługi Google Play wymagają aktualizacji). Jeśli wystąpi błąd, którego nie można rozwiązany, zadzwonimy pod numer onConnectionFailed()

Możesz też określić opcjonalną implementację interfejsu ConnectionCallbacks, jeśli aplikacja musi wiedzieć, kiedy nawiązano lub zawieszone jest automatycznie zarządzane połączenie. Jeśli na przykład: aplikacja wykonuje wywołania do zapisu danych w interfejsach API Google, które powinny być wywoływane dopiero po wywołaniu metody onConnected().

Oto przykładowe działanie, które implementuje interfejsy wywołania zwrotnego oraz dodaje i przekaż je do klienta interfejsu API Google:

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

        // ...
    }
}

Instancja GoogleApiClient połączy się automatycznie po Twojej aktywności zadzwoni do: onStart() i rozłącz po rozmowie onStop(). Aplikacja może od razu zacząć tworzyć żądania odczytu do interfejsów API Google po skompilowaniu GoogleApiClient, bez oczekiwanie na zakończenie połączenia.

Komunikacja z usługami Google

Po nawiązaniu połączenia klient będzie mógł wykonywać wywołania odczytu i zapisu za pomocą interfejsów API dotyczących konkretnej usługi w które zostały autoryzowane przez aplikację, zgodnie z interfejsami API i zakresami dodanymi do GoogleApiClient.

Uwaga: zanim zaczniesz dzwonić do określonych usług Google, być może musisz najpierw zarejestrować w Google Developer Console. Instrukcje znajdziesz w odpowiednich dla używanego interfejsu API, np. Dysk Google lub Logowanie przez Google.

Gdy wykonujesz żądanie odczytu lub zapisu przy użyciu GoogleApiClient, klient interfejsu API zwraca obiekt PendingResult, który reprezentuje żądanie. Dzieje się to natychmiast przed dostarczeniem żądania do usługi Google, z której wywołuje Twoja aplikacja.

Oto przykładowa prośba o odczytanie pliku z Dysku Google, który zawiera Obiekt PendingResult:

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

Gdy aplikacja będzie miała obiekt PendingResult, aplikacja może następnie określić, czy żądanie ma być obsługiwane jako wywołanie asynchroniczne czy synchroniczne.

Wskazówka: aplikacja może dodawać do kolejki żądania odczytu, gdy nie jest połączona z Usługami Google Play. Dla: na przykład aplikacja może wywoływać metody odczytu plików z Dysku Google niezależnie od tego, czy instancja GoogleApiClient jest jeszcze połączona. Po nawiązaniu połączenia wykonywane są żądania odczytu umieszczone w kolejce. Jeśli aplikacja wywoła żądanie, żądania zapisu generują błąd Usługi Google Play zapisują metody, gdy klient interfejsu API Google nie jest połączony.

Używanie wywołań asynchronicznych

Aby ustawić żądanie jako asynchroniczne, wywołaj funkcję setResultCallback() w: PendingResult i podaj implementacji Interfejs ResultCallback. Dla: Oto żądanie wykonane asynchronicznie:

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.
            // ...
        }
    });
}

Gdy aplikacja otrzyma obiekt Result w wywołanie zwrotne onResult(), jest dostarczana jako instancja odpowiedniej podklasy określonej przez używany interfejs API; na przykład DriveApi.MetadataBufferResult.

Korzystanie z wywołań synchronicznych

Jeśli chcesz, aby Twój kod był wykonywany w ściśle zdefiniowanej kolejności, np. dlatego, że w wyniku działania jednego z nich jest potrzebne jako argument dla innego, możesz ustawić żądanie jako synchroniczne, wywołując await() PendingResult Spowoduje to zablokowanie wątku i zwraca obiekt Result, gdy . Ten obiekt jest dostarczany jako instancja odpowiedniej podklasy określonej przez interfejsu API, którego używasz, np. DriveApi.MetadataBufferResult

Bo dzwonię pod numer await() zablokuje wątek do czasu uzyskania wyniku, aplikacja nie powinna nigdy wysyłać żądań synchronicznych do interfejsów API Google Wątek interfejsu. Aplikacja może utworzyć nowy wątek przy użyciu obiektu AsyncTask i użyć tego wątku do wykonania żądania synchronicznego.

Poniższy przykład pokazuje, jak wysłać żądanie pliku do Dysku Google w ramach wywołania synchronicznego:

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
        // ...
    }
}

Uzyskaj dostęp do interfejsu Wearable API

Interfejs Wearable API zapewnia kanał komunikacji dla aplikacji działających na urządzeniach mobilnych i urządzeniach do noszenia. Interfejs API składa się ze zbioru obiektów danych, które system może wysyłać i synchronizować oraz detektorów, które powiadamiają aplikacje o ważnych zdarzeniach za pomocą warstwy danych. Interfejs Wearable API jest dostępny na urządzeniach z Androidem 4.3 (poziom interfejsu API 18) lub nowszym, połączone urządzenie do noszenia i aplikacja towarzysząca dla Wear OS jest zainstalowana na urządzeniu.

Korzystanie z samodzielnego interfejsu Wearable API

Jeśli Twoja aplikacja korzysta z interfejsu Wearable API, ale nie z innych interfejsów API Google, możesz go dodać przez wywołanie metody addApi(). Poniższy przykład pokazuje, jak dodać Wearable API do instancji GoogleApiClient:

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

Jeśli interfejs Wearable API jest niedostępny, połączenie z kontem obejmują błąd Wearable API w tagu API_UNAVAILABLE .

Ten przykład pokazuje, jak sprawdzić, czy interfejs API do noszenia jest dostępny:

// 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
    }
    // ...
}

Używanie interfejsu Wearable API z innymi interfejsami API Google

Jeśli Twoja aplikacja używa interfejsu API do noszenia oraz innych interfejsów API Google, wywołaj metodę addApiIfAvailable() i przekaż ją za pomocą interfejsu API do noszenia, aby sprawdzić, czy jest ona dostępna. Możesz skorzystać z tej opcji, aby ułatwić aplikacji bezproblemową obsługę przypadków, w których interfejs API jest niedostępny.

Poniższy przykład pokazuje, jak uzyskać dostęp do interfejsu Wearable API wraz z Interfejs 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();

W powyższym przykładzie GoogleApiClient może połączyć się z Dysk Google bez połączenia z interfejsem API do noszenia, gdy jest on niedostępny. Po podłączysz urządzenie GoogleApiClient przed wywołaniem interfejsu API upewnij się, że interfejs Wearable API jest dostępny:

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

Ignorowanie błędów połączenia z interfejsem API

Jeśli zadzwonisz pod numer addApi(), a GoogleApiClient nie będzie w stanie nawiązać połączenie z tym interfejsem API, cała operacja połączenia dla tego klienta zakończy się niepowodzeniem uruchamia wywołanie zwrotne onConnectionFailed().

Aby zignorować niepowodzenie połączenia interfejsu API, możesz użyć funkcji addApiIfAvailable() Jeśli do interfejsu API dodano element addApiIfAvailable() nie łączy się z powodu nieodwracalnego błędu (np. API_UNAVAILABLE na Wear), że interfejs API jest usuwany z GoogleApiClient, a klient przechodzi do łączyć się z innymi interfejsami API. Jeśli jednak któreś z połączeń interfejsu API zakończy się błędem, który można naprawić (np. intencji związanych z wyrażeniem zgody OAuth), operacja połączenia z klientem kończy się niepowodzeniem. Kiedy przy użyciu połączenia zarządzanego automatycznie, GoogleApiClient spróbuje jak w miarę możliwości je usuwać. Podczas korzystania z połączenia zarządzanego ręcznie obiekt ConnectionResult zawierający intencję rozwiązania to dostarczono na wywołanie zwrotne onConnectionFailed(). Interfejs API – błędy połączeń są ignorowane tylko wtedy, gdy nie można znaleźć rozwiązania problemu. a interfejs API został dodany dzięki addApiIfAvailable(). Aby dowiedzieć się, jak wdrożyć ręczne błędy połączenia więcej informacji znajdziesz w sekcji Obsługa błędów połączeń.

Ponieważ interfejsy API zostały dodane z Wartość addApiIfAvailable() może nie być zawsze widoczna w połączonym GoogleApiClient, należy zabezpieczyć wywołania tych interfejsów API przez dodanie kontroli za pomocą hasConnectedApi(). Aby dowiedzieć się, dlaczego nie udało się nawiązać połączenia, gdy cała operacja połączenia dla klienta zakończyła się sukcesem, wywołanie getConnectionResult() i pobierz kod błędu z ConnectionResult. Jeśli klient wywołuje interfejs API, gdy nie jest po nawiązaniu połączenia z klientem nie uda się nawiązać połączenia API_NOT_AVAILABLE kodu stanu.

Jeśli interfejs API, który dodajesz za pomocą addApiIfAvailable(), wymaga jednego lub zakresów, dodaj je jako parametry w swoim raporcie. addApiIfAvailable(), a nie za pomocą Metoda addScope(). Zakresy dodane za pomocą tej metody mogą nie być żądane, jeśli interfejs API nie ma połączenia przed uzyskaniem zgody OAuth, a zakresy dodane z parametrem addScope() są wymagane zawsze.

Połączenia zarządzane ręcznie

Z większości tego przewodnika dowiesz się, jak korzystać enableAutoManage do zainicjowania żądania automatycznie zarządzane połączenie z błędami naprawionymi automatycznie. Za prawie jest to najlepszy i najłatwiejszy sposób łączenia się z interfejsami API Google Aplikacja na Androida. Istnieją jednak sytuacje, w których warto użyć atrybutu ręcznie zarządzane połączenie z interfejsami API Google w Twojej aplikacji:

  • uzyskiwać dostęp do interfejsów API Google poza aktywnością lub zachować kontrolę nad interfejsem API; połączenie
  • Aby dostosować obsługę i rozwiązywanie błędów połączenia

W tej sekcji znajdziesz przykłady takich i innych zaawansowanych zastosowań.

Rozpoczynanie połączenia zarządzanego ręcznie

Aby zainicjować ręcznie zarządzane połączenie z GoogleApiClient, musisz określ implementację interfejsów wywołań zwrotnych, ConnectionCallbacks i OnConnectionFailedListener. Te interfejsy otrzymują wywołania zwrotne w odpowiedzi na żądanie asynchroniczne connect(), gdy połączenie z Usługami Google Play zostanie prawidłowo wykonane, nie powiedzie się lub zostanie zawieszone.

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

Przy ręcznym zarządzaniu połączeniem musisz wywołać metodę connect() oraz disconnect() w odpowiednich momentach cyklu życia aplikacji. W aktywności kontekst, sprawdzoną metodą jest wywołanie connect() w onStart() aktywności i disconnect() w metodzie onStop() Twojej aktywności. connect() oraz disconnect() metod są wywoływane automatycznie podczas korzystania z połączenia zarządzanego automatycznie.

Jeśli używasz GoogleApiClient do łączenia się z interfejsami API, które wymagają takie jak Dysk Google czy Gry Google Play, jest duża szansa, pierwsza próba nawiązania połączenia się nie uda i zostanie nawiązana połączenie do aplikacji do onConnectionFailed() dzięki SIGN_IN_REQUIRED , ponieważ nie określono konta użytkownika.

Obsługa błędów połączeń

Gdy Twoja aplikacja otrzyma połączenie z numerem onConnectionFailed() oddzwanianie, wybierz hasResolution() w: ConnectionResult obiektu. Jeśli wartość to „prawda”, aplikacja może poprosić użytkownika o natychmiastowe działanie w celu naprawienia błędu przez dzwonię pod numer startResolutionForResult() na obiekcie ConnectionResult. Metoda startResolutionForResult() w tej sytuacji działa tak samo jak startActivityForResult(), i uruchamia działanie odpowiednie do kontekstu, które pomaga użytkownikowi usunąć błąd (np. działanie, które pomaga użytkownikowi wybierz konto).

Jeśli hasResolution() zwraca wartość false, aplikacja powinna wywołać GoogleApiAvailability.getErrorDialog(), przez przekazanie kodu błędu do tej metody. Powoduje to zwrócenie Dialog od Google Play odpowiednie usługi, których dotyczy błąd. Okno może zawierać po prostu komunikat wyjaśniający błąd lub może udostępnić działanie, które rozwiąże błąd. np. gdy użytkownik musi zainstalować nowszą wersję Usług Google Play.

Na przykład plik Metoda wywołania zwrotnego onConnectionFailed() powinna teraz wyglądać tak:

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();
        }
    }
}

Gdy użytkownik zakończy okno dialogowe wyświetlane przez startResolutionForResult() lub odrzuci komunikat podany przez użytkownika GoogleApiAvailability.getErrorDialog(), aktywność otrzymuje onActivityResult() wywołanie zwrotne z RESULT_OK kod wyniku. Aplikacja będzie mogła wtedy zadzwonić connect() jeszcze raz. Na przykład:

@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();
            }
        }
    }
}

W powyższym kodzie prawdopodobnie zauważyłeś(-aś) wartość logiczną mResolvingError. Śledzi to stanu aplikacji, gdy użytkownik rozwiązuje błąd, aby uniknąć powtarzających się prób rozwiązania tego samego problemu . Na przykład okno wyboru konta wyświetla się, aby pomóc użytkownikowi SIGN_IN_REQUIRED użytkownik może obrócić ekran. To odtwarza Twoją aktywność i sprawia, onStart() a następnie wywołał je ponownie, connect(). Ten powoduje kolejne wywołanie do startResolutionForResult() które tworzy kolejne okno wyboru konta przed tym istniejącym.

Ta wartość logiczna spełnia swoje zamierzone działanie tylko wtedy, gdy pozostaje w wielu instancjach aktywności. W następnej sekcji wyjaśniamy, jak zachować stan obsługi błędów w aplikacji pomimo innych działań użytkownika. ani zdarzeń na urządzeniu.

Zachowywanie stanu podczas rozwiązywania błędu

Aby uniknąć wykonywania kodu w onConnectionFailed() podczas poprzedniej próby rozwiązania błędu musisz zachować wartość logiczną, która śledzi, czy aplikacja nie próbuje już naprawić błędu.

Jak widać w przykładzie powyżej, aplikacja powinna ustawiać wartość logiczną true przy każdym wywołaniu startResolutionForResult() lub wyświetla okno dialogowe z GoogleApiAvailability.getErrorDialog() Następnie, gdy aplikacja otrzyma RESULT_OK w onActivityResult() wywołanie zwrotne, ustaw wartość logiczną na false.

Aby śledzić wartości logiczne po ponownym uruchomieniu działania (np. gdy użytkownik obraca ekran): zapisz wartość logiczną w zapisanych danych instancji przy użyciu funkcji 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);
}

Następnie przywróć zapisany stan w okresie onCreate():

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

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

Teraz możesz bezpiecznie uruchamiać aplikację i ręcznie łączyć się z Usługami Google Play.