Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android的定位策略

Android的定位策略

編輯:關於Android編程

前言


Note: 本文中的策略適用於Android平台上android.location包中的定位API。不同於Google Location Services API,Google Location Services API是Google Play Services中的一部分,能夠提供更強大更高級別的框架來自動處理定位數據源、用戶移動和定位精度問題,還能夠根據你提供的能源消耗參數調整定位的刷新方式。通過使用Google Location Services API,在大多數情況下,你都能夠獲得更好的電池性能,同時,還能得到更好的定位精度。更多關於這部分定位服務API的內容,請參考Google Location Services for Android。

獲取用戶的地理位置信息能夠讓你的應用程序顯得更加智能,借此能夠分發更合適的信息給用戶。為android開發地理位置相關的應用程序,你可以利用GPS或者android的網絡定位數據源來獲取用戶的地理位置。盡管GPS的定位更加精准,但它只適用於戶外,並且還會更快的消耗電量,它也不能按用戶所期待的及時返回地理位置信息。android的網絡定位數據源是通過使用手機信號塔和WiFi信號來獲取用戶的地理位置信息,不管是在室內還是室外都能夠以統一的方式提供地理位置信息,網絡定位的響應也會更快,消耗的電量也更好。在你的應用程序中獲取用戶的地理位置,你可以同時使用GPS或者網絡定位,也可以只使用其中一種。

 

獲取用戶地理位置信息帶來的挑戰


從移動設備上獲取用戶的地理位置信息是很復雜的。有多種原因能夠導致地理位置信息的獲取(不管使用的是哪一種數據源)發生錯誤或者精度不准。一些用戶地理位置信息獲取可能導致的數據源錯誤如下:

多種定位數據源
GPS、手機信號塔ID和WiFi,每一種數據源都包含了一種用戶地理位置定位的規則。選擇和信任哪一種數據源的數據是一個權衡定位精度、定位速度,以及電量消耗的問題。 用戶位置移動
由於用戶的位置在不停變化,你必須每隔一段時間重新更新用戶的地理位置信息來應對用戶位置不停變化問題。 不同的精度
不同定位數據源的地理位置信息精度是不同的。10秒鐘前從一個定位數據源獲取的地理位置信息精度可能比另外一個甚至是同一個定位數據源剛剛獲取的地理位置信息還要准確。

上面的這些問題讓獲取一個可靠的用戶地理位置信息變得很困難。本文檔提供一些解決方案來幫助你面對這些挑戰,獲取相對可靠的地理位置信息。同時,也提供一些建議,幫助你在應用程序中為用戶提供一個精確的響應及時的定位體驗。

 

請求定位更新


在解決上面提到的一些定位錯誤問題之前,這裡要先介紹如何在android設備上獲取定位數據。

在android上獲取用戶的地理位置信息是通過回調來實現的。你通過調用LocationManager類(Location Manager)的requestLocationUpdates() 方法,傳遞一個LocationListener監聽器來向系統表明你需要接收地理位置數據刷新信息。你的LocationListener 必須實現一些回調方法。這些方法在用戶的地理位置信息有變化,或者地理位置服務狀態有變化時,Location Manager就會回調它們。

例如,下面的代碼片段定義了一個LocationListener並且請求定位更新:

// 獲取系統的LocationManager服務
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

// 定義一個LocationListener來響應定位更新
LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
      // 當地理位置信息有變化的時候回調
      makeUseOfNewLocation(location);
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    public void onProviderDisabled(String provider) {}
  };

// 向Location Manager注冊LocationListener監聽定位更新
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

requestLocationUpdates() 方法中第一個參數指明使用的定位數據源類型(這個例子中,使用的依據手機信號塔和WiFi信號來定位的網絡數據源)。你可以通過第二和第三個參數來控制你的監聽器接收定位數據信息的頻率——第二個參數指定兩次數據更新通知之間的最小時間間隔,第三個參數指定觸發下一次定位數據更新通知的最小距離——兩個參數都設置為0則表示要盡可能快的更新。最後一個參數就是你的LocationListener監聽器啦,它的回調方法會在有定位更新的時候得到回調。

