操作說明

電池技術品質強制執行措施即將上路:如何針對常見的喚醒鎖定用途進行最佳化

8 分鐘閱讀
Alice Yuan
開發人員關係工程師

Google 瞭解 Android 使用者最重視電池耗電,因此採取重大措施,協助開發人員打造更省電的應用程式。自 2026 年 3 月 1 日起,Google Play 商店開始推出Wake Lock 技術品質處理方式,以改善電池耗電問題。我們會在接下來幾週內,逐步為受影響的應用程式推出這項處理方式。如果應用程式在 Android Vitals 中持續超出「部分 Wake Lock 停滯次數過多」門檻,商店發布可能會受到實質影響,包括商店資訊顯示警告,以及遭排除在推薦等探索途徑之外。

appDetails.png

如果應用程式超出不良行為門檻,商店資訊可能會顯示警告訊息。 

這項計畫將電池效率提升為核心重要指標,與當機和 ANR 等穩定性指標並列。「不良行為門檻」是指在過去 28 天內,有超過 5% 的使用者工作階段中,螢幕關閉時平均持有非豁免的部分 Wake Lock 至少 2 小時。如果 Wake Lock 是由系統持有,且可提供明確的使用者效益 (例如音訊播放、位置存取權或使用者啟動的資料移轉),且無法進一步最佳化,則可豁免。如要查看過多 Wake Lock 的完整定義,請參閱 Android Vitals 說明文件

為持續提升 Android 生態系統的電池續航力,我們分析了數千個應用程式,以及這些應用程式使用部分喚醒鎖定的方式。雖然有時需要喚醒鎖定,但我們經常發現應用程式會以效率不彰或不必要的方式保留喚醒鎖定,而其實有更有效率的解決方案。這篇網誌文章將說明最常見的過度喚醒鎖定情境,並提供喚醒鎖定最佳化建議。WHOOP 等合作夥伴已根據這些建議最佳化背景行為,並獲得顯著成效。

使用前景服務與部分喚醒鎖定

我們發現開發人員在執行背景執行作業時,經常難以區分前景服務和部分喚醒鎖定這兩個概念。

前景服務是生命週期 API,可向系統發出信號,指出應用程式正在執行使用者可感知的工作,因此不應終止應用程式來回收記憶體,但不會在螢幕關閉時自動防止 CPU 進入休眠狀態。相反地,部分 Wake Lock 機制專門用於讓 CPU 保持運作,即使螢幕關閉也不例外。

雖然前景服務通常是繼續執行使用者動作的必要條件,但只有在 CPU 活動期間,才需要搭配前景服務手動取得部分 Wake Lock。此外,如果您已使用可讓裝置保持喚醒狀態的 API,就不需要使用 Wake Lock。

請參閱「選擇適當的 API 來保持裝置喚醒狀態」中的流程圖,確保您充分瞭解在不必要的情況下,應使用哪種工具來避免取得 Wake Lock。

第三方程式庫取得 Wake Lock

應用程式通常會發現,第三方 SDK 或系統 API 代表應用程式持有過多的喚醒鎖定,因此遭到標記。如要找出並解決這些喚醒鎖定問題,建議採取下列步驟:

  • 檢查 Android Vitals:部分 Wake Lock 停滯次數過多資訊主頁中,找出違規 Wake Lock 的確切名稱。請參閱「識別其他 API 建立的喚醒鎖定」指南,交叉比對這個名稱,確認喚醒鎖定是否由已知的系統 API 或 Jetpack 程式庫建立。如果是,您可能需要最佳化 API 用量,並參閱建議的指南。
  • 擷取系統追蹤記錄:如果無法輕易找出 Wake Lock,請使用系統追蹤記錄在本地重現 Wake Lock 問題,並透過 Perfetto UI 檢查。如要進一步瞭解如何執行這項操作,請參閱這篇網誌文章的「偵錯其他類型的過度喚醒鎖定 」一節
  • 評估替代方案:如果問題是由效率不彰的第三方 SDK 造成,且無法設定為尊重電池續航力,請考慮向 SDK 擁有者回報問題、尋找替代 SDK,或自行建構功能。

