針對位置服務進行最佳化以降低耗電量

Android 8.0 版 (API 級別 26) 中推出的背景位置資訊限制,已再次強調使用定位服務對電池耗電的影響。本頁主要說明部分定位服務最佳做法,以及「目前」可以採取哪些行動,讓應用程式更加省電。無論應用程式在哪一個平台版本上執行,都能採用這些最佳做法,藉此從中獲益。

Android 8.0 版的背景位置資訊限制包含下列變更:

  • 背景位置資訊收集會受到限制並計算位置,且每小時只傳送幾次。
  • Wi-Fi 掃描更加保守,當裝置保持連線至相同的靜態存取點時,系統就不會計算位置資訊更新。
  • 地理圍欄回應速度從數 10 秒變更為約 2 分鐘。這項變更將大幅提升電池效能,部分裝置的效能可提升高達 10 倍。

本頁內容假設您使用的是 Google 定位服務 API,相較於架構定位 API,前者的準確率更高,電池負擔也更小。特別是,本頁內容假設您熟悉 Fused Location Provider API,這個 API 結合 GPS、Wi-Fi 和行動網路以及加速計、陀螺儀、磁力儀和其他感應器的信號。另外,您應該也熟悉 地理圍欄 API。這個 API 是以整合式位置預測提供工具 API 為基礎而建構,並經過最佳化處理,可提升電池效能。

瞭解電池耗電

位置資訊收集和電池耗電在以下各方面直接相關:

  • 準確率:位置資料的精確度。一般而言,準確率越高,電池耗電就越大。
  • 頻率:位置資訊的計算頻率。系統計算位置資訊頻率越高,電池用量越大。
  • 延遲時間:位置資料的傳送速度。延遲時間越短,通常需要的電池電量越多。

準確率

您可以使用 setPriority() 方法指定下列其中一個值,並將下列其中一個值做為引數傳遞:

  • PRIORITY_HIGH_ACCURACY 提供最準確的位置資訊,根據需要盡量使用多項輸入內容進行計算 (啟用 GPS、Wi-Fi 和行動網路,並使用各式各樣的感應器),可能導致耗用大量電力。
  • PRIORITY_BALANCED_POWER_ACCURACY 提供準確的位置資訊,同時提高電源效率。極少使用 GPS 通常使用 Wi-Fi 和手機資訊來計算裝置位置。
  • PRIORITY_LOW_POWER 主要仰賴行動通信基地台,並避免使用 GPS 和 Wi-Fi 輸入內容,以最低耗電量提供粗略的 (城市層級) 準確率。
  • PRIORITY_NO_POWER 會從其他應用程式被動接收已計算出的位置資訊。

使用平衡電源或低電源選項,即可滿足大多數應用程式的位置資訊需求。高精確度選項應保留給在前景執行且需要「即時」位置資訊更新 (例如地圖應用程式) 的應用程式。

頻率

您可以使用下列兩種方式指定位置資訊更新頻率:

  • 使用 setinterval() 方法指定「應用程式計算位置」的間隔時間。
  • 使用 setFastestInterval() 指定「其他應用程式已計算出的位置資訊傳送至您的應用程式」的間隔時間。

使用 setInterval() 時,請盡可能傳遞最大值。尤其是針對收集背景位置資訊時,因為收集背景位置資訊往往會導致多餘的電池耗電。建議保留幾秒鐘的間隔時間用於前景用途。Android 8.0 版導入的背景位置資訊限制強制執行這些策略,但您的應用程式也應盡力在 Android 7.0 以下版本的裝置上強制執行這些策略。

延遲時間

您可以使用 setMaxWaitTime() 方法指定延遲時間,通常,傳遞值大於 setInterval() 方法中指定的間隔時間。這項設定會延遲位置資訊傳送,並且可能分批傳送多個位置更新通知。這兩項變更都能使電池耗電量降至最低。

如果應用程式不需要立即的位置資訊更新,請將最大的可能值傳遞至 setMaxWaitTime() 方法,藉此有效拉長延遲時間,以掌握更多資料及提高電池效率。

使用地理圍欄時,應用程式應將較大值傳遞至 setNotificationResponsiveness() 方法以保留電力。建議值為 5 分鐘以上。

位置資訊用途

本節說明幾個典型的位置資訊收集情境,以及對於地理圍欄和整合式位置預測提供工具 API 的最佳利用建議。

