2013-03-09 11 views
10

Otrzymuję swoją ostatnią znaną lokalizację, ale nie od tego, ile czasu upłynęło od ostatniej aktualizacji mojej lokalizacji. Jak mogę się dowiedzieć, ile czasu minęło od ostatniej aktualizacji lokalizacji?Jak dawno temu zarejestrowano ostatnią znaną lokalizację?

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

Jak o subskrypcji aktualizacji lokalizacji i pomiaru różnicy czasu pomiędzy odebranymi aktualizacji? Gdy otrzymasz aktualizację lokalizacji, instancja Location pozwala ci pobrać czas aktualizacji za pomocą getTime() (uwaga: jest w UTC). – AgentKnopf

+0

['location.getTime();'] (http://developer.android.com/reference/android/location/Location.html#getTime%28%29) mówi o ['getElapsedRealtimeNanos()'] (http: //developer.android.com/reference/android/location/Location.html#getElapsedRealtimeNanos%28%29), aby obliczyć wiek poprawki i porównać poprawki lokalizacji. [Przykład] (https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/utils/GingerbreadLastLocationFusion.java) na [blogu] (http : //android-developers.blogspot.com/2011/06/deep-dive-into-location.html) używa 'getTime()'. – kush

+0

Metoda getElapsedRealtimeNanos() jest zalecanym podejściem, ale jest dostępna tylko w API 17 (4.2) i nowszych wersjach, więc getTime jest naprawdę jedyną rzeczą, której można użyć w momencie pisania ... – JamesSugrue

Odpowiedz

19

Najlepszym rozwiązaniem zarówno przed i po 17 API:

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(); 
} 

Wstępnie 17 nie jest zbyt dokładne, ale powinna być wystarczająca, aby sprawdzić, czy lokalizacja jest bardzo stary.

To, jak sądzę, byłoby 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 

} 

Sprawa stosowanie typowych dla tej logiki jest gdy aplikacja właśnie rozpoczęła i musimy wiedzieć, czy mamy musi czekać do nowej lokalizacji lub możemy korzystać z najnowszej wersji teraz, gdy czekamy na nową lokalizację.

+0

Uważam, że to rozwiązanie ma jedną wadę - wyobraź sobie, gdybym przechowywał lastLocation w jakimś magazynie pamięci trwałej. Powiedzmy, że otrzymałem ostatnią aktualizację lokalizacji 3 godziny od ostatniego restartu telefonu. Ta aktualizacja lokalizacji jest przechowywana w pamięci masowej. Następnie ponownie uruchomię telefon i zadzwonię "age_minutes (last)". Dostałbym SystemClock = ~ 1min i lastLocation = 3 godziny. "age_minutes" zwróci true, co nie jest poprawne. – Michal

+0

@Michal Błąd polega na tym, że sam przechowujesz ostatnie miejsce. Zawsze pytaj 'locationManager' &' provider' jak w wierszu w pytaniu: 'Location location = locationManager.getLastKnownLocation (provider);' – weston

+0

@Michal, jeśli tego nie zrobisz i zapiszesz ostatnią lokalizację samemu, a następnie dodatkowo powodując błąd, o którym mówisz, nie będziesz korzystać z innych aplikacji żądających lokalizacji. – weston

1

Każda lokalizacja ma atrybut czas. Zdobądź to z getTime(). Porównaj z bieżącym czasem. (Oblicz różnicę). To daje ci "wiek".

5

Location.getTime() w rzeczywistości nie jest najlepszym sposobem na znalezienie wieku ostatniej znanej lokalizacji.

Z JavaDoc:

zwróci czas UTC tej poprawki w milisekundach od 1 stycznia 1970.

Należy pamiętać, że czas UTC w urządzeniu nie jest monotoniczny: może skoczyć do przodu lub nieprzewidywalnie wstecz. Dlatego zawsze używaj getElapsedRealtimeNanos podczas obliczania delt czasu.

Obie metody wykorzystują to:

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

Należy również zauważyć, że LocationManager.lastKnownLocation() może zwrócić puste.

7

Przepraszam za ponowne otwarcie, ale myślę, że odpowiedź Westona jest niepoprawna, , a dokumentacja Androida jest co najmniej myląca.

Podstawa czasu dla getTime() jest UTC jak wynika z wyroku NMEA otrzymane z modułu GPS, nie System.currentTimeMillis(). GPS czas jest dokładny do nanosekund (musi to być, ponieważ fale elektromagnetyczne przemieszczają się 30 cm w 1ns). Jedynym problemem jest to, że może być wyłączony przez 1s z powodu do sekundowego kroku GPS (patrz [1], może się zdarzyć w ciągu kilku minut co kilka lat, przy założeniu, że GPS jest wystarczająco inteligentny, aby zapamiętać przesunięcie UTC przez cały cykl zasilania)

Z drugiej strony, System.currentTimeMillis() może być wyłączony przez kilka sekund/minut z powodu dryfu, a nawet więcej, jeśli użytkownik ustawi niepoprawnie datę/godzinę.

Zatem jedynym prawdziwym rozwiązaniem pre-API 17 jest , aby regularnie otrzymywać aktualizacje lokalizacji i za każdym razem zapisywać własny znacznik czasu oparty na SystemClock.elapsedRealtime().

Po prostu wypróbowałem to na Samsung S4, proszę poprawić mnie, jeśli inne telefony dają różne wyniki. Wątpię w to.

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

+0

Myślę, że masz rację. Tylko to widziałem przez przypadek. Powinieneś opublikować krytykę jako komentarz do mojej odpowiedzi, bo inaczej tego nie zobaczę. – weston

+0

Dodałem informację o tym, jak powinno być używane. – weston

+0

Jeśli zdobędę kolejną wersję, będę miał dość reputacji, aby publikować komentarze :) (ten wydaje się być wyjątkiem, ponieważ odpowiadam na mój post) –