個案研究

WHOOP 如何將部分 Wake Lock 工作階段過多的情況減少 90% 以上

4 分鐘小故事

為穿戴式裝置建構 Android 應用程式時,真正的挑戰在於螢幕關閉後的運作。WHOOP 協助會員瞭解身體對訓練、恢復、睡眠和壓力的反應,而對於許多使用 Android 的 WHOOP 會員來說,可靠的背景同步和連線能力是取得這些洞察資訊的關鍵。

今年稍早,Google Play 在 Android Vitals 中推出一項新指標:「部分 Wake Lock 使用過度」。這項指標會評估在 24 小時內,非豁免 Wake Lock 累計用量超過 2 小時的使用者工作階段百分比。這項指標旨在協助您找出並解決可能耗電的原因,這對提供優質使用者體驗至關重要。

2026 年 3 月 1 日起,如果應用程式仍未達到品質門檻,可能無法在 Google Play 探索介面顯示。Google Play 商店資訊也可能會顯示警告,指出應用程式的耗電量可能高於預期。

WHOOP 資深 Android 工程師 Mayank Saini 表示,Android Vitals 標記應用程式的部分 Wake Lock 過多百分比為 15%,超過建議的 5% 門檻,這「為團隊提供提高 Android 效率的機會」。

mayank.png

團隊認為 Android Vitals 指標明確指出,背景工作讓 CPU 保持喚醒的時間過長。解決這個問題後,他們就能繼續提供優質的使用者體驗,同時減少浪費的背景時間,並維持可靠、及時的藍牙連線能力和同步處理。

找出問題

為了找出著手點,團隊首先求助於 Android Vitals,深入瞭解哪些 Wake Lock 會影響指標。他們查看 Android Vitals 的「部分 Wake Lock 次數過多」資訊主頁,發現部分 Wake Lock 次數過多的主要原因,是其中一個 WorkManager worker (在資訊主頁中標示為 androidx.work.impl.background.systemjob.SystemJobService)。為了支援 WHOOP 的「全天候運作體驗」,應用程式使用 WorkManager 執行背景工作,例如定期同步處理,以及向穿戴式裝置提供週期性更新。

雖然團隊知道 WorkManager 在背景執行工作時會取得 Wake Lock,但先前他們無法掌握所有背景工作 (不只是 WorkManager) 的分配情況,直到 Android Vitals 推出過多部分 Wake Lock 指標後,他們才得以瞭解這項資訊。

資訊主頁指出 WorkManager 是主要原因後,團隊就能集中精力找出哪些 worker 影響最大,並著手解決問題。

利用內部指標和資料,更精確地找出原因

WHOOP 已設定內部基礎架構,用於監控 WorkManager 指標。他們會定期監控:

  1. 平均執行時間:worker 執行多久?
  2. 逾時:worker 逾時而非完成的頻率為何?
  3. 重試:如果工作逾時或失敗,worker 重試的頻率為何?
  4. 取消次數:工作取消的頻率。

除了追蹤 worker 的成功和失敗次數,團隊還能掌握工作效率。

內部指標指出少數幾個 worker 的平均執行時間過長,因此他們能進一步縮小調查範圍。

除了內部指標外,團隊也使用 Android Studio 的背景工作檢查器,檢查相關 worker 並進行偵錯,特別著重於相關聯的 Wake Lock,以符合 Android Vitals 標記的指標。

調查:區分 worker 變體

WHOOP 會針對部分 worker 使用一次性和週期性排程。這樣一來,應用程式就能針對相同工作重複使用相同的 Worker 邏輯,並採用相同的成功條件,只有時間不同。

他們使用內部指標,將搜尋範圍縮小到特定 worker,但無法判斷錯誤是在 worker 執行一次、定期執行或兩者皆有時發生。因此,他們推出更新,使用 WorkManager 的 setTraceTag 方法,區分同一個 Worker 的一次性和週期性變化版本。

有了這項額外資訊,他們就能明確找出哪種 Worker 變化版本 (定期或一次性) 對工作階段造成最多過度部分 Wake Lock。不過,資料顯示兩個版本的效果不相上下,這讓團隊感到驚訝。

WHOOP 的 Android 工程師 II Manmeet Tuteja 表示:「這項拆分作業也協助我們確認問題發生在『兩個』變體中,這表示問題與排程設定無關,而是與 worker 實作中的共用商業邏輯問題有關。」

manmeet.png

深入瞭解工作站行為並修正根本原因

團隊知道需要查看 worker 內部的邏輯,因此重新檢查調查期間標記的 worker 行為。具體來說,他們想找出工作可能卡住而無法完成的情況。

最後,我們終於找出 Wake Lock 使用過度的根本原因:

CoroutineWorker:設計用來等待與 WHOOP 感應器建立連線,再繼續執行。 

如果開始工作時未連接感應器,whoopSensorFlow (表示感應器是否已連接) 會是 null。SensorWorker並未將此視為提早結束條件,而是繼續執行,實際上是無限期等待連線。因此,WorkManager 會保留部分 Wake Lock,直到工作逾時為止,導致背景 Wake Lock 使用率偏高,且 SensorWorker 經常不必要地重新排程。

為解決這個問題,WHOOP 團隊更新了 worker 邏輯,在嘗試執行核心商業邏輯前,先檢查連線狀態。

如果感應器無法使用,worker 就會結束,避免逾時並釋放 Wake Lock。下列程式碼片段顯示解決方案:

class SensorWorker(appContext: Context, params: WorkerParameters): CoroutineWorker(appContext, params) {
   override suspend fun doWork(): Result {
      ...
      // Check the sensor state and perform work or return failure
       return whoopSensorFlow.replayCache
            .firstOrNull()
            ?.let { cachedData ->
                processSensorData(cachedData)
                Result.success()
            } ?: run {
                Result.failure()
            }
}

部分 Wake Lock 使用過度的工作階段減少 90%

推出修正程式後,團隊持續監控 Android Vitals 資訊主頁,確認變更帶來的影響。

最終,WHOOP 在對 Worker 進行變更後,僅僅 30 天內,過度部分 Wake Lock 百分比就從 15% 降至不到 1%。

partialWake.png

經過這些調整後,團隊發現工作逾時未完成的情況減少,平均執行時間也縮短了。

WHOOP 團隊對其他想提升背景工作效率的開發人員有以下建議:

sarthak.png

開始使用

如要減少應用程式的部分 Wake Lock 數量過多問題,或提高 worker 效率,請在 Android Vitals 查看應用程式的部分 Wake Lock 數量過多指標,並參閱 Wake Lock 說明文件,瞭解更多最佳做法和偵錯策略。

繼續閱讀