Android LBS系列05 位置策略(一)
Location Strategies
?
定位的實現(xiàn)
在Android系統(tǒng)上實現(xiàn)定位主要是通過GPS或者是基于網(wǎng)絡(luò)的定位方法。
GPS是精度最高的,但是它只在戶外有用,并且很耗電,并且首次定位花費時間較長。
基于網(wǎng)絡(luò)的定位利用通信網(wǎng)絡(luò)蜂窩基站和Wi-Fi信號,這種定位方式在室內(nèi)室外都能用,響應(yīng)時間較短,耗電較少,但是精度較差。
為了在應(yīng)用中獲得用戶的信息,你的location provider可以是GPS或者基于網(wǎng)絡(luò),也可以兩者都用。
?
決定用戶位置面臨的挑戰(zhàn)
從手機上獲取用戶的位置是個比較復(fù)雜的問題,無論采取的數(shù)據(jù)源是什么,總是有一些因素會導(dǎo)致位置信息包含誤差,從而不準確。
誤差來源如下:
多種位置信息源
GPS, Cell-ID, 和Wi-Fi都能為用戶位置提供一定的線索。決定信任和采用哪些數(shù)據(jù)是一個需要權(quán)衡的過程,權(quán)衡時要考慮精度、速度、電池效率等。
用戶移動
因為用戶的位置會改變,所以應(yīng)該考慮每隔一段時間重新估計用戶位置。
變化的精度
每一個位置信息源的精度不是恒定的。也就是說位置估計即便是同一個信息源提供的,它的精確度也是不斷在變化的。
?
請求位置更新
在Android中獲取位置主要是通過回調(diào)函數(shù)。
首先通過?LocationManager的?requestLocationUpdates()方法注冊監(jiān)聽器,向其中傳入一個實現(xiàn)了?LocationListener接口的對象。
你的?LocationListener對象中必須實現(xiàn)一些回調(diào)函數(shù),當用戶位置改變或者當服務(wù)狀態(tài)改變時,Location Manager就會調(diào)用這些回調(diào)函數(shù)。
比如,下面的代碼就展示了如何定義一個?LocationListener然后請求位置更新:
?
// Acquire a reference to the system Location Manager LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);// Define a listener that responds to location updates LocationListener locationListener = new LocationListener() {public void onLocationChanged(Location location) {// Called when a new location is found by the network location provider. makeUseOfNewLocation(location);}public void onStatusChanged(String provider, int status, Bundle extras) {}public void onProviderEnabled(String provider) {}public void onProviderDisabled(String provider) {}};// Register the listener with the Location Manager to receive location updates locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);?
? requestLocationUpdates()?中的第一個參數(shù)指明了location provider的類型,第二個參數(shù)是通知的最小時間間隔,第三個參數(shù)是通知的最小的改變距離。
如果第二個和第三個參數(shù)都設(shè)置成0就表示要盡可能頻繁地請求位置通知。
最后一個參數(shù)是用戶自己定義的實現(xiàn)了LocationListener接口的對象,它接收位置更新的回調(diào)。
如果想要同時利用GPS和網(wǎng)絡(luò)定位,可以調(diào)用?requestLocationUpdates()兩次,第一個參數(shù)分別是?GPS_PROVIDER和?NETWORK_PROVIDER?。
?
權(quán)限設(shè)置
如果沒有權(quán)限設(shè)置,程序在請求位置更新時將會失敗。
<manifest ... ><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />... </manifest> ?如果用NETWROK_PROVIDER, 那么需要聲明 ACCESS_COARSE_LOCATION和INTERNET;
如果用GPS_PROVIDER, 那么需要聲明 ACCESS_FINE_LOCATION;
ACCESS_FINE_LOCATION是包含了ACCESS_COARSE_LOCATION的,所以兩者都用時可以只聲明ACCESS_FINE_LOCATION。
?
建立一個最佳性能的模型
為了克服獲取用戶位置時的種種困難,定義一個模型,具體化你的應(yīng)用如何取得用戶位置。
這個模型包含了你何時開始和何時終止位置更新的監(jiān)聽,也包含了什么時候使用緩存的位置數(shù)據(jù)。
獲取用戶位置的流程
獲取用戶位置的典型流程如下:
? ? ? ? ? ? ? ???????????
?
1.首先開始應(yīng)用。
2.在某一個點,開始監(jiān)聽位置更新。
3.維持一個當前位置的“最佳估計”。
4.停止對位置更新的監(jiān)聽。
5.利用最后一次的最佳位置估計。
這個模型是一個窗口,窗口從開始監(jiān)聽開始,從停止監(jiān)聽結(jié)束。
?
決定何時開始監(jiān)聽更新
可以從應(yīng)用一開始就啟動監(jiān)聽,也可以在用戶觸發(fā)某個特性后開始。
要清楚如果長時間監(jiān)聽位置會消耗很多電量,但是短時間的監(jiān)聽可能達不到足夠的精度。
調(diào)用requestLocationUpdates()開始監(jiān)聽:
LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER; // Or, use GPS location data: // LocationProvider locationProvider = LocationManager.GPS_PROVIDER; locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);?
用上次定位的結(jié)果獲取快速定位
初次獲得位置信息可能會花費較長時間。在獲得一個比較精確的定位之前,可以利用一個緩存的位置:調(diào)用getLastKnownLocation(String)方法實現(xiàn)。
LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER; // Or use LocationManager.GPS_PROVIDER Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider); ?決定何時停止監(jiān)聽
位置獲取和位置使用之間的時間間隔越小,對估計精度的改善越有利。
永遠記住長時間的監(jiān)聽位置更新將會非常費電,所以一旦你得到你需要的信息,就應(yīng)該停止監(jiān)聽位置更新,調(diào)用removeUpdates(PendingIntent)方法實現(xiàn):
// Remove the listener you previously added locationManager.removeUpdates(locationListener); ?維護一個當前最佳估計
因為定位精度是實時變化的,所以很可能最新的位置并不是最準確的。
你應(yīng)該制定一些標準并包含一套邏輯判斷,來選擇出最佳估計。
這套標準也是隨著使用情景而變化的。
下面是你驗證一個location fix的精確度時可以采取的步驟:
1.檢查是否當期位置數(shù)據(jù)比之前的估計數(shù)據(jù)要新很多;
2.檢查當前數(shù)據(jù)和之前數(shù)據(jù)的精度,誰更好;
3.檢查當前數(shù)據(jù)是從哪個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 locationreturn true;}// Check whether the new location fix is newer or olderlong 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 movedif (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 accurateint 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 providerboolean isFromSameProvider = isSameProvider(location.getProvider(),currentBestLocation.getProvider());// Determine location quality using a combination of timeliness and accuracyif (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); } ?調(diào)整模型以節(jié)約電量和進行數(shù)據(jù)交換
當你測試模型的時候,可能發(fā)現(xiàn)你的模型需要做一些調(diào)整,以平衡它的準確度和性能。下面是一些你可以改變的地方:
減小流程的窗口尺寸
窗口尺寸減小,意味著與GPS和網(wǎng)絡(luò)的交互減少,這樣就可以節(jié)約電量。但是這樣也就減少了獲得最佳位置估計可以利用的位置數(shù)。
降低location provider返回更新的頻率
在窗口中降低更新頻率也可以改善電池效率,但是會導(dǎo)致精度的丟失。requestLocationUpdates()?通過其中兩個參數(shù)就可以設(shè)定更新的時間和空間間隔,從而設(shè)定頻率。
限制provider
根據(jù)應(yīng)用的特定環(huán)境或者目標精度等級,可以選擇只利用基于網(wǎng)絡(luò)的定位或者只利用GPS定位,而不是同時利用兩者。只與其中的一者交互將減少電量使用,但是會有潛在的精度丟失。
?
參考資料:
API Guides:Location Strategies
http://developer.android.com/guide/topics/location/strategies.html
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/mengdd/archive/2013/01/12/2857859.html
總結(jié)
以上是生活随笔為你收集整理的Android LBS系列05 位置策略(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】ORACLE中的子查询 ---O
- 下一篇: struts:file 提交给actio