使用者可見或前景更新

範例:需要頻繁、準確的更新,且延遲時間極少的地圖應用程式。所有更新都在前景執行:使用者開始活動、使用位置資料,並在短時間內停止活動。

使用 setPriority() 方法,其值為 PRIORITY_HIGH_ACCURACYPRIORITY_BALANCED_POWER_ACCURACY

setInterval() 方法中指定的間隔時間取決於用途:如果是即時情境,請將值設為幾秒鐘;否則,請限制為幾分鐘 (建議大約 2 分鐘以上,以盡量減少電池用量)。

知道裝置的位置

例如:天氣應用程式想知道裝置的位置。

使用 getLastLocation() 方法,會傳回最新的可用位置 (在極少數情況下可能為空值)。這個方法能夠輕鬆取得位置資訊,並且不會產生主動要求位置資訊更新的相關費用。搭配使用 isLocationAvailable() 方法,當 getLastLocation() 傳回的位置資訊為最新版本時,傳回 true

當使用者在特定位置時開始更新

範例:當使用者在工作、住家或其他位置的特定距離時要求更新。

使用 地理圍欄 搭配整合式位置預測提供工具更新。應用程式收到地理圍欄觸發條件時要求更新,並在應用程式收到地理圍欄進入觸發條件時移除更新。這可確保只有在使用者進入已定義的區域時,應用程式才會收到更精細的位置更新通知。

這種情境的典型工作流程可能包括,當地理圍欄進入轉換後立即顯示通知,以及當使用者輕觸通知時,啟動包含要求更新程式碼的活動。

根據使用者的活動狀態開始更新

範例:只在使用者開車或騎腳踏車時要求更新。

使用 動作語音辨識 API 搭配整合式位置預測提供工具更新。偵測到鎖定活動時要求更新,並在使用者停止執行該活動時移除更新。

這種用途的典型工作流程可能包括,偵測到活動時顯示通知,以及當使用者輕觸通知時啟動包含要求更新程式碼的活動。

與地理區域綁定的長時間執行背景位置資訊更新

範例:使用者想要在裝置位於零售商附近時收到通知。

這是地理圍欄的絕佳用途。因為此用途幾乎必定涵蓋背景位置資訊,所以請使用 addGeofences(GeofencingRequest, PendingIntent) 方法。

請設定下列設定選項:

  • 如果您正在追蹤暫留時間轉換,請使用 setLoiteringDelay() 方法,傳遞一個大約 5 分鐘以內的值。

  • 使用 setNotificationResponsiveness(),傳遞一個大約 5 分鐘的值。不過,如果您的應用程式可管理額外的回應延遲時間,建議採用大約 10 分鐘的值。

一個應用程式一次只能註冊最多 100 個地理圍欄。在一個用途中,如果一個應用程式想要追蹤大量的零售商選項,那麼這個應用程式可能會想註冊大型地理圍欄 (城市層級),並為大型地理圍欄內的商店動態註冊較小型的地理圍欄 (針對城市內的位置)。使用者進入大型地理圍欄時,可新增較小型的地理圍欄;當使用者退出較大的地理圍欄時,可移除較小的地理圍欄,並重新註冊新區域的地理圍欄。

無需可見的應用程式元件,即可長時間執行背景位置資訊更新

範例:被動追蹤位置的應用程式

請盡可能搭配 PRIORITY_NO_POWER 選項使用 setPriority() 方法,因為這樣幾乎不會消耗電池電力。如果無法使用 PRIORITY_NO_POWER,可以使用 PRIORITY_BALANCED_POWER_ACCURACYPRIORITY_LOW_POWER,但請避免將 PRIORITY_HIGH_ACCURACY 用於持續性的背景工作,因為這個選項會大量耗用電力。

如果您需要更多位置資料,請呼叫 setFastestInterval() 方法使用被動地位,傳遞一個比傳遞至 setInterval() 的值更小的值。與 PRIORITY_NO_POWER 選項搭配使用時,被動定位可以適時傳送其他應用程式計算出的位置資訊,無須額外付費。