請求根據GPS數據源來更新定位信息,只需要將第一個參數NETWORK_PROVIDER替換為GPS_PROVIDER就可以了。你也可以同時請求GPS和網絡定位數據源更新定位信息,但你需要調用requestLocationUpdates()方法兩次,一次使用NETWORK_PROVIDER,一次使用GPS_PROVIDER。

 

向用戶申請權限


為了能夠從NETWORK_PROVIDER或者GPS_PROVIDER定位數據源接收到定位更新數據,你必須在android的manifest文件中分別聲明ACCESS_COARSE_LOCATION和ACCESS_FINE_LOCATION權限。例如:


    
    ...

如果沒有這些權限,你的應用程序在運行過程中請求定位更新將會失敗。

注意:如果你同時使用NETWORK_PROVIDER和GPS_PROVIDER定位數據源,那麼你只需要申請ACCESS_FINE_LOCATION權限,因為它已經包含了這兩個數據源需要的權限(ACCESS_COARSE_LOCATION只包含了NETWORK_PROVIDER數據源所需要的權限)。

 

定義最佳的性能模型


基於定位的應用程序現在很常見,但由於稍差的定位精度、用戶不停移動、獲取定位信息的方法多種多樣、以及需要減少電量消耗,導致獲取用戶定位信息變得很復雜。為了解決獲取精確的定位信息與節省電量消耗之間的矛盾,你必須確定一個統一的模型來指定你的應用程序如何獲取用戶的定位信息。這個模型應該包含什麼時候你應該啟動或者停止定位更新監聽,以及什麼時候可以使用緩存的定位數據。

獲取用戶定位信息的步驟


下面是獲取用戶定位信息的典型流程:
1. 啟動應用程序
2. 稍等一段時間後,啟動對目標定位數據源更新的監聽器
3. 過濾新的,但是精度不准確的定位信息,以保持當前的地理位置測量數據是最佳的。
4. 停止監聽定位信息的更新
5. 獲取最後最佳的定位測量數據

下面圖1通過一條時間線形象地展示了一個應用程序在監聽地理位置信息更新的過程中每一個階段發生的事件。

getting-location.png
圖1:一條代表應用程序監聽定位刷新的時間線

上面的模型中,在地理位置信息更新和接收的階段,你會接收到多次地理位置信息,你需要根據你添加的地理位置服務進行判斷過濾。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMiBpZD0="確定什麼時候啟動地理位置更新監聽">確定什麼時候啟動地理位置更新監聽


你可能想要在應用程序一啟動的時候就開啟地理位置信息更新監聽,也有可能當用戶觸發了相關功能模塊的時候才進行啟動監聽。但要知道,長時間進行定位監聽來修復當前地理位置信息會消耗掉大量電量,而如果監聽時間過短又可能導致定位不夠精確。
正如上面章節所描述的,你可以通過調用requestLocationUpdates() 方法來啟動定位更新監聽:

String locationProvider = LocationManager.NETWORK_PROVIDER;
// Or, use GPS location data:
// String locationProvider = LocationManager.GPS_PROVIDER;

locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);

獲取最後快速調整修復的定位信息


你的定位監聽器第一次獲取到修復的定位信息所花費的時間常常要讓用戶等很久。直到你的定位監聽器獲取到更多精確的地理位置信息時,你才能調用getLastKnownLocation(String) 方法來獲取緩存的地理位置信息:

String locationProvider = LocationManager.NETWORK_PROVIDER;
// Or use LocationManager.GPS_PROVIDER

Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);

確定何時停止定位更新監聽


決定什麼時候不再需要新的地位位置修正信息取決於你的應用程序邏輯,它可能很簡單,也可能很復雜。當獲取的地理位置信息到使用這個地址位置信息的時間間隔越短,這個定位信息的測量精確度就越高。要始終注意監聽定位更新的時間越長,消耗的電量就更多。因此,一旦給你獲得你所需要的定位信息之後,你就應該馬上調用removeUpdates(PendingIntent) 方法停止監聽定位更新。

