Accesso alle API di Google con GoogleApiClient (deprecato)

Puoi utilizzare il GoogleApiClient ("Client API di Google") per accedere alle API di Google fornite nella libreria di Google Play Services (come Accedi con Google, Giochi e Drive). Il client API di Google fornisce un'interfaccia punto di accesso comune a Google Play Services e gestisce la rete connessione tra il dispositivo dell'utente e ogni servizio Google.

Tuttavia, la nuova interfaccia di GoogleApi e le sue implementazioni sono più facili usano e rappresentano il metodo preferito per accedere alle API di Play Services. Vedi Accesso alle API di Google.

Questa guida illustra come:

  • Gestisci automaticamente la tua connessione a Google Play Services.
  • Eseguire chiamate API sincrone e asincrone a tutti i servizi Google Play.
  • Gestisci manualmente la connessione a Google Play Services nei rari casi in cui si verifica necessaria. Per scoprire di più, vedi Connessioni gestite manualmente.
Figura 1: illustrazione che mostra in che modo il client dell'API di Google fornisce una per connetterti ed effettuare chiamate a qualsiasi servizio Google Play disponibile, come Google Play Giochi e Google Drive.

Per iniziare, devi prima installare la libreria Google Play Services (revisione 15 o versioni successive) per il tuo SDK Android. Se non lo hai già fatto, segui le istruzioni in Configura l'SDK Google Play Services.

Avviare una connessione gestita automaticamente

Dopo aver collegato il progetto alla libreria di Google Play Services, crea un'istanza di GoogleApiClient tramite GoogleApiClient.Builder API nella tua attività onCreate() . La GoogleApiClient.Builder fornisce metodi che ti consentono di specificare le API di Google che desideri utilizzare e Ambiti OAuth 2.0. Ecco un esempio di codice che crea un Istanza GoogleApiClient che si connette al servizio Google Drive:

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

Puoi aggiungere più API e ambiti allo stesso GoogleApiClient aggiungendo altre chiamate a addApi() e addScope().

Importante: se aggiungi l'API Wearable insieme ad altre API a un GoogleApiClient, potresti riscontrare errori di connessione del client sui dispositivi che non abbiano installato l'app Wear OS. A evitare errori di connessione, chiamare il metodo addApiIfAvailable() e passare l'API Wearable per consentire al client di gestire agevolmente i problemi mancanti tramite Google Cloud CLI o tramite l'API Compute Engine. Per maggiori informazioni, vedi Accedere all'API Wearable.

Per avviare una connessione gestita automaticamente, devi specificare un implementazione per OnConnectionFailedListener per ricevere errori di connessione irrisolvibili. Quando viene gestito automaticamente L'istanza GoogleApiClient tenta di connettersi alle API di Google; eseguirà automaticamente per tentare di correggere eventuali errori di connessione risolvibili (ad esempio, Google Play Services deve essere aggiornato). Se si verifica un errore che non può essere risolto, riceverai una chiamata a onConnectionFailed()

Puoi anche specificare un'implementazione facoltativa per l'interfaccia di ConnectionCallbacks se la tua app deve sapere quando la connessione gestita automaticamente viene stabilita o sospesa. Ad esempio, se la tua app effettua chiamate per scrivere dati nelle API di Google, queste dovrebbero essere richiamate solo dopo che è stato chiamato il metodo onConnected().

Ecco un'attività di esempio che implementa le interfacce di callback e aggiunge al client API di 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

        // ...
    }
}

La tua istanza di GoogleApiClient si connetterà automaticamente al termine della tua attività chiama onStart() e disconnettiti dopo aver chiamato onStop(). La tua app può iniziare immediatamente richieste di lettura alle API di Google dopo aver creato GoogleApiClient, senza in attesa del completamento della connessione.

Comunica con i servizi Google

Dopo la connessione, il client può effettuare chiamate di lettura e scrittura utilizzando le API specifiche del servizio per che la tua app è autorizzata, come specificato dalle API e dagli ambiti che hai aggiunto GoogleApiClient.

