Geolocalización

Acceder a la capacidad de geolocalización de los dispositivos con Android implica trabajar con su servicio LocationManager. Este es un servicio que puede proporcionar coordenadas de latitud, longitud y un valor para la precisión a través tanto de consultas a GPS como a consultas a una base de datos de redes wifi previamente localizadas. Cada una de estas fuentes en este contexto recibe el nombre de proveedor.

Manejar correctamente este servicio supone ser capaz de permitir a la app elegir entre uno u otro proveedor según la situación. Habida cuenta de que el GPS proporciona datos sólo cuando hay visibilidad, que consume a su vez la batería a gran velocidad, y que estos sin embargo son mucho más precisos que los de las redes wifi, es necesario que la parte del software que se encargue de la geoposición sepa altenar y encontrar el equilibrio entre el uso de un proveedor y el otro. Una guía orientativa que describe este balance puede leerse aquí.

A partir del ejemplo de Rolf van Gelder publicado en el wiki de Processing para Android y de las maticaciones que se encuentran en este hilo del foro de Processing hemos construido una clase que simplifica la obtención de coordenadas a partir de estos servicios.

Esta clase, sin embargo, no trabaja la cuestión de la alternancia entre proveedores. Esta otra clase publicada por un usuario de stackOverflow parece mucho más recomendable para un desarrollo orientado a producción, y será la que próximamente utilizaremos en esta sección.

IMPORTANTE: Para acceder a estos proveedores tenemos que marcar los permisos ACCESS_COARSE_LOCATION y ACCESS_FINE_LOCATION en Android > Sketch permissions.

Clase GPS

/*****************************************************************************************
 Android Processing GPS example
 Query the phone's GPS and display the data on the screen
 Rolf van Gelder - v 22/02/2011 - http://cage.nl :: http://cagewebdev.com :: info@cage.nl
 Check the ACCESS_FINE_LOCATION permission in Sketch Permissions! 
 
 Añadidos de http://forum.processing.org/topic/gps
 Check the ACCESS_COARSE_LOCATION
 LocationManager.GPS_PROVIDER en lugar LocationManager.NETWORK_PROVIDER
 
 *****************************************************************************************/
 
// Import needed Android libs
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.location.GpsStatus.Listener; 
 
// Set up the variables for the LocationManager and LocationListener
LocationManager locationManager;
MyLocationListener locationListener;
 
 
class GPS {
 
  // Variables to hold the current GPS data
  float currentLatitude  = 0;
  float currentLongitude = 0;
  float currentAccuracy  = 0;
  String currentProvider = "NO INICIADO. BLOQUEA Y DESBLOQUEA TU DISPOSITIVO PARA INTENTAR DE NUEVO.";  
 
  int minTime;
  float minDistance;
 
  // If minTime is greater than 0, the LocationManager could potentially 
  // rest for minTime milliseconds between location updates to conserve power.
  // If minDistance is greater than 0, a location will only be broadcasted
  // if the device moves by minDistance meters. To obtain notifications as 
  // frequently as possible, set both parameters to 0.
 
  GPS(int minTime_, float minDistance_) {
    minTime = minTime_;
    minDistance = minDistance_;
  }
 
  void start() {
    locationListener = new MyLocationListener(this);
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);    
 
    // Register the listener with the Location Manager to receive location updates
    //requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)    
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, (long)minTime, minDistance, locationListener);
  }
}

Esta clase requiere a su vez esta otra:

/*****************************************************************/
// Class for capturing the GPS data
 
class MyLocationListener implements LocationListener {
 
  GPS gps;
 
  MyLocationListener(GPS gps_) {
    gps = gps_;
  }
 
  // Define all LocationListener methods
 
  void onLocationChanged(Location location) {
    // Save new GPS data
    gps.currentLatitude  = (float)location.getLatitude();
    gps.currentLongitude = (float)location.getLongitude();
    gps.currentAccuracy  = (float)location.getAccuracy();
    gps.currentProvider  = location.getProvider();
  }
 
 
  void onProviderDisabled (String provider) { 
    gps.currentProvider = "PROVIDER DISABLED";
  }
 
 
  void onProviderEnabled (String provider) { 
    gps.currentProvider = provider;
  }
 
 
  void onStatusChanged(String provider, int status, Bundle extras) {
  }  
}

Veamos a continuación cómo usar esta clase GPS paso a paso.

1. Declaración

GPS gps;

2. Inicialización

// En setup()
gps = new GPS(1000, 20);

El objeto que inicializamos va a lanzar periódicamente un método de actualización de nuestras coordenadas. El primero de los parámetros de esta inicialización es el tiempo entre actualizaciones en milisegundos. El segundo, la distancia que tenemos que haber recorrido para que la actualización de coordenadas se comunique a todo el programa.

3. Puesta en marcha

// En onResume()
void onResume() {
  super.onResume();
  if (gps != null) gps.start();
}

onResume() es un método que se ejecuta al iniciar el app y cada vez que ésta aparece en la pantalla tras un bloqueo o fundido a negro del dispositivo. Dado que por ahorro de energía cuando el app está en modo reposo el gps detiene su actividad, es necesario lanzar el servicio cada vez que volvemos a reanimarlo.

4. Nuestras coordenadas estarán disponibles en:

//    gps.currentLatitude
//    gps.currentLongitude
//    gps.currentAccuracy
//    gps.currentProvider