2013-08-15 17 views
9

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):alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 0, INTERVAL, pendingIntent), né alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, INTERVAL, INTERVAL, pendingIntent) risolto il problema.

+0

Il tipo di allarme deve essere una delle costanti _WAKEUP, ad esempio RTC_WAKEUP – msh

+0

@msh Vedere l'aggiornamento 2. –

+0

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

risposta

8

Il codice è probabilmente corretto, ma i provider di posizione non sono in esecuzione quando il telefono sta dormendo.Potrebbe essere necessario acquisire un wakelock (se non ti interessa il power draw), o usare AlarmManager e programmare la tua applicazione per svegliarti e controllare periodicamente la posizione (devi ancora avere wakelock attivo mentre aspetti un aggiornamento, sia acquisito da AlamManager o il tuo).

+0

ho cambiato il codice (vedi "Update 1"), ma ancora non funziona come previsto. Qualche idea? –

+0

È possibile basare il codice di allarme in questo esempio http://stackoverflow.com/questions/4459058/alarm-manager-example – msh

+0

Sì, questo esempio funziona, almeno il metodo per ottenere l'ubicazione viene eseguita anche, quando il telefono dorme. –

Problemi correlati