常見的 Wake Lock 情境

以下是我們審查過的一些特定用途,以及最佳化 Wake Lock 實作方式的建議路徑。

使用者啟動上傳或下載

用途範例:

  • 使用者在影片串流應用程式中下載大型檔案,以便離線存取。
  • 媒體備份應用程式:使用者透過通知提示觸發上傳最近的相片。

如何減少 Wake Lock: 

  • 請勿取得手動 Wake Lock。請改用 User-Initiated Data Transfer (UIDT) API。這是使用者啟動長時間執行的資料移轉工作的指定路徑,因此可免除過度 Wake Lock 計算。

一次性或定期背景同步

用途範例:

  • 應用程式會定期在背景同步處理,以便擷取資料供離線存取。
  • 定期擷取步數的計步器應用程式。

如何減少 Wake Lock:

  • 請勿取得手動 Wake Lock。使用為一次性或週期性工作設定的 WorkManagerWorkManager 會將工作分批處理,並設有最短週期性間隔 (15 分鐘),以維護系統健康狀態,這通常足以應付背景更新。
  • 如果發現 WorkManager 或 JobScheduler 建立的 Wake Lock 用量偏高,可能是因為您設定的 worker 在特定情況下無法完成工作。建議您分析工作站停止的原因,特別是如果 STOP_REASON_TIMEOUT 的發生次數很高。
  workManager.getWorkInfoByIdFlow(syncWorker.id)
  .collect { workInfo ->
      if (workInfo != null) {
        val stopReason = workInfo.stopReason
        logStopReason(syncWorker.id, stopReason)
      }
  }
  • 除了記錄工作站停止的原因外,請參閱偵錯工作站的說明文件。此外,請考慮收集及分析系統追蹤記錄 ,瞭解喚醒鎖定功能的取得和釋出時間。
  • 最後,請參閱我們與 WHOOP 合作的個案研究,瞭解他們如何發現 worker 的設定問題,並大幅減少 Wake Lock 影響。

藍牙通訊

用途範例:

  • 配對裝置應用程式會提示使用者配對藍牙外部裝置。
  • 配對裝置應用程式會監聽外部裝置上的硬體事件,以及通知中使用者可見的變更。
  • 配對裝置應用程式的使用者在行動裝置和藍牙裝置之間啟動檔案傳輸。
  • 配對裝置應用程式會透過藍牙,不時更新外部裝置的韌體。

如何減少 Wake Lock:

  • 使用配對裝置配對功能配對藍牙裝置,避免在藍牙配對期間取得手動 Wake Lock。
  • 請參閱 在背景中通訊指南,瞭解如何進行背景藍牙通訊。
  • 如果延遲通訊不會對使用者造成影響,通常使用 WorkManager 就已足夠。如果認為必須手動 Wake Lock,請只在藍牙活動或處理活動記錄期間保留 Wake Lock。

定位追蹤

用途範例:

  • 健身應用程式會快取位置資料,以便稍後上傳,例如繪製跑步路線
  • 外送應用程式會以高頻率擷取位置資料,並在通知或小工具 UI 中更新外送進度。

如何減少 Wake Lock:

  • 請參閱我們的指南,瞭解如何最佳化位置資訊的使用方式。請考慮導入逾時、善用位置資訊要求批次處理,或使用被動位置資訊更新,確保電池效率。
  • 使用 FusedLocationProvider 或 LocationManager API 要求位置更新時,系統會在位置事件回呼期間自動觸發裝置喚醒。系統管理的短暫 Wake Lock 不會納入部分 Wake Lock 使用過度的計算。
  • 避免為快取位置資料取得個別的連續喚醒鎖定,因為這是多餘的。請改為將位置資訊事件儲存在記憶體或本機儲存空間中,並利用 WorkManager 定期處理這些事件。
  override fun onCreate(savedInstanceState: Bundle?) {
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            // System wakes up CPU for short duration
            for (location in locationResult.locations){
                // Store data in memory to process at another time
            }
        }
    }
}

