Devo scrivere un'app, che ogni 5 minuti determina la posizione corrente del telefono cellulare (utilizzando tutti i provider di posizione disponibili e gratuiti) e la invia a un server.Come monitorare continuamente la posizione di un telefono cellulare Android?
Se alcuni provider di località non funzionano all'inizio dell'applicazione, ma diventano disponibili successivamente, l'applicazione deve elaborare anche i relativi dati di posizione.
Per fare ciò, ho implementato la seguente classe. In una delle mie attività, creo una sua istanza e chiamo il suo metodo startTrackingUpdates
. locationChangeHandler
esegue l'elaborazione dei dati di posizione.
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) {
}
}
ho costruito l'applicazione e installato sul mio telefono cellulare. Poi, al mattino presi il mio telefono, andai a lavorare, poi tornai a casa. A casa ho controllato i risultati di un giorno di lavoro dell'applicazione e ho trovato solo un record nel database.
A condizione che il resto del sistema (trasmissione dei dati di posizione al server, salvataggio nel database) funzioni correttamente, devo avere qualche problema nel codice di localizzazione (onLocationChanged
non è stato richiamato anche se ho cambiato la mia posizione parecchie volte).
Cosa c'è di sbagliato nel mio codice (come dovrei cambiarlo, in modo che lo onLocationChanged
venga chiamato ogni volta che la posizione del telefono cambia di più di MIN_DISTANCE_CHANGE_FOR_UPDATES
metri in base a uno dei fornitori di locatine)?
Update 1 (2013/08/18 13:59 MSK):
ho cambiato il mio codice secondo msh raccomandazioni. Comincio il timer utilizzando il codice seguente:
public void startSavingGeoData() {
final IAlarmManager alarmManager = activity.getAlarmManager();
final IPendingIntent pendingIntent = activity.createPendingResult(
ALARM_ID, intentFactory.createEmptyIntent(), 0);
alarmManager.setRepeating(INTERVAL, pendingIntent);
}
Nel activity
ho messo seguente gestore di eventi timer:
@Override
protected void onActivityResult(final int aRequestCode, final int aResultCode,
final Intent aData) {
geoDataSender.processOnActivityResult(aRequestCode, aResultCode,
new IntentWrapper(aData));
}
Quando il telefono è acceso, tutto funziona come previsto - onActivityResult
viene eseguita una volta in INTERVAL
millisecondi.
Ma quando si preme il pulsante di alimentazione (lo schermo diventa disattivato), onActivityResult
non viene invocato affatto. Quando premo di nuovo il pulsante di accensione, onActivityResult
viene eseguito tutte le volte che è trascorso INTERVAL
dal momento in cui ho spento il telefono. Se spengo il telefono per 1 * INTERVAL
millisecondi, verrà generato una volta. Se spengo il telefono per 2 * INTERVAL
millisecondi, si spara due volte ecc.
Nota: "spegnendo" intendo una breve pressione del pulsante di accensione (il telefono continua a "vivere" e reagisce agli SMS in entrata, per esempio).
Come modificare il codice di startSavingGeoData
in modo che il metodo onActivityResult
venga eseguito ogni INTERVAL
millisecondi, anche quando il telefono è inattivo?
Aggiornamento 2 (2013/08/18 19:29 MSK): Né alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent)
, né alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent)
risolto il problema.
Il tipo di allarme deve essere una delle costanti _WAKEUP, ad esempio RTC_WAKEUP – msh
@msh Vedere l'aggiornamento 2. –
Provare prima http://stackoverflow.com/questions/4459058/alarm-manager-example prima - se funziona, basarsi su esso. Si noti che mantiene solo wakelock fino a quando non riceve restituisce, se è necessario eseguire più a lungo - acquisire il proprio – msh