// Remove the listener you previously added
locationManager.removeUpdates(locationListener);

維護一個當前最精確的定位信息


你可能認為最近獲取的定位修正信息就是最准確的,然而,由於地理位置修正值變化的精度問題,最近獲取的修正定位信息不一定就是最精確的。你應該在應用程序中添加基於幾個標准來選擇定位信息修正值的邏輯。這些標准同樣也會由於應用程序的用戶和實際測量值的不同而變化。

下面有幾個你可以用來檢驗定位修正值精確度的步驟:

檢查定位修正值是否明顯比上次的測量值要新很多。 檢查定位信息的精度要求是否比上次的測量值要好還是差。 檢查新的定位測量值是哪個定位數據源提供的,你是否信任這個定位數據源。

綜合上面所描述的邏輯,類似的處理代碼如下:

private static final int TWO_MINUTES = 1000 * 60 * 2;

/** 判斷是一個新的定位測量值是否比當前的定位修正值更好
  * @param location  需要評估的新定位測量值
  * @param currentBestLocation  當前的定位修正值,也就是你想要用來跟新定位測量值比較的定位數據
  */
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
    if (currentBestLocation == null) {
        // 如果當前沒有定位修正值,那麼新的定位測量值肯定是更好的
        return true;
    }

    // 檢查新的定位測量值是更新的數據還是更舊的數據
    long timeDelta = location.getTime() - currentBestLocation.getTime();
    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
    boolean isNewer = timeDelta > 0;

    // 如果新的定位測量值晚於當前的定位修正值兩分鐘,那麼使用新的定位測量值,因為用戶可能已經移動了
    if (isSignificantlyNewer) {
        return true;
    // 如果新的定位測量值早於當前定位修正值兩分鐘,那麼新的定位測量值應該是過時的
    } else if (isSignificantlyOlder) {
        return false;
    }

    // 檢查新的定位測量值精度是否更加精確
    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    boolean isLessAccurate = accuracyDelta > 0;
    boolean isMoreAccurate = accuracyDelta < 0;
    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

    // 檢查兩個定位測量值是否來源於同一個定位數據源
    boolean isFromSameProvider = isSameProvider(location.getProvider(),
            currentBestLocation.getProvider());

    // 組合定位的及時性和准確度來評估定位的質量
    if (isMoreAccurate) {
        return true;
    } else if (isNewer && !isLessAccurate) {
        return true;
    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
        return true;
    }
    return false;
}

/** 檢查兩個定位數據源是否是同一個數據源 */
private boolean isSameProvider(String provider1, String provider2) {
    if (provider1 == null) {
      return provider2 == null;
    }
    return provider1.equals(provider2);
}

調整模式以節省電量和數據交換


當你測試你的應用程序的時候,你可能會發現你為了提供更好的定位和更好的性能而設計的定位模式可能需要一些調整。為了更好的在兩者之間取得平衡,下面提到的一些東西你可能需要進行調整。

減少監聽時間

更少的監聽定位刷新時間意味著與GPS和網絡定位服務更少的交互操作,因此,也就延長了電池的使用時間。而且,這種策略也允許從少數定位信息中挑選最佳的測量值。

為定位數據源設定更低的刷新頻率

在監聽定位刷新期間,降低新更新信息出現的頻率同樣可以提升電池的效率,但需要考慮精度損耗的成本。刷新頻率值需要根據你的應用程序用途來權衡。你可以通過增加requestLocationUpdates() 的參數來指定刷新間隔時間和最小的距離變化條件。

限制多個定位數據源的使用

取決於你的應用程序使用場景以及要求的精確度等級,你可能只需要選擇網絡定位數據源或者GPS定位數據源就夠了,不用兩種數據源同時使用。在可預見能夠接受的精度范圍內置選擇與一種定位數據源交互能夠降低電量的消耗。

 

常見的應用程序案例


