位置

要在 Android 中構建位置感知應用,有兩種途徑:

LocationManager

優點

  • 更精細的控制
  • 適用於所有裝置
  • Android 框架的一部分

缺點

  • 如果管理不當,電池耗盡是一個問題
  • 如果裝置無法找到位置(例如建築物內的 GPS 不良),則需要邏輯來切換位置提供商

特徵

  • NMEA 聽眾
  • GPS 狀態監聽器
  • 收聽提供商狀態更改(例如,使用者關閉 GPS)
  • 從中選擇位置源的提供商列表

供應商

全球定位系統

  • 所需許可權:
  • 準確度:10 米 - 100 米
  • 電源要求:HIGH
  • 可用性:全球(能夠清晰地看到天空)
  • 注意
    • 位置更新通常每秒進行一次,但是在 GPS 已經使用一段時間並且 A-GPS 不可用的情況下,接收位置需要幾分鐘。
    • 在天空的清晰視野被阻擋的情況下,由於“ 城市峽谷 ”效應,GPS 點將不會非常好地聚集(位置點跳躍)並且在某些區域中準確性可能會誤導。

網路

  • 所需許可權:
  • 準確度:100m - 1000m +
  • 電源要求:低 - 中等
  • 可用性:在蜂窩塔或 wifi 訊號範圍內
  • 筆記:
    • 位置更新發生頻率低於 GPS
    • 位置更新通常不能很好地聚類(位置點跳躍),並且準確度可以取決於不同因素的數量(wifi 訊號的數量,訊號強度,蜂窩塔的型別等)。

被動

  • 所需許可權:
  • 準確度:10 米 - 1000 米+
  • 電源要求:無
  • 可用性:僅當另一個應用程式從 GPS 或網路接收位置時
  • 筆記:
    • 不要依賴它來為你提供持續更新。這會被動地偵聽到發出位置請求的其他應用程式,並將這些位置傳回。
    • 不返回 FusedLocationProviderApi 生成的點,僅返回用於生成它們的基礎位置點。

FusedLocationProviderApi

優點

  • 提供更少的電池消耗開箱即用
  • 處理好 GPS 很好
  • 更頻繁地獲取更新

缺點

  • 對顆粒的控制較少
  • 可能無法在所有裝置或某些國家/地區使用
  • 需要第三方庫依賴

特徵

  • 妥善管理使用位置提供商以節省最佳電池
  • 通常會生成比網路位置提供商更準確的點
  • 更頻繁地更新庫,允許更多改進
  • 無需指定要使用的提供程式型別

LocationRequest 優先順序

PRIORITY_HIGH_ACCURACY

  • 所需許可權:
  • 準確度:10 米 - 100 米
  • 電源要求:HIGH
  • 可用性:Google Play 服務的可用位置。
  • 筆記:
    • 如果未使用 ACCESS_FINE_LOCATION ,則不會使用 GPS 生成位置更新,但仍會在正確的條件下找到相當準確的點。
    • 如果使用 ACCESS_FINE_LOCATION ,它可能會或可能不會使用 GPS 來生成位置點,具體取決於在給定環境條件下它當前可以跟蹤裝置的準確度。
    • 雖然這可能比其他設定報告更準確的位置更新,但它仍然傾向於“ 城市峽谷 ”效應。

PRIORITY_BALANCED_POWER_ACCURACY

  • 所需許可權:
  • 準確度:100m - 1000m +
  • 電源要求:MEDIUM
  • 可用性:Google Play 服務的可用位置。
  • 筆記:
    • PRIORITY_HIGH_ACCURACY 相同的音符
    • 雖然不太可能,但此設定仍可能使用 GPS 生成位置。

PRIORITY_LOW_POWER

  • 所需許可權:
  • 準確度:100m - 1000m +
  • 電源要求:低
  • 可用性:Google Play 服務的可用位置。
  • 筆記:
    • 可能不使用 GPS,但到目前為止尚未經過測試。
    • 更新通常不是很準確
    • 通常用於檢測位置的重大變化

PRIORITY_NO_POWER

  • 所需許可權:
  • 準確度:10 米 - 1000 米+
  • 電源要求:無
  • 可用性:Google Play 服務的可用位置。
  • 筆記:
    • 功能幾乎與 LocationManager PASSIVE_PROVIDER 相同
    • 收到時報告 Google Play 服務更新,其中 PASSIVE_PROVIDER 報告使用的基礎位置更新

故障排除

OnLocationChanged() 從不呼叫

由於這似乎是獲取 Android Locations 的常見問題,因此我將簡要列出常見修復程式:

  1. 檢查你的清單!

    最常見的問題之一是從未給出正確的許可權。如果你使用 GPS(有或沒有網路),請使用 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>,否則使用 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>。谷歌的 FusedLocationApi 需要 ACCESS_FINE_LOCATION

  2. (適用於 Android 6+) 檢查執行時許可權

    檢查並請求許可權! 如果你從未獲得許可權,你最終會崩潰,或者更糟(如果你正在捕捉所有例外情況),你最終都沒有任何跡象! 如果使用者在應用程式啟動時授予你許可權並不重要,請始終檢查你是否擁有所有呼叫的許可權。使用者可以輕鬆地進入他們的設定並撤消它們。

  3. 仔細檢查你的程式碼!

    你確定你是在傳遞正確的傾聽者嗎?你把 BroadcastReceiverIntentService 新增到你的清單中了嗎?你是在 BroadcastReceiver 級上使用 PendingIntent.getService(),還是在 IntentService 級上使用 getBroadcast()?你確定在請求後立即在程式碼中的其他位置取消註冊你的偵聽器嗎?

  4. 檢查裝置設定!

    顯然,請確保你已啟用位置服務。

    https://i.stack.imgur.com/XDsXs.jpg

    如果你使用網路服務,是否開啟掃描始終可用?你的位置模式是否設定為最佳高精度)或省電僅網路)?

    https://i.stack.imgur.com/IJpXQ.jpg

    如果你使用 GPS,你是否在位置模式下開啟最佳高精度)或僅裝置

    https://i.stack.imgur.com/wgBuU.jpg

  5. 仔細檢查你的程式碼!

    是的,這是兩次。你是否嘗試使用 LocationListener 而不是 PendingIntent,反之亦然,以確保你實際正確實施了 LocationManager?你確定在你預期不會發生的活動或服務生命週期的某些部分中未刪除位置請求嗎?

  6. 檢查周圍的環境!

    你在舊金山市中心一棟樓的一樓測試 GPS 嗎?你是否在不知名的地方測試網路位置?你是否在一個沒有所有無線電訊號的祕密地下掩體中工作,想知道為什麼你的裝置沒有位置?在嘗試解決位置問題時,請務必仔細檢查周圍環境!

可能有許多其他不太明顯的原因,為什麼位置不起作用,但在搜尋那些深奧的修復之前,只需執行這個快速清單。