使用 setMaxWaitTime() 方法增加一些延遲時間,藉此調節頻率。舉例來說,如果您使用 setinterval() 方法和大約 10 分鐘的設定值,應考慮呼叫的 setMaxWaitTime() 和 30 至 60 分鐘的設定值。使用這些選項時,系統大約每 10 分鐘計算應用程式的位置,但每 30 至 60 分鐘才喚醒應用程式,其中有部分位置資料可批次更新。這個方法會拉長延遲時間,以換取更多資料並提高電池效能。

使用者與其他應用程式互動時,頻繁進行高精確度更新

範例:當使用者關閉螢幕或開啟其他應用程式時,導航或健身應用程式仍會繼續運作。

使用前景服務。如果應用程式可能會以使用者的名義執行費用昂貴的作業,建議的最佳做法是讓使用者瞭解該項作業。前景服務需要持續通知。詳情請參閱 通知總覽

定位最佳做法

導入本節中的最佳做法有助於降低應用程式的電池用量。

移除定位更新通知

不必要的電池耗電是造成電力用盡的常見原因。舉例來說,當活動的 onStart()onResume() 生命週期方法中包含 requestlocationUpdates() 呼叫,就可能發生這種情形,但在 onPause()onStop() 生命週期方法中,卻沒有對應的 removeLocationUpdates() 呼叫。

您可以使用生命週期感知元件,妥善管理應用程式中的活動生命週期。詳情請參閱如何使用生命週期感知元件處理生命週期的相關說明。

設定逾時

為防止電池耗電,請設定一個位置更新通知應停止的合理逾時時間。逾時設定確保更新不會無限期地持續進行,在要求更新後但未移除更新的情況下 (例如,因為程式碼發生錯誤),還能保護應用程式。

針對整合式位置預測提供工具要求,請呼叫 setExpirationDuration() (接收代表接收自系統上次呼叫這個方法後的毫秒時間參數) 來新增逾時設定。此外,您也可以呼叫 setExpirationTime() (接收代表自系統上次啟動後起算的毫秒到期時間參數),來新增逾時設定。

如果要在地理圍欄定位要求中新增逾時設定,請呼叫 setExpirationDuration() 方法。

批次處理要求

對於所有非前景用途,請批次處理多個要求。您可以使用 setInterval() 方法,指定計算位置的間隔時間。接著,使用 setMaxWaitTime() 方法設定位置「傳送」至應用程式的間隔時間。傳遞至 setMaxWaitTime() 方法的值應數倍於傳遞至 setInterval() 方法的值。以下列定位要求為例:

Kotlin

val request = LocationRequest()
request.setInterval(10 * 60 * 1000)
request.setMaxWaitTime(60 * 60 * 1000)

Java

LocationRequest request = new LocationRequest();
request.setInterval(10 * 60 * 1000);
request.setMaxWaitTime(60 * 60 * 1000);

在這個案例中,我們大約每 10 分鐘計算一次位置,並且大概每小時批量傳送 6 個左右位置資料點。儘管您仍然每隔 10 分鐘左右就會收到位置更新通知,但由於每小時才喚醒您的裝置,因此可節省電力。

使用被動位置更新通知

在背景用途中,建議您限制位置更新通知次數。雖然 Android 8.0 限制會強制執行這種做法,但在舊版裝置上執行的應用程式應盡可能設法限制背景位置資訊。

很可能當您的應用程式在背景執行時,另一個應用程式可能正在前景頻頻要求位置更新通知。定位服務為您的應用程式提供這些更新。請考慮以下列位置資訊要求,適時使用位置資料:

Kotlin

val request = LocationRequest()
request.setInterval(15 * 60 * 1000)
request.setFastestInterval(2 * 60 * 1000)

Java

LocationRequest request = new LocationRequest();
request.setInterval(15 * 60 * 1000);
request.setFastestInterval(2 * 60 * 1000);

在上一個範例中,系統大約每 15 分鐘為您的應用程式計算位置。如果其他應用程式要求位置資訊,系統會以最長 2 分鐘的間隔時間將資料提供給您的應用程式。

雖然以被動方式使用位置資訊而未導致電池耗電,但在接收位置資料的位置時,會觸發費用昂貴的 CPU 或 I/O 作業,請務必格外小心謹慎。為盡量減少降低電池消耗,setFastestInterval() 中指定的間隔時間不得太小。

請參照本資訊頁面的建議,即可大幅提升使用者裝置的電池效能。使用者很可能比較不輕易刪除不耗電的應用程式。