高頻感應器監控

用途範例:

  • 被動收集步數或移動距離的計步器應用程式。
  • 安全應用程式會即時監控裝置感應器是否快速變化,並提供車禍偵測或跌倒偵測等功能。

如何減少 Wake Lock:

  • 如果使用 SensorManager,請減少使用次數,只在使用者透過 UI 互動明確授予存取權時使用。高頻率感應器監控會導致 CPU 喚醒次數和處理作業增加,因此耗電量會大幅提升。
  • 如要追蹤步數或移動距離,請使用 Recording API,而非 SensorManager,或考慮使用 健康資料同步存取裝置的歷史和匯總步數,以省電的方式擷取資料。
  • 如要使用 SensorManager 註冊感應器,請指定 30 秒以上的 maxReportLatencyUs,以便運用感應器批次處理功能,盡量減少 CPU 中斷的頻率。當裝置隨後因其他觸發條件 (例如使用者互動、位置資訊擷取或已排定的工作) 而喚醒時,系統會立即傳送快取的感應器資料。
  val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

sensorManager.registerListener(this,
                 accelerometer,
                 samplingPeriodUs, // How often to sample data
                 maxReportLatencyUs // Key for sensor batching 
              )
  • 如果應用程式需要位置和感應器資料,請同步擷取及處理這些資料的事件。將感應器讀數附加到系統為位置資訊更新保留的簡短 Wake Lock,即可避免需要 Wake Lock 來保持 CPU 喚醒狀態。使用 worker 或短時間 Wake Lock,處理這項合併資料的上傳和處理作業。

遠端訊息

用途範例:

  • 需要監控透過區域網路連線的外部裝置上發生的事件。
  • 與電腦版維持網路通訊端連線的訊息應用程式。

如何減少 Wake Lock:

  • 如果網路事件可在伺服器端處理,請使用 FCM 在用戶端接收資訊。如果需要額外處理 FCM 資料,您可以選擇安排加急工作人員
  • 如果必須透過通訊端連線在用戶端處理事件,則不需要 Wake Lock 來監聽事件中斷。資料封包抵達 Wi-Fi 或行動網路無線電時,無線電硬體會以核心 Wake Lock 的形式觸發硬體中斷。然後,您可以選擇排定 worker 或取得 Wake Lock,以處理資料。
  • 舉例來說,如果您使用 ktor-network 監聽網路插座上的資料封包,只有在封包已傳送至用戶端且需要處理時,才應取得 Wake Lock。
  val readChannel = socket.openReadChannel()
while (!readChannel.isClosedForRead) {
    // CPU can safely sleep here while waiting for the next packet
    val packet = readChannel.readRemaining(1024) 
    if (!packet.isEmpty) {
         // Data Arrived: The system woke the CPU and we should keep it awake via manual wake lock (urgent) or scheduling a worker (non-urgent)
         performWorkWithWakeLock { 
              val data = packet.readBytes()
              // Additional logic to process data packets
         }
    }
}

摘要

針對常見用途 (例如背景同步、位置追蹤、感應器監控和網路通訊) 採用這些建議解決方案,開發人員就能減少不必要的 Wake Lock 使用量。如要繼續瞭解,請參閱其他技術網誌文章,或觀看技術影片,瞭解如何找出並偵錯 Wake Lock:「Optimize your app battery using Android vitals wake lock metric」(使用 Android Vitals Wake Lock 指標改善應用程式電池用量)。此外,請參閱更新的喚醒鎖定說明文件。為協助我們持續改善技術資源,請在文件意見回饋問卷中,分享您對指南的其他意見。

撰寫者:

繼續閱讀