Guía para desarrolladores de Android sobre la API de servicios de ubicación de Google

Publicado: 2022-03-11

Conocer la ubicación de su usuario es información útil en muchas aplicaciones que desarrollamos y usamos hoy. Existen muchas aplicaciones populares basadas en la ubicación que nos facilitan la vida, además de cambiar la forma en que usamos estos servicios. Un ejemplo es la popular aplicación Foursquare, donde los usuarios que frecuentan un establecimiento y se registran suelen ganar descuentos. Uber, que te ayuda a conseguir un viaje desde tu teléfono móvil a una tarifa más baja que un taxi normal. La lista es grande y sigue creciendo.

API de servicios de ubicación

En este artículo, vamos a crear una aplicación de Android simple para determinar la latitud y la longitud del usuario utilizando la API de servicios de ubicación de Google de Android. Al desarrollar aplicaciones de Android, hay un par de formas de obtener la ubicación del usuario.

Paquete "android.ubicación"

El paquete “android.ubicación” ha estado disponible desde que se introdujo Android por primera vez y nos brinda acceso a los servicios de ubicación. Estos servicios permiten que las aplicaciones obtengan actualizaciones periódicas de la ubicación geográfica del dispositivo.

El paquete proporciona dos medios para adquirir datos de ubicación:

  • LocationManager.GPS_PROVIDER: Determina la ubicación usando satélites. Dependiendo de las condiciones, este proveedor puede tardar un tiempo en devolver una corrección de ubicación.

  • LocationManager.NETWORK_PROVIDER: determina la ubicación en función de la disponibilidad de torres celulares cercanas y puntos de acceso WiFi. Esto es más rápido que GPS_PROVIDER.

Cuando busca la ubicación del usuario, debe jugar con estos proveedores y su disponibilidad. Idealmente, obtiene la primera ubicación mediante NETWORK_PROVIDER, que puede no ser tan preciso, pero es mucho más rápido. Luego, puede intentar aumentar la precisión escuchando una mejor ubicación utilizando GPS_PROVIDER.

Las API proporcionadas por este paquete son de nivel bastante bajo y requieren que el desarrollador de la aplicación maneje los detalles más finos para determinar cuándo solicitar datos de ubicación y programar llamadas a la API de manera optimizada. Para mejorar la experiencia del desarrollador con los servicios del sistema basados ​​en la ubicación y facilitar el proceso de desarrollo de aplicaciones que reconocen la ubicación, Google introdujo una nueva forma de solicitar la ubicación de un usuario mediante Google Play Services. Ofrece una API más simple con mayor precisión, geocercas de bajo consumo y mucho más.

API de servicios de ubicación de Google

La API de Google Location Services, también conocida como FusedLocationProviderApi, es la forma recomendada por Google de obtener la ubicación de un usuario. Proporciona la mejor precisión en función de nuestras necesidades. Algunas de las ventajas de utilizar esta API frente a la anterior son:

  • Simplicidad: a diferencia de la API anterior, ya no tiene que tratar con varios proveedores. En su lugar, especifica necesidades de alto nivel, como "alta precisión" o "baja potencia", y adoptará un enfoque adecuado.

  • Disponibilidad: le da a su aplicación acceso inmediato a la mejor y más reciente ubicación conocida. Por lo general, esta información está fácilmente disponible, solo tiene que solicitarla.

  • Eficiencia energética: minimiza el uso de energía de su aplicación.

  • Versatilidad: satisface una amplia gama de necesidades, desde usos en primer plano, que necesitan datos de ubicación de alta precisión, hasta usos en segundo plano, que solo requieren actualizaciones periódicas de ubicación con un impacto energético insignificante.

Construyamos una aplicación de Android basada en la ubicación utilizando esta API. Para ello, utilizaremos el IDE sugerido por Google para el desarrollo de aplicaciones de Android: Android Studio. Comenzar con Android Studio es bastante sencillo. Su sitio web describe con gran detalle el procedimiento relacionado con la instalación y configuración de Android Studio, incluido cómo iniciar su primera aplicación de Android para el desarrollo.

