Obtaining the Current Location
設置Location監聽器
LocationManager
中有很多方法,使得應用可以獲取位置更新。
典型的觀察者模式:注冊一個事件監聽器,說明location manager想從哪里接收位置更新,並且設定接收位置更新的最小時間間隔和距離間隔, onLocationChanged()
回調方法就會在時間和位置間隔相應的頻率下被激發。
LocationListener是一個接口,用於接收LocationManager關於位置變化的通知。
需要通過requestLocationUpdates(String, long, float, LocationListener)進行監聽器的注冊。
LocationListener其中的onLocationChanged(Location location)方法每當位置變化就會被調用。
比如下面的代碼例子,每隔至少10秒,或者距離變化大於10米時接收一次位置信息。
private final LocationListener listener = new LocationListener() { @Override public void onLocationChanged(Location location) { // A new location update is received. Do something useful with it. In this case, // we're sending the update to a handler which then updates the UI with the new // location. Message.obtain(mHandler, UPDATE_LATLNG, location.getLatitude() + ", " + location.getLongitude()).sendToTarget(); ... } ... }; mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, // 10-second interval. 10, // 10 meters. listener);
處理多源位置更新
一般來說,更高精確度的定位方法(如GPS定位)比低精確度的定位方法(如基於網絡的定位)花費更多的定位時間。
如果你想要盡快展示位置數據並且在有更好精度的信息可用的時候更新它,一個通常的做法是注冊一個位置監聽器,同時監聽GPS和網絡位置提供者。
在 onLocationChanged()
回調函數中,你可以接收多個location provider的位置更新,它們可能有不同時間間隔和不同的精度,這時候需要結合邏輯判斷,舍棄過時的還有不准確的更新。
一個實現的例子:
private static final int TWO_MINUTES = 1000 * 60 * 2; /** Determines whether one Location reading is better than the current Location fix * @param location The new Location that you want to evaluate * @param currentBestLocation The current Location fix, to which you want to compare the new one */ protected boolean isBetterLocation(Location location, Location currentBestLocation) { if (currentBestLocation == null) { // A new location is always better than no location return true; } // Check whether the new location fix is newer or older long timeDelta = location.getTime() - currentBestLocation.getTime(); boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; boolean isNewer = timeDelta > 0; // If it's been more than two minutes since the current location, use the new location // because the user has likely moved if (isSignificantlyNewer) { return true; // If the new location is more than two minutes older, it must be worse } else if (isSignificantlyOlder) { return false; } // Check whether the new location fix is more or less accurate int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); boolean isLessAccurate = accuracyDelta > 0; boolean isMoreAccurate = accuracyDelta < 0; boolean isSignificantlyLessAccurate = accuracyDelta > 200; // Check if the old and new location are from the same provider boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider()); // Determine location quality using a combination of timeliness and accuracy if (isMoreAccurate) { return true; } else if (isNewer && !isLessAccurate) { return true; } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { return true; } return false; } /** Checks whether two providers are the same */ private boolean isSameProvider(String provider1, String provider2) { if (provider1 == null) { return provider2 == null; } return provider1.equals(provider2); }
可以看到在這個實現中,判斷位置信息是否是一個更好的結果,首先判斷獲取的位置的時間信息,是不是更新;然后檢查精度、是否是同一個provider提供等信息。
明智地使用getLastKnownLocation()
一些特定應用下,獲取位置的首次建立時間如果過長可能難以使用戶接受。可以考慮調用 getLastKnownLocation()
方法,這個方法返回上一次的定位結果。
當然這個結果很有可能是過期的,因為中間設備可能被關閉然后移動到了一個其他的地方。可以檢查返回位置的時間戳和精度,然后決定這個位置是否有用。
如果丟棄了getLastKnownLocation()
方法返回的位置,等待新的位置更新時,最好考慮顯示一個合適的信息給用戶。
關閉位置更新
當你不再需要位置數據時,可以關閉位置更新,以減少多余的能量消耗和網絡帶寬。
比如,當用戶已經離開了位置更新顯示的界面,就可以通過在onStop()中調用 removeUpdates()
方法來停止位置更新。如下:
protected void onStop() { super.onStop(); mLocationManager.removeUpdates(listener); }
當然也有一些應用需要持續地更新和處理位置數據,這時候最好將位置更新邏輯放在后台service中,用系統的notification bar讓用戶看到位置數據。
參考資料
Training: Obtaining the Current Location
http://developer.android.com/training/basics/location/currentlocation.html
LocationManager類:
http://developer.android.com/reference/android/location/LocationManager.html
LocationListener接口:
http://developer.android.com/reference/android/location/LocationListener.html
Location類:
http://developer.android.com/reference/android/location/Location.html