Processing para Android

EN ES

Geolocalización y permisos

Aprende a cómo acceder la ubicación usando GPS, y configurar correctamente los permisos de tu bosquejo en dipositivos con Android 6+.

Las API de geolocalización de Android

Un dispositivo Android puede determinar su ubicación con varios grados de precisión mediante el uso de la información de la red a la que está conectado (WiFi, celular), o de las señales de los satélites GPS (Sistema de posicionamiento global). La ubicación basada en GPS es más precisa, pero requiere estar al aire libre, además de consumir más batería y actualizarse con menos frecuencia que la ubicación basada en la red.

Creando un administrador de geolocalización

La estructura básica de un bosquejo que permite acceder a la información de ubicación es muy similar a la que vimos para otros sensores. Podemos obtener el administrador de geolocalización desde el contexto del app, fondo de pantalla o cara de reloj usando la función getContext() en la versión 4.0+ del modo (en 3 puede obtener una referencia a la actividad con getActivity()), y luego agregar un oyente de eventos al administrador:


import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.Manifest;

LocationManager locationManager;
MyLocationListener locationListener;

boolean hasLocation = false;

void setup () {
  fullScreen();
  orientation(PORTRAIT);  
  textFont(createFont("SansSerif", 26 * displayDensity));
  textAlign(CENTER, CENTER);
  requestPermission("android.permission.ACCESS_FINE_LOCATION", "initLocation");
}

void draw() {
}

void initLocation(boolean granted) {
  if (granted) {    
    Context context = getContext();
    locationListener = new MyLocationListener();
    locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);    
    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
    hasLocation = true;
  } else {
    hasLocation = false;
  }
}

class MyLocationListener implements LocationListener {
  public void onLocationChanged(Location location) {
    println(location.getLatitude(), location.getLongitude());
  }

  public void onProviderDisabled (String provider) { }

  public void onProviderEnabled (String provider) { }

  public void onStatusChanged (String provider, int status, Bundle extras) {
  }
}

Sin embargo, aquí estamos solicitando explícitamente el permiso para acceder la información de geolocalización con la función requestPermission(), y colocando el código de inicialización del administrador y el oyente dentro de la función initLocation() en lugar de hacerlo dentro de la función setup(), como en los ejemplos anteriores. La razón es que en las versiones de Android 6.0 y más nuevas, los permisos se dividen en dos niveles de protección: normal y peligroso. Los permisos clasificados como peligrosos determinan el acceso a datos privados del usuario, tales como la ubicación o la lista de contactos, y requiere que el usuario los otorgue de forma individual cuando ejecuta el app, y no cuando la misma es instalada.

El app mostrará un cuadro de diálogo solicitando permitir o denegar el permiso, y solo entonces se llamará a la función initLocation() con el resultado de la solicitud en el argumento booleano. Esta función, que debe contener el código de inicialización correspondiente al permiso que se solicita, no necesita llamarse initLocation, puede tener un nombre diferente, pero las dos reglas importantes que se deben seguir es que esta función reciba un argumento booleano, y que su nombre sea proporcionado como argumento a la función requestPermission().

Sin embargo, aún debemos seleccionar los permisos que necesita el bosquejo, en este caso ACCESS_COARSE_LOCATION y ACCESS_FINE_LOCATION para la ubicación de red y GPS, utilizando el selector de permisos en el PDE:

Selección de permiso

La variable de ubicación que recibimos en el oyente de eventos del sensor contiene toda la información necesaria para especificar la ubicación en latitud y longitud:


class MyLocationListener implements LocationListener {
  public void onLocationChanged(Location location) {
    currentLatitude  = (float)location.getLatitude();
    currentLongitude = (float)location.getLongitude();
    currentAccuracy  = (float)location.getAccuracy();
    currentProvider  = location.getProvider();
  }

  public void onProviderDisabled (String provider) { 
    currentProvider = "";
  }

  public void onProviderEnabled (String provider) { 
    currentProvider = provider;
  }

  public void onStatusChanged (String provider, int status, Bundle extras) {
  }
}

Comprobando si la geolocalización está disponible

Incluso si agregamos los permisos de geolocalización al bosquejo a través del selector, todavía puede ocurrir que el usuario no los otorge cuando ejecuta al app en su dispositivo. Por esta razón, tenemos que manejar la situación en la que la ubicación no está disponible. Para este fin disponemos de la función checkPermission(), que nos permite asegurarnos de que se haya otorgado un permiso dado y podamos acceder a la funcionalidad asociada:


void draw() {
  background(0);
  if (hasPermission("android.permission.ACCESS_FINE_LOCATION")) {
    text("Latitude: " + currentLatitude + "\n" +
         "Longitude: " + currentLongitude + "\n" +
         "Accuracy: " + currentAccuracy + "\n" +
         "Provider: " + currentProvider, 0, 0, width, height);
  } else {
    text("No permissions to access location", 0, 0, width, height);
  }
}

El código completo de este ejemplo está disponible aquí. Una vez que lo ejecute en un dispositivo con Android 6 o superior, el siguiente cuadro de diálogo que solicita los permisos de ubicación debería aparecer antes de mostrar cualquier otra cosa:

Diálogo de permiso

Después de permitir que tu aplicación acceda a la ubicación del dispositivo, obtendrás los valores de latitud y lenguaje a través del oyente de ubicación.