Puedes usar GoogleApiClient
("Cliente de la API de Google")
para acceder a las APIs de Google que se proporcionan en la biblioteca de Google Play Services
(como Acceso con Google, Juegos y Drive). El cliente de la API de Google proporciona
punto de entrada común a Google Play Services y administra la red
conexión entre el dispositivo del usuario y cada servicio de Google.
Sin embargo, la interfaz GoogleApi
más reciente y sus implementaciones son más fáciles de
y son la forma preferida de acceder a las APIs de los Servicios de Play.
Consulta Cómo acceder a las APIs de Google.
En esta guía, se muestra cómo puedes hacer lo siguiente:
- Administra automáticamente tu conexión a los Servicios de Google Play.
- Realizar llamadas de API síncronas y asíncronas a cualquiera de los Servicios de Google Play
- Administra manualmente tu conexión a los Servicios de Google Play en los casos excepcionales en que sea necesario. Para obtener más información, consulta Conexiones administradas de forma manual.
Para comenzar, primero debes instalar la biblioteca de Google Play Services (revisión 15 o posterior) para tu SDK de Android. Si aún no lo has hecho, sigue las instrucciones en Configura el SDK de Servicios de Google Play.
Inicia una conexión administrada automáticamente
Una vez que tu proyecto esté vinculado a la biblioteca de Google Play Services, crea una instancia de
GoogleApiClient
con el
GoogleApiClient.Builder
en la configuración de tu
onCreate()
. El
GoogleApiClient.Builder
proporciona métodos que te permiten especificar las APIs de Google que quieres usar y las APIs
de OAuth 2.0. Este es un ejemplo de código que crea un
Instancia de GoogleApiClient
que se conecta con el servicio de Google Drive:
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this) .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) .addApi(Drive.API) .addScope(Drive.SCOPE_FILE) .build();
Puedes agregar varias APIs y varios alcances al mismo
GoogleApiClient
agregando llamadas adicionales a addApi()
y addScope()
.
Importante: Si agregas la API de Wearable
junto con otras APIs a una
GoogleApiClient
, es posible que se produzcan errores de conexión del cliente en dispositivos que no
tener instalada la app para Wear OS Para
para evitar errores de conexión, llama al método addApiIfAvailable()
y pasa
la API de Wearable
para que tu cliente pueda manejar correctamente los problemas
en la API de Cloud. Para obtener más información, consulta Cómo acceder a la API de Wearable.
Para iniciar una conexión administrada automáticamente, debes especificar una
implementación para OnConnectionFailedListener
para recibir errores de conexión que no se pueden resolver. Cuando se administran de forma automática
La instancia GoogleApiClient
intenta conectarse a las APIs de Google, se hará automáticamente
de visualización para intentar corregir cualquier falla de conexión que se pueda resolver (por ejemplo, si
los Servicios de Google Play deben actualizarse). Si se produce un error que no se puede
resuelto, recibirás una llamada para
onConnectionFailed()
También puedes especificar una implementación opcional para la interfaz ConnectionCallbacks
si tu app necesita saber cuándo se debe
cuando se establece o suspende la conexión administrada automáticamente. Por ejemplo,
tu app realiza llamadas para escribir datos a las APIs de Google; estos deben invocarse
Solo después de que se haya llamado al método onConnected()
.
Esta es una actividad de ejemplo que implementa las interfaces de devolución de llamada y agrega al cliente de la API de 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 // ... } }
Tu instancia de GoogleApiClient
se conectará automáticamente después de tu actividad
llamar a onStart()
y desconectarse después de llamar a onStop()
.
Tu app puede comenzar a hacer cambios
de lectura a las APIs de Google después de compilar GoogleApiClient
, sin
a que se complete la conexión.
Cómo comunicarse con los servicios de Google
Después de conectarte, tu cliente puede realizar llamadas de lectura y escritura usando las APIs específicas del servicio para
el que tu aplicación está autorizada, tal como lo especifican las APIs y los alcances que agregaste a tu
GoogleApiClient
.
Nota: Antes de realizar llamadas a servicios de Google específicos, es posible que primero debas registrar tu app en la Consola para desarrolladores de Google. Para obtener instrucciones, consulta la página de inicio de introducción para la API que estás usando, como Google Drive o Acceso con Google:
Cuando realizas una solicitud de lectura o escritura con GoogleApiClient
, el cliente de la API muestra un objeto PendingResult
que representa la solicitud.
Esto ocurre inmediatamente, antes de que la solicitud se entregue al servicio de Google al que está llamando tu app.
Por ejemplo, esta es una solicitud para leer un archivo de Google Drive que proporciona un
Objeto PendingResult
:
Query query = new Query.Builder() .addFilter(Filters.eq(SearchableField.TITLE, filename)); PendingResult<DriveApi.MetadataBufferResult> result = Drive.DriveApi.query(mGoogleApiClient, query);
Después de que tu app tenga un objeto PendingResult
, haz lo siguiente:
tu app puede especificar si la solicitud se maneja como una llamada asíncrona o como una llamada síncrona.
Nota: Tu app puede poner en cola solicitudes de lectura sin estar conectada a los Servicios de Google Play. Para
Por ejemplo, tu app puede llamar a métodos para leer un archivo de Google Drive independientemente de si tu instancia de GoogleApiClient
ya está conectada. Después de que se establece una conexión, se ejecutan las solicitudes de lectura en cola. Las solicitudes de escritura generan un error si tu app llama
Métodos de escritura de los Servicios de Google Play mientras tu cliente de la API de Google no está conectado.
Usa llamadas asíncronas
Para que la solicitud sea asíncrona, llama a
setResultCallback()
en el objeto PendingResult
y proporciona un
implementación del
ResultCallback
. Para
Por ejemplo, esta es la solicitud ejecutada de forma asíncrona:
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. // ... } }); }
Cuando tu app recibe un objeto Result
en
la devolución de llamada onResult()
se entrega como una instancia de la subclase correspondiente, tal como lo especifica la API que estás usando,
como, por ejemplo,
DriveApi.MetadataBufferResult
Usa llamadas síncronas
Si quieres que tu código se ejecute en un orden estrictamente definido, quizás porque el resultado de una
se necesita una llamada como argumento para otra, puedes hacer que tu solicitud sea síncrona llamando
await()
en
PendingResult
Esto bloqueará el subproceso
y devuelve el objeto Result
cuando
se completa la solicitud. Este objeto se entrega como una instancia de la subclase correspondiente según lo especificado en
la API que estás usando, por ejemplo,
DriveApi.MetadataBufferResult
Porque llamar a await()
bloquea el subproceso hasta que llega el resultado, tu app nunca debe realizar solicitudes síncronas a las APIs de Google en
subproceso de IU. Tu app puede crear un subproceso nuevo con un objeto AsyncTask
y usarlo para realizar la solicitud síncrona.
En el siguiente ejemplo, se muestra cómo realizar una solicitud de archivo a Google Drive como una llamada síncrona:
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 // ... } }
Accede a la API de Wearable
La API de Wearable proporciona un canal de comunicación para apps que se ejecutan en dispositivos portátiles y wearables. La API consta de un conjunto de objetos de datos que el sistema puede enviar y sincronizar. objetos de escucha que notifican a tus apps sobre eventos importantes mediante una capa de datos. El La API de Wearable está disponible en dispositivos con Android 4.3 (nivel de API 18) o versiones posteriores cuando un dispositivo wearable está conectado y la aplicación complementaria de Wear OS esté instalada en el dispositivo.
Cómo usar la API independiente de Wearable
Si tu app usa la API de Wearable pero no otras APIs de Google, puedes agregar esta API
llamando al método addApi()
. En el siguiente ejemplo, se muestra cómo agregar
API de Wearable a tu instancia de GoogleApiClient
:
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this) .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) .addApi(Wearable.API) .build();
En situaciones en las que la API de Wearable no esté disponible, las solicitudes de conexión que
incluir la API de Wearable fallan con el
API_UNAVAILABLE
código de error.
En el siguiente ejemplo, se muestra cómo determinar si la API de Wearable está disponible:
// 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 } // ... }
Cómo usar la API de Wearable con otras APIs de Google
Si tu app usa la API de Wearable además de otras APIs de Google, llama al
addApiIfAvailable()
y pasa la API de Wearable para verificar si está disponible. Puedes usar esta verificación para ayudar a tu app a manejar correctamente los casos en los que la API no está disponible.
En el siguiente ejemplo, se muestra la manera de acceder a la API de Wearable junto con la API de 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();
En el ejemplo anterior, GoogleApiClient
se puede conectar correctamente con
Google Drive sin conectarse a la API de Wearable si no está disponible. Después del
conecta tu GoogleApiClient
asegúrate de que la API de Wearable esté disponible antes de realizar las llamadas a la API:
boolean wearAvailable = mGoogleApiClient.hasConnectedApi(Wearable.API);
Cómo ignorar errores de conexión de API
Si llamas a addApi()
, y GoogleApiClient
no puede
conectarse correctamente a esa API, la operación de conexión completa para ese cliente falla y
activa la devolución de llamada onConnectionFailed()
.
Puedes registrar una falla de conexión a la API para que se ignore mediante
addApiIfAvailable()
Si una API agregada con
addApiIfAvailable()
no se conecta debido a un error irrecuperable
(como API_UNAVAILABLE
para Wear),
esa API se elimina de tu GoogleApiClient
y el cliente procede
conectarse a otras APIs. Sin embargo, si cualquier conexión a una API falla con un error recuperable (como una
el intent de resolución de consentimiento de OAuth), fallará la operación de conexión del cliente. Cuándo
con una conexión administrada automáticamente, GoogleApiClient
intentará
para resolver esos errores cuando sea posible. Cuando usas una conexión administrada de forma manual
se muestra un objeto ConnectionResult
que contiene un intent de resolución
se envía a la devolución de llamada onConnectionFailed()
. API
las fallas de conexión se ignoran solo si no hay una resolución para la falla.
y la API se agregó
con addApiIfAvailable()
.
Para aprender a implementar la falla de conexión manual
consulta Soluciona fallas de conexión.
Debido a que las APIs agregadas con
Es posible que addApiIfAvailable()
no siempre esté presente en el archivo conectado.
GoogleApiClient
, debes proteger las llamadas a estas APIs agregando una verificación
usando hasConnectedApi()
. Para averiguar por qué un
API específica no pudo conectarse cuando la operación de conexión se realizó correctamente para el cliente, llama
getConnectionResult()
y obtén el código de error del
objeto ConnectionResult
. Si tu cliente llama a una API cuando no está
conectado al cliente, la llamada falla y muestra el
API_NOT_AVAILABLE
código de estado.
Si la API que estás agregando a través de addApiIfAvailable()
requiere una o
más permisos, agrégalos como parámetros en tu
addApiIfAvailable()
, en lugar de usar la
addScope()
. Es posible que no se soliciten los permisos agregados con este enfoque si la API
antes de obtener el consentimiento para OAuth, mientras que los permisos agregados con
addScope()
siempre se solicitan.
Conexiones administradas de forma manual
La mayor parte de esta guía te muestra cómo usar la
enableAutoManage
para iniciar una
una conexión administrada automáticamente con errores resueltos automáticamente. En casi
en todos los casos, esta es la mejor y la más sencilla para conectarte a las APIs de Google desde tu
App para Android Sin embargo, hay algunas situaciones en las que querrás usar un
conexión administrada manualmente a las APIs de Google en tu app:
- Para acceder a las APIs de Google fuera de una actividad o retener el control de la API conexión
- Para personalizar el manejo y la resolución de errores de conexión
En esta sección, se proporcionan ejemplos de estos y otros casos de uso avanzados.
Inicia una conexión administrada de forma manual
Para iniciar una conexión administrada de forma manual a GoogleApiClient
, debes
especificar una implementación para las interfaces de devolución de llamada,
ConnectionCallbacks
y OnConnectionFailedListener
.
Estas interfaces reciben devoluciones de llamada en respuesta al proceso
connect()
cuando la
conexión a los Servicios de Google Play es exitosa, falla o se suspende.
mGoogleApiClient = new GoogleApiClient.Builder(this) .addApi(Drive.API) .addScope(Drive.SCOPE_FILE) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build()
Cuando administres una conexión de forma manual, deberás llamar al
connect()
y
disconnect()
en los puntos correctos
del ciclo de vida de tu app. En una actividad
contexto, la práctica recomendada es llamar a connect()
en el onStart()
de tu actividad
y disconnect()
en el método onStop()
de tu actividad.
El connect()
y
Métodos disconnect()
se llaman automáticamente cuando se usa una conexión administrada automáticamente.
Si usas GoogleApiClient
para conectarte a APIs que requieren
de Google, como Google Drive o Google Play Juegos, es muy probable
tu primer intento de conexión fallará y tu app recibirá una llamada
para onConnectionFailed()
con el SIGN_IN_REQUIRED
porque no se especificó la cuenta de usuario.
Soluciona las fallas de conexión
Cuando tu app recibe una llamada al onConnectionFailed()
devolución de llamada, debes llamar a hasResolution()
en el ConnectionResult
proporcionado
. Si devuelve un valor "true", tu app puede solicitar que el usuario tome medidas inmediatas para resolver el error
llamando a startResolutionForResult()
en el objeto ConnectionResult
.
Método startResolutionForResult()
Se comporta de la misma manera que startActivityForResult()
en esta situación.
e inicia una actividad adecuada para el contexto que ayuda al usuario a resolver el error (como una actividad que ayuda al usuario a
seleccionar una cuenta).
Si es hasResolution()
devuelve un valor falso, tu app debe llamar
GoogleApiAvailability.getErrorDialog()
:
y pasar el código de error a este método. Esto muestra un
Dialog
proporcionado por Google Play
servicios adecuados para el error. El diálogo puede simplemente proporcionar un mensaje que explique
el error, o también puede proporcionar una acción para iniciar una actividad que resuelva el error
(por ejemplo, cuando el usuario necesita instalar una versión más reciente de los Servicios de Google Play).
Por ejemplo, tu
El método de devolución de llamada onConnectionFailed()
debería verse de la siguiente manera:
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(); } } }
Una vez que el usuario completa el diálogo proporcionado por
startResolutionForResult()
o descarta el mensaje proporcionado por GoogleApiAvailability.getErrorDialog()
,
tu actividad recibe el
onActivityResult()
con el
Código de resultado RESULT_OK
.
Entonces, tu app podrá llamar
connect()
de nuevo.
Por ejemplo:
@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(); } } } }
En el código anterior, es probable que hayas notado el valor booleano, mResolvingError
. Esto lleva un registro de la
estado de la app mientras el usuario resuelve el error para evitar intentos repetitivos de resolver el mismo
. Por ejemplo, mientras se muestra el diálogo del selector de cuenta para ayudar al usuario a resolver el problema
SIGN_IN_REQUIRED
el usuario puede girar la pantalla. Esto recrea tu actividad y provoca que tu
onStart()
lo que luego llama
connect()
de nuevo. Esta
genera otra llamada a
startResolutionForResult()
:
lo que creará otro diálogo del selector de cuentas frente al diálogo existente.
Este booleano es válido solo si persiste en todas las instancias de actividad. En la siguiente sección, se explica cómo mantener el estado de manejo de errores de tu app a pesar de otras acciones del usuario o eventos que ocurran en el dispositivo.
Cómo mantener el estado mientras se resuelve un error
Para evitar la ejecución del código en
onConnectionFailed()
mientras hay en curso un intento anterior de resolver un error, debes conservar un valor booleano que
realiza un seguimiento para saber si tu app ya está intentando resolver un error.
Como se muestra en el ejemplo de código anterior, tu app debe establecer un valor booleano en true
cada vez que llama
startResolutionForResult()
o muestra el diálogo de
GoogleApiAvailability.getErrorDialog()
Luego, cuando tu app reciba
RESULT_OK
en
onActivityResult()
establece el valor booleano en false
.
Para realizar un seguimiento del valor booleano en los reinicios de la actividad (por ejemplo, cuando el usuario rota la pantalla),
guarda el valor booleano en los datos de instancia guardados de la actividad usando
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); }
Luego, recupera el estado guardado durante
onCreate()
:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... mResolvingError = savedInstanceState != null && savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false); }
Ya está todo listo para que ejecutes tu app de forma segura y te conectes manualmente a los Servicios de Google Play.