¿Cómo realizar un seguimiento continuo de la ubicación de un teléfono móvil Android?

Tengo que escribir una aplicación, que cada 5 minutos determina la ubicación actual del teléfono móvil (usando todos los proveedores de localización disponibles y gratuitos) y lo envía a un servidor.

Si algún proveedor de ubicación no funciona al inicio de la aplicación, pero se vuelve disponible posteriormente, la aplicación también debería procesar sus datos de ubicación.

Para ello, implementé la siguiente clase. En una de mis actividades, creo una instancia de ella y llamo a su método startTrackingUpdates . locationChangeHandler realiza el procesamiento de datos de ubicación.

 public class LocationTracker implements ILocationTracker, LocationListener { public static final long MIN_TIME_BETWEEN_UPDATES = 1000 * 60 * 5; // 5 minutes public static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters private ILocationManager locationManager; private ILocationChangeHandler locationChangeHandler; public LocationTracker(final ILocationManager aLocationManager, final ILocationChangeHandler aLocationChangeHandler) { this.locationManager = aLocationManager; this.locationChangeHandler = aLocationChangeHandler; } public void startTrackingUpdates() { final List<String> providers = locationManager.getAllProviders(); for (final String curProviderName : providers) { final ILocationProvider provider = locationManager.getLocationProvider(curProviderName); if (!provider.hasMonetaryCost()) { subscribeToLocationChanges(provider); } } } private void subscribeToLocationChanges(final ILocationProvider aProvider) { locationManager.requestLocationUpdates(aProvider.getName(), MIN_TIME_BETWEEN_UPDATES, (float)MIN_DISTANCE_CHANGE_FOR_UPDATES, this); } public void onLocationChanged(final Location aLocation) { locationChangeHandler.processLocationChange(new LocationWrapper(aLocation)); } public void onProviderDisabled(final String aProvider) { } public void onProviderEnabled(final String aProvider) { } public void onStatusChanged(final String aProvider, final int aStatus, final Bundle aExtras) { } } 

Construí la aplicación y la instalé en mi teléfono móvil. Entonces, por la mañana tomé mi teléfono, fui a trabajar, luego volví a casa. En casa comprobé los resultados de un día de trabajo de la aplicación y encontré sólo un registro en la base de datos.

Siempre que el resto del sistema (transmisión de datos de ubicación al servidor, guardar en la base de datos) funcione correctamente, debo tener algún problema en el código de seguimiento de ubicación ( onLocationChanged no se invocó aunque cambié mi ubicación varias veces).

¿Qué hay de malo en mi código (¿cómo debo cambiarlo, para que el onLocationChanged se llame cada vez que la ubicación del teléfono cambia por más de MIN_DISTANCE_CHANGE_FOR_UPDATES metros de acuerdo con uno de los proveedores de locatin)?

Actualización 1 (18.08.2013 13:59 MSK):

He cambiado mi código de acuerdo con las recomendaciones msh . Inicie el temporizador utilizando el código siguiente:

 public void startSavingGeoData() { final IAlarmManager alarmManager = activity.getAlarmManager(); final IPendingIntent pendingIntent = activity.createPendingResult( ALARM_ID, intentFactory.createEmptyIntent(), 0); alarmManager.setRepeating(INTERVAL, pendingIntent); } 

En la activity que pongo después del manejador de eventos del temporizador:

 @Override protected void onActivityResult(final int aRequestCode, final int aResultCode, final Intent aData) { geoDataSender.processOnActivityResult(aRequestCode, aResultCode, new IntentWrapper(aData)); } 

Cuando el teléfono está encendido, todo funciona como se espera – onActivityResult se ejecuta una vez en INTERVAL milisegundos.

Pero cuando onActivityResult el botón de encendido (la pantalla se deshabilita), onActivityResult no se invoca en absoluto. Cuando vuelvo a pulsar el botón de encendido, onActivityResult se ejecuta tantas veces como INTERVAL ha pasado desde el momento en que apagué el teléfono. Si apagué el teléfono durante milisegundos de 1 * INTERVAL , se disparará una vez. Si apagué el teléfono durante 2 * INTERVAL , se disparará dos veces, etc.

Nota: Al "apagar" me refiero a presionar brevemente el botón de encendido (el teléfono todavía "vive" y reacciona a los SMS entrantes, por ejemplo).

¿Cómo debo modificar el código de startSavingGeoData para que el método onActivityResult se ejecute cada milisegundos INTERVAL , incluso cuando el teléfono duerme?

Actualización 2 (18.08.2013 19:29 MSK): Ni alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent) , ni alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent) resuelto el problema.

Su código es probablemente correcto, pero los proveedores de ubicación no se están ejecutando cuando el teléfono está durmiendo. Es posible que necesite adquirir un wakelock (si no le importa el power draw), o usar AlarmManager y programar su aplicación para que se despierte y compruebe la ubicación periódicamente (todavía necesita tener un wakelock activo mientras espera una actualización, o bien Adquirido por AlamManager, o el suyo propio).

  • Java io ioexception no puede analizar la respuesta del geocoder de servidor
  • ¿Qué dispositivos admiten Android Batching de sensores?
  • ¿Qué tan confiable es LocationLastKnownLocation de LocationManager y con qué frecuencia se actualiza?
  • LocationListener funciona en el emulador, no en el teléfono
  • ¿Google ofrece una API que puedo usar para obtener la ubicación de mi teléfono?
  • Android: Cómo inicializar una variable de tipo "Ubicación" (que no sea igual a null)
  • ¿Cómo comprobar si la ubicación está disponible utilizando FusedLocationProviderApi y GoogleClient?
  • Error getFromLocationName, Servicio no disponible. Han estado trabajando, se detuvo
  • Geolocalización de webview de android
  • Cómo mostrar mi ubicación en Google Maps para Android API v2
  • ¿Existe una alternativa al Cliente de ubicación (API de Google Play)?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.