Nota: prima di effettuare chiamate a servizi Google specifici, potrebbe essere necessario registrare il tuo nella Google Developers Console. Per istruzioni, consulta il documento per l'API che stai utilizzando, ad esempio Google Drive oppure Accedi con Google.

Quando esegui una richiesta di lettura o scrittura utilizzando GoogleApiClient, il client API restituisce un oggetto PendingResult che rappresenta la richiesta. Ciò avviene immediatamente, prima che la richiesta venga consegnata al servizio Google chiamato dalla tua app.

Ad esempio, ecco una richiesta di lettura di un file da Google Drive che fornisce Oggetto PendingResult:

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

Quando l'app ha un oggetto PendingResult, la tua app potrà specificare se la richiesta viene gestita come una chiamata asincrona o come una chiamata sincrona.

Suggerimento:la tua app può accodare le richieste di lettura quando non è connessa a Google Play Services. Per Ad esempio, la tua app può chiamare metodi per leggere un file da Google Drive indipendentemente dal fatto che l'istanza GoogleApiClient sia già connessa o meno. Dopo aver stabilito una connessione, le richieste di lettura accodate vengono eseguite. Le richieste di scrittura generano un errore se la tua app chiama Metodi di scrittura di Google Play Services quando il client API di Google non è connesso.

Utilizzo delle chiamate asincrone

Per rendere la richiesta asincrona, richiama setResultCallback() sulla PendingResult e fornire un dell'implementazione ResultCallback. Per Ad esempio, ecco la richiesta eseguita in modo asincrono:

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

Quando la tua app riceve un oggetto Result in il callback onResult(), viene pubblicato come un'istanza della sottoclasse appropriata, come specificato dall'API che stai utilizzando, come DriveApi.MetadataBufferResult

Utilizzo delle chiamate sincrone

Se vuoi che il tuo codice venga eseguito in un ordine ben definito, forse perché il risultato di una necessaria come argomento a un'altra, puoi rendere sincrona la richiesta await() il PendingResult. Questa operazione blocca il thread e restituisce l'oggetto Result quando completa della richiesta. Questo oggetto viene pubblicato come istanza della sottoclasse appropriata come specificato all'API che stai utilizzando, ad esempio DriveApi.MetadataBufferResult

Perché chiamare il numero await() blocca il thread finché non arriva il risultato, l'app non deve mai effettuare richieste sincrone alle API di Google nella Thread UI. La tua app può creare un nuovo thread utilizzando un oggetto AsyncTask e utilizzare il thread per effettuare la richiesta sincrona.

L'esempio seguente mostra come effettuare una richiesta di file a Google Drive come chiamata sincrona:

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

Accedi all'API Wearable

L'API Wearable fornisce un canale di comunicazione per le app eseguite su dispositivi portatili e indossabili. L'API è costituita da un set di oggetti di dati che il sistema può inviare e sincronizzare listener che avvisano le app di eventi importanti utilizzando un livello dati. La L'API Wearable è disponibile sui dispositivi con Android 4.3 (livello API 18) o versioni successive quando è connesso un dispositivo indossabile e l'app complementare Wear OS sia installata sul dispositivo.

Utilizzo dell'API Wearable standalone

Se la tua app usa l'API Wearable, ma non altre API di Google, puoi aggiungere questa API chiamando il metodo addApi(). L'esempio seguente mostra come aggiungere il parametro API Wearable alla tua istanza GoogleApiClient:

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

Nei casi in cui l'API Wearable non sia disponibile, una richiesta di connessione includi l'API Wearable con errore API_UNAVAILABLE codice di errore.

L'esempio seguente mostra come determinare se è disponibile l'API Wearable:

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

Utilizzo dell'API Wearable con altre API di Google

Se la tua app utilizza l'API Wearable oltre ad altre API di Google, chiama il metodo addApiIfAvailable() e passa l'API Wearable per verificare se è disponibile. Puoi utilizzare questo controllo per consentire alla tua app di gestire agevolmente i casi in cui l'API non è disponibile.

