本文指導內容所描述的策略適用於android.location中的平台定位api。
google定位服務api,作為google應用服務的一部分,提供了一個更有力的,水平更高的的架構,能夠自動處理定位服務供應者,用戶移動,定位精確度。
它也能夠處理基於你所提供的電力損耗參數的定位更新調度。
在大多數例子中,使用定位服務api,我們可以得到更好的電力性能,以及更有可能得到的精確度。
我們要了解用戶的需求,這樣我們的app才能更聰明,才能為用戶提供更好的信息。
當開發安卓定位有關的app時,我們可以使用gps和安卓網絡定位提供者來獲取用戶位置信息。
雖然gps更精確,但它只在戶外有效,而且耗電快,並且不能及時地回饋用戶的位置信息。
安卓網絡定位提供者通過蜂窩塔和wifi信號來定位,這種位置信息提供方式適用於戶內和戶外,反饋快,並且耗電較少。
在app中獲取定位信息,我們可以同時使用gps和網絡定位,或者兩者的其中一個。
確定用戶位置中的挑戰
從移動設備中獲取用戶位置信息是一件複雜的事情。
對於為什麼位置讀取(不管來源)包含錯誤信息,以及不准確,有這樣幾個原因。
用戶位置信息中的錯誤來源有:
1. 定位信息的多重來源
gps,蜂窩-id,wifi都能為用戶定位提供線索,決定使用和信任哪一個,是對精確度,速度,電池效能的權衡。
2. 用戶的移動
當用戶的位置改變時,我們必須每隔一段時間就為這種移動進行用戶定位重新估計。
3. 變化的准確度
從每一個定位源得來的定位估計准確度是不恆定的。
一個定位源得來的10秒鐘之前的位置信息可能比另一個定位源得來的最新的位置信息更准確。
這些問題能夠使讀取到穩定的位置信息成為一件難事。
此文檔為我們迎接挑戰,獲得穩定的位置信息讀取提供信息。
它同樣為我們開發應用使用戶獲得更准確,更好響應的地理位置體驗提供了一些想法。
請求位置更新
在描述上述的一些定位錯誤前,我們先介紹一下如何在安卓設備上獲取用戶位置。
我們通過反饋的方法在安卓上獲取用戶位置。
這意味著我們通過調用requestlocationupdates(),從location manager(“location manager”)來獲取位置更新,並把它傳遞給locationlistener。
locationlistener必須配置幾個反饋方法,當用戶位置改變,或者服務的狀態改變時,來供location manager調用。
下面的代碼展示了如何定義locationlistener,並且請求位置更新:
codes
requestlocationupdates()中的第一個參數是我們使用的定位服務者的類型(在上段代碼中是指網絡定位供應者的基於蜂窩塔荷wifi的定位)。
我們可以使用第二個和第三個參數來控制監聽器所接收到的位置更新的頻率,第二個參數是位置更新通知之間的最小時間間隔,第三個參數是位置更新通知之間的位置距離的最小相差值,可以均設置為0,這意味著儘可能得高頻率的接收位置通知。
最後一個參數是我們的locationlistener,它為位置更新來接收反饋。
如果想從gps服務接收位置更新,可以將network_provider替換為gps_provider。
我們也可以同時向gps和網絡定位提供者請求定位更新,可以調用requestlocationupdates()兩次,一次用network_provder,一次用gps_provider。
請求用戶權限
為了從network_provider或gps_provider接收位置更新,我們必須在安卓清單文件中分別聲明access_coarse_location或access_fine_location權限來獲得用戶權限。
例如:
codes
沒有這些權限,app在運行過程中請求位置更新時就會失敗。
如果同時使用network_provider和gps_provider,我們只需要access_fine_location權限,因為它包含了所有服務供應者的所需權限。(access_coarse_location權限只包含了network_provider所需的權限。)
為得到最好的性能定義一個模型
基於定位的app現在很普遍,但是由於缺少精度,用戶移動,獲取位置的多樣化,節約電池電力的最優化,獲取用戶位置成為了一件複雜的事情。
為了達到保存電池電力同時,獲取良好的用戶位置信息的目的,我們必須定義一個穩定的模型來規定我們的app如何獲取用戶位置。
這個模型包括了何時開始和停止監聽更新,以及何時使用緩存的位置數據。
獲取用戶位置的流程
下面是獲取用戶位置的一個常用流程:
1. 開啟應用。
2. 過一會,開始監聽從所選位置供應者發出的更新。
3. 維持位置信息的當前最佳估計,濾除新的但不精確的更新。
4. 停止監聽位置更新。
5. 使用最後一個最佳的位置估計。
圖1描述了時間線上的該模型,它圖像化了整個週期,包含了監聽位置更新和在此期間發生的事。
圖1
這個模型包含了一個時間窗口,在這個時間窗口中,它接收了位置更新,並且在我們將定位服務嵌入app時,將我們在這個時間窗口中所做的決定打包為了一幀。
決定何時開始監聽更新
我們可能會想要在應用開啟的時候就開始監聽位置更新,也有可能要在用戶開啟某一個特性之後開始監聽。
注意使用長窗口監聽位置更新會耗費大量的電力,但是使用短窗口就可能得不到足夠的精確度。
如上所說,我們可以調用requestlocationupdates()來開始監聽更新:
codes
使用上一次所知的位置得到快速定位
位置監聽器取得第一個位置往往需要用戶等待很長時間。在位置監聽器得到一個較為準確的位置信息之前,我們可以調用getlastknownlocation(string)來獲得緩存位置信息。
codes
決定何時停止監聽更新
決定何時不再需要位置更新的邏輯,基於我們的app,可以很簡單,也可以很複雜。
何時獲得位置信息和何時使用位置信息之間的短間隔,可以提升估計的準確性。
謹記長時間的監聽會耗費大量的電池電力,一旦我們取得了所需的信息,就應當調用removeupdates(pendingintent)來停止監聽更新。
codes
保持當前的最佳估計
我們可能會希望最近得到的位置信息是最精確的。
然而因為位置信息的精確度是會變化的,所以最近的位置信息並不往往是最佳的。
我們應當將基於幾個標準的選擇位置信息的邏輯包含進代碼。
這些標準基於應用的使用實例和現場測試情況往往也是變化的。
這裏有一些步驟我們可以用來驗證位置信息的精確度:
1. 檢查獲得的位置是否比上一個位置要新(有一定範圍)。
2. 檢查位置所帶的精確度比上一個位置是好還是壞。
3. 檢查新的位置來源於哪一個供應者,並決定你更相信哪一個供應者。
這個邏輯的範例如下代碼所示:
codes
調整模型來節約電池,和進行數據交換
當測試app時,我們可能會發現模型需要一些改進來提供更佳的位置和更好的性能。我們可以嘗試更改下列條目來取得這兩者之間的更好平衡。
縮小窗戶的尺寸
當我們監聽位置更新時使用尺寸較小的窗戶,這意味著它和gps以及網絡定位服務進行了較少的交流,因此,節約了電池。
但是這將會導致我們從較少的位置中來挑選最佳估計。
將定位提供者設置為較小頻率反饋更新
縮小在一個窗戶中出現的更新的頻率,同樣也能夠節約電池,但這是以降低精確度作為代價的。
這種權衡的價值取決於app的使用場景。
我們可以通過增大requestlocationupdates()的參數來指定間隔時間和最小距離改變,使更新的出現頻率減小。
限定一組供應者
根據app使用的環境,還有所想要的精確度,我們可以選擇僅由網絡定位供應或僅由gps供應,或者兩者同時供應。
只和這兩者中的一個交流位置信息能夠花費一些精確度來換得電池節能。
通用的應用實例
有很多原因會使我們想要在app中獲取用戶位置。下面描述了我們使用用戶位置來充實應用的一些場景。
每一個場景都描述了何時開始或者停止監聽位置的實例,使我們能夠讀到好的位置信息和節約電池時間。
將用戶創造的內容附上位置標簽
我們可能會開發一個應用,該應用中用戶所創造的內容會被打上位置標簽。
用戶會分享一些本地的經驗,例如貼上對一家餐館的評價,或者錄製一些內容,這些內容如果附上當前位置信息,那麼影響就可能會擴大。
此種交互發生的模型,以及對位置服務的反應,在圖2中進行來展示。
圖2
在圖2 中,模型和圖1中的如何用代碼獲取用戶位置的模型一樣,以線型發展。
為了取得最好的位置精確度,我們可能要選擇在用戶開始創建內容,或者甚至於應用剛開始運行時,應用就要開始監聽位置更新。
以及在內容準備要被貼上或者錄製完時,停止監聽更新。
我們可能需要考慮創建內容的一個典型例子中會花費多少時間,並且判斷這個時間間隔是否允許位置的估計得到一個有效的搜集。
幫助用戶判斷去哪裡
我們也可能會開發一類應用,試圖為用戶提供一系列選擇,讓用戶決定去哪裡。
例如,我們想要提供一張附近餐館,商店,娛樂場所的列表,列表的推薦排序取決於用戶的位置。
要得到上述功能,我們可以選擇:
1. 當新的位置估計取得後,重新排列建議選項
2. 當建議排序穩定後,停止監聽位置更新
此種模型如圖3所示。
圖3
提供模擬的位置數據
當我們在開發自己的應用時,我們一定需要測試app的模型處理獲得用戶位置的效果如何。
如果使用真實安卓設備,這是一件很簡單的事。
但是,如果我們沒有這樣的設備,我們也可以通過在安卓模擬器中使用模擬位置數據來測試一些基於位置的特性。
有三種不同的方法可以發送應用模擬位置數據:使用eclipse,ddms,或者在模擬器控制台中使用“geo”命令。
note:提供的模擬位置數據一般會以gps位置數據被插入,所以我們必須要請求gps_provider的位置更新來確保模擬位置數據可以正常工作。
使用eclipse
選擇window-show view-other-emulator control
在模擬器控制面板,位置控制下輸入gps坐標作為單獨的緯度/經度坐標,輸入的方式可以是gpx文件路線回放,或者kml文件多個地點標註。
(確保在設備面板中已經勾選了一個設備,路徑是window-show view-other-device。)
使用ddms
使用ddms工具,我們可以用以下幾種方式來模擬位置數據:
1. 手動發送單獨的經度/緯度坐標到設備。
2. 使用gpx文件向設備描述路線回放。
3. 使用kml文件向設備描述單獨的點標記進行有序回放。
更多信息參考原文鏈接。
在模擬器控制台使用“geo”命令
從命令行發送模擬位置數據:
1. 在安卓模擬器中運行應用,並在sdk的/tools目錄下,打開終端/控制台。
2. 連接到模擬器控制台:
codes
3. 發送位置數據:
1)geo fix 發送固定的地理位置
此命令可以接受十進制度的經度和緯度,以及可選的以米為單位的高度。例如:
codes
2)geo nmea 發送nmea 0183語句
此命令可以接受“$gpgga”(固定數據)類型或者“$gprmc”(中轉數據)類型的單獨nmea語句。例如:
codes
要了解有關連接模擬器控制台的更多信息,參考原文鏈接。