Android Studio debería facilitarnos las cosas. Sin embargo, tendremos que comenzar configurando el script de compilación y agregando Google Play Services como una dependencia para esta aplicación. Esto se puede hacer modificando el archivo "build.gradle" de la siguiente manera:

 dependencies { compile 'com.android.support:appcompat-v7:21.0.3' compile 'com.google.android.gms:play-services:6.5.87' // Add this line }

En el momento en que escribo este artículo, la última versión disponible de Google Play Services es la 6.5.87. Asegúrese de verificar siempre la última versión disponible antes de comenzar. En caso de que salgan versiones más nuevas más adelante y decidas actualizarlas para tus propios proyectos, prueba todas las funciones relacionadas con la ubicación con todas las versiones de Android que admitas.

En este punto, deberíamos poder comenzar a hacer el trabajo real para nuestra aplicación.

Solicitud de permiso, configuración de AndroidManifest.xml

Los Android tienen características de seguridad específicas que evitarían que cualquier aplicación arbitraria solicite una ubicación precisa del usuario. Para solucionar esto, necesitamos editar “AndroidManifest.xml” y agregar el permiso que requerimos para esta aplicación:

 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Mientras estamos en eso, también debemos definir la versión de Google Play Services que estamos usando para esta aplicación:

 <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

Comprobación de la disponibilidad de los servicios de Google Play

Antes de acceder a las funciones proporcionadas por Google Play Services, debemos verificar si el dispositivo tiene instalado Google Play Services y que la versión es la que pretendemos usar (6.5.87).

 private boolean checkGooglePlayServices(){ int checkGooglePlayServices = GooglePlayServicesUtil .isGooglePlayServicesAvailable(mContext); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { /* * Google Play Services is missing or update is required * return code could be * SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID. */ GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, mContext, REQUEST_CODE_RECOVER_PLAY_SERVICES).show(); return false; } return true; }

Este método comprobará Google Play Services y, en caso de que el dispositivo no lo tenga instalado (es raro, pero he visto casos así), abrirá un cuadro de diálogo con el error correspondiente e invitará al usuario a instalar/actualizar. Servicios de Google Play de Google Play Store.

servicios de juego de google

Una vez que el usuario completa la resolución proporcionada por "GooglePlayServicesUtil.getErrorDialog()", se activa un método de devolución de llamada "onActivityResult()", por lo que tenemos que implementar alguna lógica para manejar esa llamada:

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) { if (resultCode == RESULT_OK) { // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(mContext, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show(); finish(); } } }

Acceso a las API de Google

Para acceder a las API de Google, solo necesitamos realizar un paso más: crear una instancia de GoogleApiClient. El Cliente API de Google proporciona un punto de entrada común a todos los servicios de Google Play y administra la conexión de red entre el dispositivo del usuario y cada servicio de Google. Nuestro primer paso aquí es iniciar la conexión. Normalmente llamo a este código desde el método "onCreate" de la actividad:

 protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); }

