Geolocalización en Android

La geolocalización en android es un servicio que nos proporciona el sistema para ubicar el dispositivo en coordenadas como lo son la latitud y longitud. Para obtener esta información existen multitud de formas, aunque la más conocida y popular es la localización por GPS, también es posible obtener la posición de un dispositivo por ejemplo a través de las antenas de telefonía móvil o mediante puntos de acceso Wi-Fi cercanos, y todos cada uno de estos mecanismos tiene una precisión, velocidad y consumo de recursos distinto. Por otro lado, el modo de funcionamiento de cada uno de estos mecanismos hace que su utilización desde nuestro código no sea todo lo directa e intuitiva que se desearía.

¿Qué mecanismos de localización tenemos disponibles?

Lo primero que debe conocer una aplicación que necesite obtener la geolocalización es qué mecanismos de localización (proveedores de localización, o location providers) tiene disponibles en el dispositivo.

La forma más sencilla de saber los proveedores disponibles en el dispositivo es mediante una llamada al método getAllProviders() de la clase LocationManager, clase principal en la que nos basaremos siempre a la hora de utilizar la API de localización de Android. Para ello, obtendremos una referencia al location manager llamando a getSystemService(LOCATION_SERVICE), y posteriormente obtendremos la lista de proveedores mediante el método citado para obtener la lista de nombres de los proveedores:

  
LocationManager locManager = (LocationManager)getSystemService(LOCATION_SERVICE);
List listaProviders = locManager.getAllProviders();

Una vez obtenida la lista completa de proveedores disponibles podríamos acceder a las propiedades de cualquiera de ellos (precisión, coste, consumo de recursos, o si es capaz de obtener la altitud, la velocidad, …). Así, podemos obtener una referencia al provider mediante su nombre llamando al método getProvider(nombre) y posteriormente utilizar los métodos disponibles para conocer sus propiedades, por ejemplo getAccuracy() para saber su precisión (tenemos disponibles las constantes Criteria.ACCURACY_FINE para precisión alta, y Criteria.ACCURACY_COARSE para precisión media), supportsAltitude() para saber si obtiene la altitud, ogetPowerRequirement() para obtener el nivel de consumo de recursos del proveedor. La lista completa de métodos para obtener las características de un proveedor se puede consultar en la documentación oficial de la clase LocationProvider.

  
LocationManager locManager = (LocationManager)getSystemService(LOCATION_SERVICE);
List listaProviders = locManager.getAllProviders();
 
LocationProvider provider = locManager.getProvider(listaProviders.get(0));
int precision = provider.getAccuracy();
boolean obtieneAltitud = provider.supportsAltitude();
int consumoRecursos = provider.getPowerRequirement();

Al margen de esto, hay que tener en cuenta que la lista de proveedores devuelta por el método getAllProviders() contendrá todos los proveedores de localización conocidos por el dispositivo, incluso si éstos no están permitidos (según los permisos de la aplicación) o no están activados, por lo que esta información puede que no nos sea de mucha ayuda.

¿Qué proveedor de localización es mejor para mi aplicación?

Android proporciona un mecanismo alternativo para obtener los proveedores que cumplen unos determinados requisitos entre todos los disponibles. Para ello nos permite definir un criterio de búsqueda, mediante un objeto de tipo Criteria, en el que podremos indicar las características mínimas del proveedor que necesitamos utilizar (podéis consultar la documentación oficial de la clase Criteria para saber todas las características que podemos definir). Así, por ejemplo, para buscar uno con precisión alta y que nos proporcione la altitud definiríamos el siguiente criterio de búsqueda:

En el código anterior, verificamos si el GPS está activado y en caso negativo mostramos al usuario un mensaje de advertencia. Este mensaje podríamos mostralo sencillamente en forma de notificación de tipo toast, pero en el próximo artículo sobre localización veremos cómo podemos, además de informar de que el GPS está desactivado, invitar al usuario a activarlo dirigiéndolo automáticamente a la pantalla de configuración del dispositivo.

El GPS ya está activado

