Servicios o "Daemons": LocationManager

La semana pasada vimos como crear un servicio o "daemon" que hiciera algún proceso aún cuando habíamos salido de nuestra aplicación. Fue un ejercicio muy sencillo donde además hicimos una clase para poder notificar en cualquier momento al usuario lo que quisiéramos. Ahora lo vamos a complicar un poco añadiendo un localizador a nuestro servicio, el cual nos puede servir para avisarnos que estamos cerca de algún lugar o lo que se os ocurra.

Lo básico de este ejercicio lo tenéis en la entrada anterior, cambios en el AndroidManifest.xml y otras cosas. Hoy nos centraremos en la clase donde tenemos el servicio. Vamos a ver la clase y a continuación la iré explicando:

public class LocationService extends Service implements LocationListener {

 boolean locationOn = false;
 int timeUpdate = 1000 * 60 * 1; //15 minutos
 long timeRefreshPost = 1000 * 60 * 1; //15 minutos
 float distanceUpdate = 500; //500 metros

    LocationManager locationManager;
    private final Handler handler = new Handler();
    
    public class MyBinder extends Binder{
     LocationService getService(){
            return LocationService.this;
        }
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return new MyBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        locationManager.removeUpdates(this);
        super.onDestroy();
    }

    @Override
    public void onStart(Intent intent, int startId) {
     handler.post(getData);
        super.onStart(intent, startId);
    }

    private final Runnable getData = new Runnable() {
        public void run() {
            getDataFrame();      
        }
    };

    private void getDataFrame() {
        if (locationOn){
            locationOn = false;
            stopGPS();
        }
        if (!locationOn){
             startGPS();            
             locationOn = true;
        }
        handler.postDelayed(getData, timeRefreshPost);
    }
    public void onLocationChanged(Location location) {
        if (location != null){
           doSomething(this.getApplicationContext(),
              (int)(location.getLatitude()*1E6), 
              (int)(location.getLongitude()*1E6));
        }

    }

    public void onProviderDisabled(String provider) {}

    public void onProviderEnabled(String provider) {}

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

    public void startGPS(){
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, timeUpdate, distanceUpdate,this);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, timeUpdate , distanceUpdate,this);
    }

    public void stopGPS(){
        locationManager.removeUpdates(this);        
    }    
    
    private final Handler handlerSearch = new Handler();
    private Runnable runRunnableAction;
    
 private void doSomething(Context context,final int latitud,final int longitud){
  runRunnableAction = new Runnable() { 
   public void run() {    
     NotifyManager notify = new NotifyManager();
     notify.playNotification(getApplicationContext(),
       HelloWorldActivity.class, "Cerca de tí hay algo"
       , "Notificación", R.drawable.notification);    
   }
  };
  
  Thread thread  = new Thread(){
   @Override
   public void run(){
    //Aqui se lanza una consulta a un servicio web pasandole la latitud y la longitud para buscar lo que se quiera
        
    handlerSearch.post(runRunnableAction);
   }
  };  
  thread.start();  
 }
}

Nuestra clase servicio va a heredar de Service como en la entrada anterior y además va a implementar un LocationListener, de este modo tendremos métodos como onLocationChanged que nos dará nuestra posición cada vez que esta cambie.

Las variables que utilizaremos son:

  • timeUpdate: nos dirá cada cuanto tiempo queremos refrescar nuestra posición.
  • distanceUpdate: indica cada cuanta distancia queremos refrescar nuestra posición.
  • timeRefreshPost: indica cada cuanto tiempo nuestro handler hace una petición.
  • locationOn: indica si tenemos la localización activa o no.
A parte de esto definiremos un handler y un LocationManager que nos ayudará a gestionar la posición del usuario. En el evento onStart de nuestro service será donde ponemos a andar nuestro handler enviando a su método post un Runnable getData.

En getData es donde se verifica si la localización está activa o no y se iniciará si no lo está. Este proceso se repetirá con postDelayed en el tiempo indicado en timeRefreshPost.

El método startGPS inicializará nuestro LocationManager. Con el método requestLocationUpdates controlamos las actualizaciones de la posición del usuario. Le indicamos el sistema de localización, en este caso se utiliza tanto la red móvil como el GPS, también le indicamos el tiempo de refresco y la distancia. El último parámetro es la propia clase, esto es porque está implementando un LocationListener y así ya tenemos los métodos en la propia clase, de no hacerlo así tendríamos que definir un LocationListener y asignarlo en vez del this.

En el onLocationChanged es el evento que se llama cada vez que se lancen las actualizaciones de posición. Aquí verificamos solo por seguridad que la posición no sea nula y lanzamos nuestro método doSomething, aquí cada uno hará lo que necesite. Buscar puntos cercanos a una posición dada por ejemplo.

El método doSomething define un Runnable donde se lanzarán las notificaciones y un Thread donde podemos por ejemplo realizar una búsqueda a un servicio web pasándole la latitud y la longitud. Una vez recogido el resultado podemos llamar a nuestro Runnable definido antes para lanzar la notificación con el método post de handlerSearch.

Como veis no he añadido ninguna llamada servicios web o cosas similares para no liar más el ejemplo y que quede simplemente la base para que vosotros podáis implementar lo que queráis o necesitéis.

Comments are closed.