¿Cómo realizar un seguimiento continuo de la ubicación de un teléfono móvil Android?
Necesito escribir una aplicación, que cada 5 minutos determina la ubicación actual del teléfono móvil (utilizando todos los proveedores de ubicación gratuitos y disponibles) y lo envía a un servidor.
Si algún proveedor de ubicación no funciona al inicio de la aplicación, pero está disponible más tarde, la aplicación también debe procesar sus datos de ubicación.
Para hacer esto, implementé la siguiente clase. En una de mis actividades, creo una instancia de ella y la llamostartTrackingUpdates
método.locationChangeHandler
hace el procesamiento de los 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. Luego, por la mañana, tomé mi teléfono, fui a trabajar y luego volví a casa. En casa comprobé los resultados de un trabajo de un día de duración de la aplicación y encontré solo un registro en la base de datos.
Siempre que el resto del sistema (transmisión de datos de ubicación al servidor, guardando en la base de datos) funcione correctamente, debo tener algún problema en el código de seguimiento de ubicación (onLocationChanged
no fue invocado a pesar de que cambié mi ubicación varias veces).
¿Qué hay de malo con mi código? ¿Cómo debo cambiarlo?onLocationChanged
ser llamado siempre que la ubicación del teléfono cambie en más deMIN_DISTANCE_CHANGE_FOR_UPDATES
metros según uno de los proveedores de locatin)?
Actualización 1 (18.08.2013 13:59 MSK):
Cambié mi código de acuerdo amsh recomendaciones Arranco el temporizador usando el siguiente código:
public void startSavingGeoData() {
final IAlarmManager alarmManager = activity.getAlarmManager();
final IPendingIntent pendingIntent = activity.createPendingResult(
ALARM_ID, intentFactory.createEmptyIntent(), 0);
alarmManager.setRepeating(INTERVAL, pendingIntent);
}
En elactivity
Pongo siguiente controlador de eventos 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 enINTERVAL
milisegundos.
Pero cuando presiono el botón de encendido (la pantalla se desactiva),onActivityResult
No se invoca en absoluto. Cuando presiono el botón de encendido otra vez,onActivityResult
Se ejecuta tantas veces, comoINTERVAL
ha pasado desde el momento en que apagué el teléfono. Si apago el teléfono para1 * INTERVAL
milisegundos, se disparará una vez. Si apago el teléfono para2 * INTERVAL
milisegundos, se disparará dos veces, etc.
Nota: al "apagar" me refiero a una pulsación corta del botón de encendido (el teléfono aún "vive" y reacciona a los SMS entrantes, por ejemplo).
¿Cómo debo modificar el código destartSavingGeoData
en orden para el metodoonActivityResult
para ser ejecutado cadaINTERVAL
milisegundos, incluso cuando el teléfono duerme?
Actualización 2 (18.08.2013 19:29 MSK): NingunoalarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent)
, nialarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent)
resuelve el problema.