Una vez que sabemos que nuestro proveedor de localización favorito está activado, ya estamos en disposición de intentar obtener nuestra localización actual. Y aquí es donde las cosas empiezan a ser menos intuitivas. Para empezar, en Android no existe ningún método del tipo “obtenerPosiciónActual()“. Obtener la posición a través de un dispositivo de localización como por ejemplo el GPS no es una tarea inmediata, sino que puede requerir de un cierto tiempo de procesamiento y de espera, por lo que no tendría sentido proporcionar un método de ese tipo. Si buscamos entre los métodos disponibles en la clase LocationManager, lo más parecido que encontramos es un método llamadogetLastKnownLocation(String provider), que como se puede suponer por su nombre, nos devuelve la última posición conocida del dispositivo devuelta por un provider determinado. Es importante entender esto: este método NO devuelve la posición actual, este método NO solicita una nueva posición al proveedor de localización, este método se limita a devolver la última posición que se obtuvo a través del proveedor que se le indique como parámetro. Y esta posición se pudo obtener hace pocos segundos, hace días, hace meses, o incluso nunca (si el dispositivo ha estado apagado, si nunca se ha activado el GPS, …). Por tanto, cuidado cuando se haga uso de la posición devuelta por el método getLastKnownLocation(). Entonces, ¿de qué forma podemos obtener la posición real actualizada? Pues la forma correcta de proceder va a consistir en algo así como activar el proveedor de localización y suscribirnos a sus notificaciones de cambio de posición. O dicho de otra forma, vamos a suscribirnos al evento que se lanza cada vez que un proveedor recibe nuevos datos sobre la localización actual. Y para ello, vamos a darle previamente unas indicaciones (que no ordenes, ya veremos esto en el próximo artículo) sobre cada cuanto tiempo o cada cuanta distacia recorrida necesitaríamos tener una actualización de la posición. Todo esto lo vamos a realizar mediante una llamada al método requestLocationUpdates(), al que deberemos pasar 4 parámetros distintos:

  • Nombre del proveedor de localización al que nos queremos suscribir.
  • Tiempo mínimo entre actualizaciones, en milisegundos.
  • Distancia mínima entre actualizaciones, en metros.
  • Instancia de un objeto LocationListener, que tendremos que implementar previamente para definir las acciones a realizar al recibir cada nueva actualización de la posición.

Tanto el tiempo como la distancia entre actualizaciones pueden pasarse con valor 0, lo que indicaría que ese criterio no se tendrá en cuenta a la hora de decidir la frecuencia de actualizaciones. Si ambos valores van a cero, las actualizaciones de posición se recibirán tan pronto y tan frecuentemente como estén disponibles. Además, como ya hemos indicado, es importante comprender que tanto el tiempo como la distancia especificadas se entenderán como simples indicaciones o “pistas” para el proveedor (al menos para versiones no recientes de Android), por lo que puede que no se cumplan de forma estricta. En el próximo artículo intentaremos ver esto con más detalle para entenderlo mejor. Por ahora nos basta con esta información.

En cuanto al listener, éste será del tipo LocationListener y contendrá una serie de métodos asociados a los distintos eventos que podemos recibir del proveedor:

  • onLocationChanged(location). Lanzado cada vez que se recibe una actualización de la posición.
  • onProviderDisabled(provider). Lanzado cuando el proveedor se deshabilita.
  • onProviderEnabled(provider). Lanzado cuando el proveedor se habilita.
  • onStatusChanged(provider, status, extras). Lanzado cada vez que el proveedor cambia su estado, que puede variar entre OUT_OF_SERVICE, TEMPORARILY_UNAVAILABLE, AVAILABLE.

Por nuestra parte, tendremos que implementar cada uno de estos métodos para responder a los eventos del proveedor, sobre todo al más interesante, onLocationChanged(), que se ejecutará cada vez que se recibe una nueva localización desde el proveedor. Veamos un ejemplo de cómo implementar un listener de este tipo:

  
LocationListener locListener = new LocationListener() {
 
    public void onLocationChanged(Location location) {
        mostrarPosicion(location);
    }
 
    public void onProviderDisabled(String provider){
        lblEstado.setText("Provider OFF");
    }
 
    public void onProviderEnabled(String provider){
        lblEstado.setText("Provider ON");
    }
 
    public void onStatusChanged(String provider, int status, Bundle extras){
        lblEstado.setText("Provider Status: " + status);
    }
};

Comentarios

  1. como haria para optener la localizacion (latitud, Longitud) en base a las antenas de telefonia celular. ??

    gracias..

    ResponderEliminar
    Respuestas
    1. Luis que pena no poder colaborar con la pregunta pero nunca he hecho algo parecido con Android.

      Eliminar

Publicar un comentario

Gracias por compartir tus comentarios con nosotros, si el comentario requiere de alguna respuesta por parte de nosotros, trataremos de responderte lo mas pronto posible.

Entradas populares de este blog

Como conectar MySQL con Android Nativo

Lista con imágenes Android nativo (ListView)

La nueva App de Android para trabajar