2013-03-09 11 views
10

Я получаю свое последнее известное местоположение, но не так, как долго это было с тех пор, как мое местоположение было в последний раз обновлено. Как узнать, сколько времени прошло с момента последнего обновления местоположения?Как давно было зарегистрировано последнее известное местоположение?

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

Как насчет подписки на обновления местоположения и измерения разницы во времени между полученными обновлениями? Когда вы получаете обновление местоположения, экземпляр Location позволяет вам получить время обновления через getTime() (будьте осторожны, но это в UTC). – AgentKnopf

+0

['location.getTime();'] (http://developer.android.com/reference/android/location/Location.html#getTime%28%29) говорит о ['getElapsedRealtimeNanos()'] (http: //developer.android.com/reference/android/location/Location.html#getElapsedRealtimeNanos%28%29), чтобы рассчитать возраст исправления и сравнить исправления местоположения. [Пример] (https://code.google.com/p/android-protips-location/source/browse/trunk/src/com/radioactiveyak/location_best_practices/utils/GingerbreadLastLocationFinder.java) в [блоге] (http : //android-developers.blogspot.com/2011/06/deep-dive-into-location.html) использует 'getTime()'. – kush

+0

getElapsedRealtimeNanos() - рекомендуемый подход в будущем, но доступен только в API 17 (4.2) и выше, поэтому getTime - это единственное, что нужно использовать на момент написания ... – JamesSugrue

ответ

19

Лучший вариант для обоих до и после 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(); 
} 

Предварительно 17 не очень точны, но должно быть достаточным, чтобы проверить, если место очень старый.

Это, я думаю, все будет в порядке:

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 

} 

Обычным примером использования этой логики, когда приложение только началось, и мы должны знать, является ли мы должны ждать новое место или можете использовать последнее на данный момент, пока мы ждем нового местоположения.

+0

Я считаю, что это решение имеет один недостаток - представьте, если бы у меня было lastLocation, хранящееся в каком-то хранилище настойчивости. Скажем, я получил последнее обновление местоположения 3 часа с момента последней перезагрузки телефона. Это обновление местоположения хранится в хранилище. Затем я снова перезагружу свой телефон и назову «age_minutes (last)». Я бы получил SystemClock = ~ 1min и lastLocation = 3hours. «age_minutes» вернет true, что неверно. – Michal

+0

@Michal Недостаток мысли, что вы храните последнее место самостоятельно. Всегда задавайте «locationManager» и «поставщик» в соответствии с линией в вопросе: «Location location = locationManager.getLastKnownLocation (поставщик);' – weston

+0

@Michal, если вы этого не сделаете и сохраните последнее местоположение самостоятельно, то дополнительно чтобы вызвать ошибку, о которой вы говорите, вы не сможете воспользоваться другими приложениями, запрашивающими местоположение. – weston

1

В каждом месте есть время атрибута. Получите его с getTime(). Сравните его с текущим временем. (Рассчитайте разницу). Это дает вам «возраст».

5

Location.getTime() на самом деле не лучший способ найти возраст последнего известного местоположения.

От JavaDoc:

Вернуть время UTC данного исправления, в миллисекундах с 1 января 1970 года

Обратите внимание, что время UTC на устройстве не является монотонной: она может прыгать вперед или назад непредсказуемо. Поэтому при вычислении временных дельтах всегда используйте getElapsedRealtimeNanos.

Два способа использования являются:

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

Заметим также, что LocationManager.lastKnownLocation() может возвращать нуль.

7

Извините, что открыли его повторно, но я думаю, что ответ Weston неверен, и документация для Android, по крайней мере, вводят в заблуждение.

время базой для GetTime() является UTC, как определено из NMEA предложения, полученные от модуля GPS, не System.currentTimeMillis(). GPS время точно соответствует наносекундам (это должно быть, поскольку электромагнитные волны перемещаются на 30 см в 1 нс). Недостаток заключается в том, что он может быть отключен на 1 с до секунды скачка GPS (см. [1]; это может произойти в течение нескольких минут каждые несколько лет, если предположить, что GPS достаточно умен, чтобы запомнить смещение UTC через электрические циклы)

С другой стороны, System.currentTimeMillis() может быть отключен несколькими секундами/минутами из-за дрейфа или даже больше, если пользователь неправильно устанавливает время/дату.

Итак, единственное реальное решение pre-API 17 - , чтобы регулярно получать обновления местоположения и каждый раз записывать свою собственную временную метку на основе SystemClock.elapsedRealtime().

Я просто попробовал это на Samsung S4, пожалуйста, поправьте меня, если другие телефоны дают разные результаты. Я в этом сомневаюсь.

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

+0

Думаю, ты прав. Только что видел это случайно. Вы должны опубликовать критику в качестве комментария к моему ответу, иначе я этого не увижу. – weston

+0

Я добавил информацию о том, как его использовать – weston

+0

Если я получу еще один взнос, у меня будет достаточно репутации, чтобы публиковать комментарии :) (кажется, это исключение, так как я отвечаю на свой собственный пост) –

Смежные вопросы