L'esempio seguente mostra come accedere all'API Wearable insieme all'API API Drive:

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

Nell'esempio precedente, GoogleApiClient può connettersi correttamente con Google Drive senza connettersi all'API Wearable se non è disponibile. Dopo il giorno connetti GoogleApiClient assicurati che l'API Wearable sia disponibile prima di effettuare le chiamate API:

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

Ignorare gli errori di connessione all'API

Se chiami il numero addApi() e il GoogleApiClient non riesce a connettersi correttamente a quell'API, l'intera operazione di connessione per quel client non va a buon fine attiva il callback onConnectionFailed().

Puoi registrare un errore di connessione API affinché venga ignorato utilizzando addApiIfAvailable() Se viene aggiunta un'API con addApiIfAvailable() non riesce a connettersi a causa di un errore non recuperabile (ad esempio API_UNAVAILABLE per Wear), che l'API viene eliminata dal tuo GoogleApiClient e il client passa e la connessione ad altre API. Tuttavia, se una connessione all'API non riesce e si verifica un errore recuperabile (come un intent di risoluzione del consenso OAuth), l'operazione di connessione del client non va a buon fine. Quando utilizzando una connessione gestita automaticamente, GoogleApiClient tenterà se possibile. Quando utilizzi una connessione gestita manualmente Una ConnectionResult contenente un intent di risoluzione è inviato al callback onConnectionFailed(). API gli errori di connessione vengono ignorati solo se non esiste una soluzione per l'errore e l'API è stata aggiunta con addApiIfAvailable(). Per scoprire come implementare un errore di connessione manuale vedi Gestire gli errori di connessione.

Poiché le API sono state aggiunte addApiIfAvailable() potrebbe non essere sempre presente nella GoogleApiClient, devi proteggere le chiamate a queste API aggiungendo un controllo utilizzando hasConnectedApi(). Per scoprire perché un Una particolare API non è riuscita a connettersi se l'intera operazione di connessione è riuscita per il client, chiama getConnectionResult() e ricevi il codice di errore dal ConnectionResult. Se il client chiama un'API quando non lo è connessa al client, la chiamata non va a buon fine API_NOT_AVAILABLE codice di stato.

Se l'API che aggiungi tramite addApiIfAvailable() richiede uno o altri ambiti, aggiungili come parametri addApiIfAvailable() anziché utilizzare il metodo addScope(). Gli ambiti aggiunti utilizzando questo approccio potrebbero non essere richiesti se l'API la connessione non riesce prima di ottenere il consenso OAuth, mentre gli ambiti aggiunti con I valori addScope() sono sempre richiesti.

Connessioni gestite manualmente

La maggior parte di questa guida illustra come utilizzare enableAutoManage per avviare una connessione gestita automaticamente con errori risolti automaticamente. Tra quasi In ogni caso, questo è il modo migliore e più semplice per connettersi alle API di Google dal tuo App per Android. Tuttavia, in alcune situazioni è consigliabile utilizzare una connessione gestita manualmente alle API di Google nella tua app:

  • Per accedere alle API di Google al di fuori di un'attività o mantenere il controllo dell'API connessione
  • Per personalizzare la gestione e la risoluzione degli errori di connessione

Questa sezione fornisce esempi di questi e altri casi d'uso avanzati.

Avviare una connessione gestita manualmente

Per avviare una connessione gestita manualmente a GoogleApiClient, devi specificare un'implementazione per le interfacce di callback ConnectionCallbacks e OnConnectionFailedListener. Queste interfacce ricevono callback in risposta all'interazione connect() quando il parametro la connessione a Google Play Services ha esito positivo, non va a buon fine o viene sospesa.

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

