robado - ¿Cómo rastrear continuamente la ubicación de un teléfono móvil Android?
localizar numero de celular por satelite gratis (1)
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 disponibles gratuitos) 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 adelante, 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 la misma y llamo a su método startTrackingUpdates
. locationChangeHandler
realiza 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) {
}
}
Creé la aplicación y la instalé en mi teléfono móvil. Luego, en la mañana, tomé mi teléfono, fui a trabajar y luego regresé a casa. En casa revisé los resultados de un trabajo de un día 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, guardado en la base de datos) funcione correctamente, debo tener algún problema en el código de seguimiento de ubicación (no se invocó onLocationChanged
aunque cambié mi ubicación varias veces).
¿Qué ocurre con mi código (cómo debería cambiarlo, para que se onLocationChanged
a onLocationChanged
siempre que la ubicación del teléfono cambie en más de MIN_DISTANCE_CHANGE_FOR_UPDATES
metros de acuerdo con uno de los proveedores de ubicación)?
Actualización 1 (18.08.2013 13:59 MSK):
Cambié mi código de acuerdo con las recomendaciones de msh . Comienzo 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 la activity
pongo el siguiente controlador 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 esperaba: onActivityResult
se ejecuta una vez en INTERVAL
milisegundos.
Pero cuando onActivityResult
el botón de encendido (la pantalla se desactiva), onActivityResult
no se invoca en absoluto. Cuando onActivityResult
botón de encendido nuevamente, onActivityResult
se ejecuta tantas veces como INTERVAL
ha pasado desde que onActivityResult
el teléfono. Si apagué el teléfono durante 1 * INTERVAL
milisegundos, se disparará una vez. Si apagué el teléfono durante 2 * INTERVAL
milisegundos, se dispararán dos veces, etc.
Nota: Al "apagar" me refiero a presionar brevemente el 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 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)
resolvió el problema.
Es probable que su código sea correcto, pero los proveedores de ubicación no se están ejecutando cuando su teléfono está inactivo. Es posible que necesite adquirir un wakelock (si no le importa el consumo de energía), o use AlarmManager y programe su aplicación para que se despierte y verifique la ubicación periódicamente (aún necesita tener wakelock activo mientras espera una actualización, ya sea adquirido por AlamManager, o el suyo).