Al encadenar una serie de llamadas a métodos, estamos especificando la implementación de la interfaz de devolución de llamada y la API del servicio de ubicación que queremos usar. La implementación de la interfaz, en este caso "esto", recibirá una respuesta al método asíncrono "conectar ()" cuando la conexión a los Servicios de Google Play sea exitosa, falle o se suspenda. Después de agregar este código, nuestra "Actividad principal" debería verse así:

 package com.bitwoo.userlocation; import android.content.Intent; import android.location.Location; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationServices; public class MainActivity extends ActionBarActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private static int REQUEST_CODE_RECOVER_PLAY_SERVICES = 200; private GoogleApiClient mGoogleApiClient; private Location mLastLocation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (checkGooglePlayServices()) { buildGoogleApiClient(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } private boolean checkGooglePlayServices() { int checkGooglePlayServices = GooglePlayServicesUtil .isGooglePlayServicesAvailable(this); if (checkGooglePlayServices != ConnectionResult.SUCCESS) { /* * google play services is missing or update is required * return code could be * SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID. */ GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, this, REQUEST_CODE_RECOVER_PLAY_SERVICES).show(); return false; } return true; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) { if (resultCode == RESULT_OK) { // Make sure the app is not already connected or attempting to connect if (!mGoogleApiClient.isConnecting() && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } else if (resultCode == RESULT_CANCELED) { Toast.makeText(this, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show(); finish(); } } } protected synchronized void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); } @Override public void onConnected(Bundle bundle) { } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(ConnectionResult connectionResult) { } }

Luego, en nuestro método "onStart", llamamos al método "conectar" y esperamos a que se invoque el método de devolución de llamada "onConnected":

 @Override protected void onStart() { super.onStart(); if (mGoogleApiClient != null) { mGoogleApiClient.connect(); } }

El método "onConnected" se verá así:

 @Override public void onConnected(Bundle bundle) { mLastLocation = LocationServices.FusedLocationApi.getLastLocation( mGoogleApiClient); if (mLastLocation != null) { Toast.makeText(this, "Latitude:" + mLastLocation.getLatitude()+", Longitude:"+mLastLocation.getLongitude(),Toast.LENGTH_LONG).show(); } }

Esta devolución de llamada se activa cuando Google Play Services está conectado, lo que significa que para entonces deberíamos tener la última ubicación conocida. Sin embargo, esta ubicación puede ser nula (es raro pero no imposible). En ese caso, lo que recomiendo es escuchar las actualizaciones de ubicación que se tratarán a continuación.

Escuchar actualizaciones de ubicación

Después de invocar "getLastLocation", es posible que desee solicitar actualizaciones periódicas del proveedor de ubicación fusionada. Dependiendo de su aplicación, este período puede ser corto o largo. Por ejemplo, si está creando una aplicación que rastrea la ubicación de un usuario mientras conduce, deberá escuchar las actualizaciones en intervalos cortos. Por otro lado, si su aplicación se trata de compartir la ubicación del usuario con su amigo, tal vez solo necesite solicitar la ubicación de vez en cuando.

Crear una solicitud es bastante fácil: puede llamar a este método dentro del método "onCreate":

 protected void createLocationRequest() { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(20000); mLocationRequest.setFastestInterval(5000); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); }

Instanciamos un nuevo objeto LocationRequest. Establezca el intervalo en 20 segundos (20000 milisegundos). Además, establecimos una velocidad de actualización acelerada de 5 segundos. Esto le dice a la API que proporcione actualizaciones cada 20 segundos (preferiblemente), pero si hay un cambio disponible dentro de un período de 5 segundos, también debería proporcionarlo. Finalmente, establecemos la prioridad en “PRIORITY_HIGH_ACCURACY”, entre las otras opciones de prioridad disponibles: PRIORITY_BALANCED_POWER_ACCURACY, PRIORITY_LOW_POWER, PRIORITY_NO_POWER.

Una vez que haya creado la solicitud, estará listo para comenzar a escuchar las actualizaciones de ubicación después de que se haya activado el método "onConnected()":

 protected void startLocationUpdates() { LocationServices.FusedLocationApi.requestLocationUpdates( mGoogleApiClient, mLocationRequest, this); }

Todo lo que queda ahora es implementar el método de devolución de llamada para satisfacer la interfaz LocationListener:

 public class MainActivity extends ActionBarActivity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener { // ... @Override public void onLocationChanged(Location location) { mLastLocation = location; Toast.makeText(this, "Latitude:" + mLastLocation.getLatitude()+", Longitude:"+mLastLocation.getLongitude(),Toast.LENGTH_LONG).show(); } } 

dejar de escuchar actualizaciones

Dejar de escuchar actualizaciones

Es importante dejar de escuchar explícitamente las actualizaciones cuando ya no las necesite o si el usuario abandona su aplicación. El siguiente método debe invocarse desde la devolución de llamada "onPause":

 protected void stopLocationUpdates() { if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates( mGoogleApiClient, this); } }

… y desconectando la API de Google:

 @Override protected void onStop() { super.onStop(); if (mGoogleApiClient != null) { mGoogleApiClient.disconnect(); } }

Terminando

Como puede ver, las ideas fundamentales detrás de la implementación de aplicaciones con reconocimiento de ubicación en Android son muy simples. Además, con las API disponibles que son simples de usar y fáciles de entender, debería ser obvio crear aplicaciones básicas basadas en la ubicación para Android. La pequeña aplicación de muestra que hemos creado aquí pretende demostrar exactamente eso. Puede encontrar el código fuente completo para esto en GitHub. Tenga en cuenta que, para simplificar las cosas, la aplicación no maneja el método de devolución de llamada "onConnectionFailed".

Con suerte, este tutorial lo ayudará a comenzar a usar la API de servicios de ubicación de Google.