2013-03-09 8 views
10

Sto ricevendo la mia ultima posizione nota, ma non quanto tempo è passato dall'ultima volta che la mia posizione è stata aggiornata. Come posso sapere quanto tempo è trascorso dall'ultimo aggiornamento della posizione?Quanto tempo fa è stata registrata l'ultima posizione conosciuta?

LocationManager locationManager 
         = (LocationManager) getSystemService(LOCATION_SERVICE); 
Criteria c = new Criteria(); 
    c.setAccuracy(Criteria.ACCURACY_FINE); 
    c.setAccuracy(Criteria.ACCURACY_COARSE); 
    c.setAltitudeRequired(false); 
    c.setBearingRequired(false); 
    c.setCostAllowed(true); 
    c.setPowerRequirement(Criteria.POWER_HIGH); 
String provider = locationManager.getBestProvider(c, true); 
Location location = locationManager.getLastKnownLocation(provider); 
+0

Come circa la sottoscrizione per aggiornamenti sulla posizione e misurando la differenza di tempo tra gli aggiornamenti ricevuti? Quando ottieni un aggiornamento di posizione, l'istanza di posizione ti consente di recuperare l'ora dell'aggiornamento tramite getTime() (attenzione però, è in UTC). – AgentKnopf

+0

['location.getTime();'] (http://developer.android.com/reference/android/location/Location.html#getTime%28%29) parla di ['getElapsedRealtimeNanos()'] (http: //developer.android.com/reference/android/location/Location.html#getElapsedRealtimeNanos%28%29) per calcolare l'età di una correzione e confrontare le correzioni di posizione. L'[esempio] (https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/utils/GingerbreadLastLocationFinder.java) in [il blog] (http : //android-developers.blogspot.com/2011/06/deep-dive-into-location.html) usa 'getTime()'. – kush

+0

getElapsedRealtimeNanos() è l'approccio consigliato in futuro, ma è disponibile solo in API 17 (4.2) e sopra, quindi getTime è davvero l'unica cosa da usare al momento della scrittura ... – JamesSugrue

risposta

19

opzione migliore sia per il pre e post API 17:

public int age_minutes(Location last) { 
    return age_ms(last)/(60*1000); 
} 

public long age_ms(Location last) { 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) 
     return age_ms_api_17(last); 
    return age_ms_api_pre_17(last); 
} 

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 
private long age_ms_api_17(Location last) { 
    return (SystemClock.elapsedRealtimeNanos() - last 
      .getElapsedRealtimeNanos())/1000000; 
} 

private long age_ms_api_pre_17(Location last) { 
    return System.currentTimeMillis() - last.getTime(); 
} 

Il pre 17 non è molto preciso, ma dovrebbe essere sufficiente per verificare se una posizione è molto antica.

Questa, direi, sarebbe OK:

if (age_minutes(lastLoc) < 5) { 
    // fix is under 5 mins old, we'll use it 

} else { 
    // older than 5 mins, we'll ignore it and wait for new one 

} 

Il caso d'uso consueto per questa logica è quando l'applicazione è appena iniziata e abbiamo bisogno di sapere se ci dobbiamo aspettare una nuova posizione oppure puoi usare l'ultimo per ora mentre aspettiamo una nuova posizione.

+0

Credo che questa soluzione abbia un difetto - immagina se ho avuto lastLocation memorizzato in un archivio di persistenza. Diciamo che ho ricevuto l'ultimo aggiornamento della posizione 3 ore dall'ultimo riavvio del telefono. Questo aggiornamento di posizione è archiviato in una memoria. Quindi riavvio il mio telefono e chiamo "age_minutes (last)". Otterrei SystemClock = ~ 1min e lastLocation = 3hours. "age_minutes" restituirebbe true che non è corretto. – Michal

+0

@Michal Il difetto sta pensando di memorizzare da solo l'ultima posizione. Chiedi sempre il 'locationManager' &' provider' secondo la riga nella domanda: 'Posizione posizione = locationManager.getLastKnownLocation (provider);' – weston

+0

@Michal se non lo fai e salva l'ultima posizione da te, poi in aggiunta per causare il bug di cui parli, non trarrai beneficio da altre app che richiedono una posizione. – weston

1

Ogni posizione ha un tempo di attributo. Scaricalo con getTime(). Confrontalo con l'ora corrente. (Calcola la differenza). Questo ti dà l '"età".

5

Location.getTime() non è in realtà il modo migliore per trovare l'età dell'ultima posizione nota.

Dal JavaDoc:

Ritorna l'ora UTC di questa correzione, in millisecondi dal 1 gennaio 1970.

Nota che il tempo UTC su un dispositivo non è monotona: si può saltare in avanti o indietro imprevedibilmente. Quindi usa sempre getElapsedRealtimeNanos quando calcoli i delta di tempo.

I due metodi da utilizzare sono:

SystemClock.elapsedRealtimeNanos(); 
Location.getElapsedRealtimeNanos(); 

noti inoltre che LocationManager.lastKnownLocation() possono restituire null.

7

Ci scusiamo per riaprire questo, ma penso che la risposta di Weston sia errata, e la documentazione di Android sia almeno fuorviante.

La base dei tempi per getTime() è UTC, come determinato dalla frase NMEA ricevuti dal modulo GPS, non System.currentTimeMillis(). Il tempo del GPS è preciso per i nanosecondi (lo è perché le onde elettromagnetiche viaggiano a 30 cm in 1ns). La complicazione di è che potrebbe essere spenta di 1s dovuto a a un balzo secondo GPS (vedi [1], questo può succedere in pochi minuti ogni pochi anni, supponendo che il GPS sia abbastanza intelligente da ricordare l'offset UTC attraverso i cicli di alimentazione)

D'altra parte, System.currentTimeMillis() può essere disattivato di diversi secondi/minuti a causa di deriva o anche di più se l'utente imposta l'ora/data in modo errato.

Quindi l'unica soluzione reale pre-API 17 è per ricevere gli aggiornamenti di posizione regolarmente e ogni volta che registra il proprio timestamp basato su SystemClock.elapsedRealtime().

Ho appena provato questo su un Samsung S4, correggimi se altri telefoni danno risultati diversi. Ne dubito, comunque.

[1] http://en.wikipedia.org/wiki/Global_Positioning_System#Leap_seconds

+0

Penso che tu abbia ragione. Ho appena visto questo per caso. Dovresti postare recensioni come commento sulla mia risposta altrimenti non la vedrò. – weston

+0

Ho aggiunto informazioni su come dovrebbe essere usato – weston

+0

Se ottengo un altro upvote, avrò abbastanza reputazione per postare commenti :) (questo sembra essere un'eccezione dato che sto rispondendo al mio stesso post) –

Problemi correlati