有很多種原因你需要獲取用戶的地理位置信息。下面是一組你可以使用用戶的地理位置信息來豐富你的應用程序的場景。每一種場景都描述了為獲取好的定位信息並且在節省電量消耗的情況下,應該什麼時候啟動或者停止監聽定位刷新的做法。

用地理位置信息標記用戶創建的內容


你可能想要創建一個應用程序,使用地理位置信息標志用戶創建的內容。例如用戶可能想要分享他所在地的風俗,發表對一家餐廳的評論,或者記錄一些能通過他們當前地理位置信息來增強的內容。圖2形象的描述了這個過程中與定位服務的交互模型:

content-tagging.png
圖2:一條包含用戶定位獲取,以及消耗掉當前獲取的地理位置後停止定位監聽的時間線

這條時間線基於前面如何在代碼中獲取用戶定位信息的模型(圖一)。為了更好的定位精確度,你可能需要在用戶開始創建內容甚至是應用程序啟動的時候就開始監聽定位信息的刷新,然後在內容發表或者保存之後挺屍定位刷新的監聽。你可能需要考慮創建一個內容的典型任務需要花費多長的時間,然後判斷這個時間間隔是否足夠高效采集一個定位測量值。

幫助用戶決定應該走去哪裡


你可能想要創建一個應用程序來嘗試給用戶提供一系列關於去哪裡的選項。例如,你要查詢提供一個附近餐廳、商店和公寓的列表,並且這個建議列表會根據用戶的地理位置變化而變化。

為了適應這個流程,你可以選擇:

當獲取的更新更准確的定位測量值時,刷新建議列表 當建議列表排序相對穩定的時候停止監聽定位刷新

圖3形象的表述了這個模型:

where-to-go.png

圖3:一條每一次用戶定位刷新都要動態更新一系列數據的時間線

 

提供假的定位數據


當你在開發應用程序,你當然需要測試你的獲取用戶地理位置信息模型是否足夠滿足要求。使用一台android設備很容易進行這種測試。然而,即使你沒有一台真機設備,你同樣可以在android模擬器中通過假定位數據來測試你的定位模塊功能。下面有三種向你的應用程序發送假定位數據的方法:使用android studio,DDMS,或者在模擬器控制台上使用“geo”命令。

注意:提供假定位信息是以GPS定位信息的方式注入的,因此你必須從GPS定位數據源獲取定位刷新數據才能使假定位信息正常使用。

使用Android Studio


選擇Tool > Andorid > AVD Manager.在android虛擬機管理器窗口中選擇你的AVD,並且通過點擊操作列表中的綠色播放按鈕啟動這個模擬器。

之後,選擇Tool > Android > Android Device Monitor.在Android Device Monitor窗口中選擇Emulator Control(模擬器控制)標簽頁,然後在Location Controls裡面輸入GPS坐標作為用戶的經緯度坐標,或者使用GPX文件指定路線規劃,或者使用KML文件標識多個地點。

使用DDMS


使用DDMS工具,你可以通過幾種不同的方式模擬位置:

手動發送個人經緯度坐標到設備上 使用一個GPX文件來描述一條回放的路線 使用一個KML文件來描述用於測量回放的個體標識地點

更多關於使用DDMS模擬地理位置的內容,請參考使用DDMS.

在模擬器控制台上使用“geo”命令


從終端命令行上發送假地理位置數據:

在android模擬器中啟動你的應用程序,同時打開你的SDK中/tools目錄下的terminal/console。 連接模擬器的控制台:

telnet localhost
發送地理位置數據:
geo fix命令發送一個修正的地理位置。
這個命令接受一對十進制的經緯度參數,還有一個可選的以米為單位的海拔高度參數。例如

geo fix -121.45356 46.51119 4392
geo nmea命令發送一個NMEA 0183句子
這個命令接受一個單一的’GPGGA′(穩定數據)類型或者′GPRMC’(過渡數據)類型的句子。例如:

geo nmea $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62

更多關於如何連接到模擬器控制台的內容,請參考使用模擬機控制台。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved