¿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.
- ¿Hacer algo cuando el teléfono llega a un conjunto de ubicación?
- ¿Cuál es la manera más simple y más robusta de obtener la ubicación actual del usuario en Android?
- Navigator.geolocation.getCurrentPosition siempre obtiene un código de error 3: timeout expirado
- Cómo encontrar la distancia entre dos geopuntos?
- OnProviderEnabled no funciona?
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.
- ¿Cómo determinar la ubicación actual de un dispositivo Android, independientemente de la configuración de la ubicación del usuario?
- ¿Dónde estoy? - Obtener país
- Obtener la dirección particular utilizando latitud y longitud
- Buscar origen de ubicación mediante Fused Location Provider
- Cómo determinar la ubicación del dispositivo en Android mediante la dirección IP
- Cómo enviar datos al servidor en android
- Error al agregar geofences en Android (código de estado 1000)
- JavaScript La geolocalización no funciona en todos los navegadores de Android: funciona en iOS y PC
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).
- Prioridad de truncamiento de Android TextView o Resistencia de compresión
- ¿Cómo se muestra un CalendarView en un AlertDialog?