Quando gestisci manualmente una connessione, devi chiamare il connect() e disconnect() nei punti giusti del ciclo di vita della tua app. In un'attività in un contesto, la best practice è chiamare connect() nel campo onStart() della tua attività e disconnect() nel metodo onStop() delle tue attività. Le connect() e disconnect() metodi vengono chiamati automaticamente quando si utilizza una connessione gestita automaticamente.

Se utilizzi GoogleApiClient per connetterti alle API che richiedono di autenticazione, come Google Drive o Google Play Giochi, c'è una buona probabilità il primo tentativo di connessione non andrà a buon fine e la tua app riceverà una chiamata per onConnectionFailed() con SIGN_IN_REQUIRED perché l'account utente non è stato specificato.

Gestire gli errori di connessione

Quando la tua app riceve una chiamata al onConnectionFailed() callback, devi chiamare hasResolution() nel ConnectionResult fornito . Se restituisce true, la tua app può richiedere all'utente di intervenire immediatamente per risolvere l'errore chiamata al numero startResolutionForResult() sull'oggetto ConnectionResult. Il metodo startResolutionForResult() si comporta allo stesso modo di startActivityForResult() in questa situazione, e avvia un'attività adatta al contesto che aiuta l'utente a risolvere l'errore (ad esempio un'attività che aiuta l'utente a seleziona un account).

Se hasResolution() restituisce false, l'app deve chiamare GoogleApiAvailability.getErrorDialog(), passando il codice di errore a questo metodo. Questo restituisce un Dialog fornita da Google Play i servizi più appropriati per l'errore. La finestra di dialogo potrebbe fornire semplicemente un messaggio che spiega l'errore oppure può anche fornire un'azione per avviare un'attività in grado di risolverlo ad esempio quando l'utente deve installare una versione più recente di Google Play Services.

Ad esempio, Il metodo di callback onConnectionFailed() ora dovrebbe avere il seguente aspetto:

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

Dopo che l'utente ha completato la finestra di dialogo fornita startResolutionForResult() o ignora il messaggio fornito da GoogleApiAvailability.getErrorDialog(), la tua attività riceve onActivityResult() richiamarlo con RESULT_OK Codice risultato. L'app può quindi chiamare connect(). Ad esempio:

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

Nel codice riportato sopra, avrai probabilmente notato il valore booleano mResolvingError. Questo tiene traccia stato dell'app mentre l'utente sta risolvendo l'errore per evitare tentativi ripetitivi di risolvere lo stesso . Ad esempio, mentre viene visualizzata la finestra di dialogo del selettore account per aiutare l'utente a risolvere SIGN_IN_REQUIRED l'utente potrebbe ruotare lo schermo. In questo modo la tua attività viene ricreata e la tua onStart() da usare di nuovo, che a sua volta richiama connect() di nuovo. Questo comporta un'altra chiamata a startResolutionForResult(), che crea un'altra finestra di dialogo del selettore account davanti a quella esistente.

Questo valore booleano serve allo scopo previsto solo se persiste in più istanze di attività. La sezione successiva spiega come mantenere lo stato di gestione degli errori dell'app nonostante le altre azioni dell'utente o eventi che si verificano sul dispositivo.

Mantieni lo stato durante la risoluzione di un errore

Per evitare di eseguire il codice onConnectionFailed() mentre è in corso un tentativo precedente di risolvere un errore, devi mantenere un valore booleano controlla se la tua app sta già tentando di risolvere un errore.

Come mostrato nell'esempio di codice riportato sopra, l'app deve impostare un valore booleano su true ogni volta che chiama startResolutionForResult() o visualizza la finestra di dialogo GoogleApiAvailability.getErrorDialog(). Quando la tua app riceve RESULT_OK nel onActivityResult() imposta il valore booleano su false.

Per tenere traccia del valore booleano durante i riavvii dell'attività (ad esempio quando l'utente ruota lo schermo), salva il valore booleano nei dati dell'istanza salvata dell'attività utilizzando 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);
}

Quindi ripristina lo stato salvato durante onCreate():

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

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

Ora puoi eseguire in sicurezza l'app e connetterti manualmente a Google Play Services.