Cuando quieras realizar una llamada a una de las APIs de un SDK que se ejecuta con los Servicios de Google Play, como Acceder con Google o ML Kit, primero debes crear una instancia de un objeto cliente de API. Estos objetos administran automáticamente la conexión a los Servicios de Google Play. Cuando hay una conexión disponible, cada objeto cliente de la API ejecuta las solicitudes en orden. De lo contrario, el objeto cliente pone en cola las solicitudes. A menos que la documentación indique lo contrario, los objetos cliente son económicos de compilar. Está bien crear clientes de API nuevos cada vez que quieras invocar métodos de API.
En esta guía, se muestra cómo puedes realizar llamadas a la API a cualquiera de los SDKs que usan los Servicios de Google Play, lo que incluye cómo acceder a los servicios que no requieren autorización y a los que sí la requieren.
Comenzar
Para comenzar, agrega las herramientas y dependencias necesarias en el proyecto de tu app, como se describe en la guía para configurar los Servicios de Google Play.
Acceso cuando no se requiere autorización
Para acceder a un servicio que no requiere autorización de la API, obtén una instancia del objeto cliente del servicio y pásale el Context
o el Activity
actuales.
Antes de que se ejecuten las llamadas a la API, se les solicita a los usuarios que actualicen los Servicios de Google Play si es necesario.
Por ejemplo, para obtener la última ubicación conocida del dispositivo con el proveedor de ubicación combinada para Android, agrega la lógica que se muestra en el siguiente fragmento de código:
Kotlin
// Code required for requesting location permissions omitted for brevity. val client = LocationServices.getFusedLocationProviderClient(this) // Get the last known location. In some rare situations, this can be null. client.lastLocation.addOnSuccessListener { location : Location? -> location?.let { // Logic to handle location object. } }
Java
// Code required for requesting location permissions omitted for brevity. FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(this); // Get the last known location. In some rare situations, this can be null. client.getLastLocation() .addOnSuccessListener(this, location -> { if (location != null) { // Logic to handle location object. } });
Acceso cuando se requiere autorización
Para acceder a un servicio que requiere autorización del usuario, completa los siguientes pasos:
- Permite que el usuario acceda.
- Solicita permiso para acceder a los permisos que requiere el servicio.
- Obtén una instancia del objeto cliente del servicio y pásale el objeto
GoogleSignInAccount
del usuario, además de un objetoContext
oActivity
.
En el siguiente ejemplo, se implementa la lectura de los pasos diarios de un usuario con la API de Google Fit. Para ver una implementación similar en el contexto de un proyecto completo, consulta la actividad principal de la app BasicHistoryApiKotlin en GitHub.
Kotlin
class FitFragment : Fragment() { private val fitnessOptions: FitnessOptions by lazy { FitnessOptions.builder() .addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE) .addDataType(DataType.TYPE_STEP_COUNT_DELTA) .build() } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { fitSignIn() } /* * Checks whether the user is signed in. If so, executes the specified * function. If the user is not signed in, initiates the sign-in flow, * specifying the function to execute after the user signs in. */ private fun fitSignIn() { if (oAuthPermissionsApproved()) { readDailySteps() } else { GoogleSignIn.requestPermissions( this, SIGN_IN_REQUEST_CODE, getGoogleAccount(), fitnessOptions ) } } private fun oAuthPermissionsApproved() = GoogleSignIn.hasPermissions(getGoogleAccount(), fitnessOptions) /* * Gets a Google account for use in creating the fitness client. This is * achieved by either using the last signed-in account, or if necessary, * prompting the user to sign in. It's better to use the * getAccountForExtension() method instead of the getLastSignedInAccount() * method because the latter can return null if there has been no sign in * before. */ private fun getGoogleAccount(): GoogleSignInAccount = GoogleSignIn.getAccountForExtension(requireContext(), fitnessOptions) /* * Handles the callback from the OAuth sign in flow, executing the function * after sign-in is complete. */ override fun onActivityResult( requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (resultCode) { RESULT_OK -> { readDailySteps() } else -> { // Handle error. } } } /* * Reads the current daily step total. */ private fun readDailySteps() { Fitness.getHistoryClient(requireContext(), getGoogleAccount()) .readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA) .addOnSuccessListener { dataSet -> val total = when { dataSet.isEmpty -> 0 else -> dataSet.dataPoints.first() .getValue(Field.FIELD_STEPS).asInt() } Log.i(TAG, "Total steps: $total") } .addOnFailureListener { e -> Log.w(TAG, "There was a problem getting the step count.", e) } } companion object { const val SIGN_IN_REQUEST_CODE = 1001 } }
Java
public class FitFragment extends Fragment { private final FitnessOptions fitnessOptions = FitnessOptions.builder() .addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE) .addDataType(DataType.TYPE_STEP_COUNT_DELTA) .build(); @Override public void onViewCreated( @NotNull View view, @Nullable Bundle savedInstanceState) { fitSignIn(); } /* * Checks whether the user is signed in. If so, executes the specified * function. If the user is not signed in, initiates the sign-in flow, * specifying the function to execute after the user signs in. */ private void fitSignIn() { if (oAuthPermissionsApproved()) { readDailySteps(); } else { GoogleSignIn.requestPermissions(this, SIGN_IN_REQUEST_CODE, getGoogleAccount(), fitnessOptions); } } private boolean oAuthPermissionsApproved() { return GoogleSignIn.hasPermissions(getGoogleAccount(), fitnessOptions); } /* * Gets a Google account for use in creating the fitness client. This is * achieved by either using the last signed-in account, or if necessary, * prompting the user to sign in. It's better to use the * getAccountForExtension() method instead of the getLastSignedInAccount() * method because the latter can return null if there has been no sign in * before. */ private GoogleSignInAccount getGoogleAccount() { return GoogleSignIn.getAccountForExtension( requireContext(), fitnessOptions); } /* * Handles the callback from the OAuth sign in flow, executing the function * after sign-in is complete. */ @Override public void onActivityResult( int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { readDailySteps(); } else { // Handle error. } } /* * Reads the current daily step total. */ private void readDailySteps() { AtomicInteger total = new AtomicInteger(); Fitness.getHistoryClient(requireContext(), getGoogleAccount()) .readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA) .addOnSuccessListener(dataSet -> { if (!dataSet.isEmpty()) total.set(Integer.parseInt(dataSet.getDataPoints() .get(0).getValue(FIELD_STEPS).toString())); Log.i(TAG, "Total steps: $total"); }) .addOnFailureListener(e -> { Log.w(TAG, "There was a problem getting the step count.", e); }); } private static final int SIGN_IN_REQUEST_CODE = 1001; }
Cómo verificar la disponibilidad de la API
Antes de habilitar una función en tu app que dependa de una API de los Servicios de Google Play, incluye una verificación de la disponibilidad de la API en el dispositivo. Para ello, llama a checkApiAvailability()
.
En el siguiente fragmento de código, se muestra cómo verificar la disponibilidad del proveedor de ubicación combinada.
Kotlin
fun getLastLocationIfApiAvailable(context: Context?): Task<Location>? { val client = getFusedLocationProviderClient(context) return GoogleApiAvailability.getInstance() .checkApiAvailability(client) .onSuccessTask { _ -> client.lastLocation } .addOnFailureListener { _ -> Log.d(TAG, "Location unavailable.")} }
Java
public Task<Location> getLastLocationIfApiAvailable(Context context) { FusedLocationProviderClient client = getFusedLocationProviderClient(context); return GoogleApiAvailability.getInstance() .checkApiAvailability(client) .onSuccessTask(unused -> client.getLastLocation()) .addOnFailureListener(e -> Log.d(TAG, "Location unavailable.")); }