¿Cómo manejar las actualizaciones del oyente de ubicación dentro de un servicio en Android?

Estoy trabajando en una aplicación que debe obtener la ubicación exacta del usuario continuamente si el usuario está dentro de una zona específica. Las actualizaciones de ubicación deben guardarse en un servidor (Parse.com) para que otros usuarios puedan obtener la ubicación actual del usuario.

El flujo es:

  1. Aplicación onCreate ->
  2. Inicio Servicio con LocationListener ->
  3. onLocationChanged ->
  4. guardar nueva ubicación en Parse.com ->
  5. Parse.com Cloud afterSave método enviar notificación push a los usuarios ->
  6. otros usuarios reciben notificaciones vía broadcast reciever ->
  7. actualizar marcador de usuario en el mapa <-

Preguntas:

  1. No estoy seguro de cómo implementar el paso 4, ¿debería guardar la nueva ubicación en el análisis en el método onLocationChanged? ¿Debo pasarlo a un BroadcastReciever y guardarlo en analizar allí? o debo pasarlo a un método estático en mi clase de CurrentUser que realizará el ahorro en el servidor?

  2. He notado que la documentación requestLocationUpdates dice:

    "Este método es adecuado para los casos de uso en primer plano, más específicamente para solicitar ubicaciones mientras se está conectado a LocationClient. Para casos de uso de fondo, se recomienda la versión de PendingIntent del método".

    En mi caso, ¿qué método debo utilizar?

  3. ¿Qué valores debo utilizar para obtener la ubicación casi en tiempo real sin consumir más del 5% de la energía de la batería por hora?

Mi clase de servicio:

public class UserTracker extends Service implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener{ static int GEOFENCE_STATUS; final static int INSIDE_GEOFENCE = 9001, OUTSIDE_GEOFENCE = 9002; static final int MINIMUM_ACCURACY = 26; final static int GEOFENCE_RADIUS = 2000; static final int NULL_LOCATION_ERROR = 7001; static final int INSIDE_INTERVAL = 10000, INSIDE_FASTEST_INTERVAL = 1000, INSIDE_SMALLEST_DISPLACEMENT = 10; static final int OUTSIDE_INTERVAL = 300000, OUTSIDE_FASTEST_INTERVAL = 60000, OUTSIDE_SMALLEST_DISPLACEMENT = 100; static Location eventLocation; LocationClient lc; @Override public void onCreate() { super.onCreate(); eventLocation = new Location("Test"); lc = new LocationClient(getApplicationContext(), this, this); } @Override public int onStartCommand(Intent intent, int flags, int startId) { double eventLat = intent.getDoubleExtra("Latitude", -1); double eventLon = intent.getDoubleExtra("Longitude", -1); if (eventLat == -1 || eventLon == -1) { stopSelf(); return START_REDELIVER_INTENT; } eventLocation.setLatitude(eventLat); eventLocation.setLongitude(eventLon); lc.connect(); return START_STICKY; } public int getGeofenceStatus(Location currentLocation) { if (currentLocation == null) { return NULL_LOCATION_ERROR; } if (currentLocation.distanceTo(eventLocation) > GEOFENCE_RADIUS) { Log.d(TAG, "User is outside geofence"); return OUTSIDE_GEOFENCE; } else { Log.d(TAG, "User is inside geofence"); return INSIDE_GEOFENCE; } } public void requestLocationUpdates(int status) { GEOFENCE_STATUS = status; LocationRequest request = LocationRequest.create(); switch (status) { case NULL_LOCATION_ERROR: stopSelf(); break; case INSIDE_GEOFENCE: request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); request.setInterval(INSIDE_INTERVAL); request.setFastestInterval(INSIDE_FASTEST_INTERVAL); request.setSmallestDisplacement(INSIDE_SMALLEST_DISPLACEMENT); break; case OUTSIDE_GEOFENCE: request.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); request.setInterval(OUTSIDE_INTERVAL); request.setFastestInterval(OUTSIDE_FASTEST_INTERVAL); request.setSmallestDisplacement(OUTSIDE_SMALLEST_DISPLACEMENT); break; } lc.requestLocationUpdates(request, this); } @Override public void onLocationChanged(Location location) { int newStatus = getGeofenceStatus(location); int accuracy = (int) location.getAccuracy(); String message = "Geofence status: " + newStatus + "\nAccuracy: " + accuracy + "\nDistance to event: " + location.distanceTo(eventLocation); Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show(); if (newStatus == INSIDE_GEOFENCE && accuracy < MINIMUM_ACCURACY) { Log.d(TAG, "Accuracy is good"); // do the save on server procees } if (GEOFENCE_STATUS != newStatus) { requestLocationUpdates(newStatus); } } @Override public void onConnectionFailed(ConnectionResult result) { Log.d(TAG, "LocationClient connection failed: " + result.getErrorCode()); } @Override public void onConnected(Bundle arg0) { Location currentLocation = lc.getLastLocation(); requestLocationUpdates(getGeofenceStatus(currentLocation)); } @Override public void onDisconnected() { Log.d(TAG, "LocationClient disconnected"); } @Override public IBinder onBind(Intent intent) { return null; } } 

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.