功耗問題之Partial Wake Locks

和你一起終身學(xué)習(xí),這里是程序員 Android

本篇文章主要介紹 Android 開發(fā)中的部分知識(shí)點(diǎn),通過閱讀本篇文章,您將收獲以下內(nèi)容:

一、發(fā)現(xiàn)問題
二、解決問題
三、驗(yàn)證問題
四、最佳實(shí)踐

Partial wake locksPowerManager API 中的一種機(jī)制??勺岄_發(fā)人員在設(shè)備顯示屏關(guān)閉(無(wú)論是由于系統(tǒng)超時(shí)還是用戶按下電源按鈕)之后,繼續(xù)讓CPU保持運(yùn)行狀態(tài)。

您的應(yīng)用通過 acquire() 使用 PARTIAL_WAKE_LOCK 標(biāo)志調(diào)用來(lái)獲取部分喚醒鎖。

如果部分喚醒鎖 在您的應(yīng)用程序在后臺(tái)運(yùn)行時(shí)被長(zhǎng)時(shí)間Hold,則會(huì) stuck(用戶看不到應(yīng)用程序的任何部分)。

這種情況會(huì)耗盡設(shè)備的電池電量,因?yàn)樗鼤?huì)阻止設(shè)備進(jìn)入低功耗模式。建議Partial wake locks應(yīng)僅在必要時(shí)使用,并且再不需要時(shí)立即釋放。

如果您的應(yīng)用有 Partial wake locks卡住,則可以使用下文中的指導(dǎo)來(lái)診斷和解決問題。

一、發(fā)現(xiàn)問題

您可能并不總是知道AppPartial wake locks卡住了。如果您已經(jīng)發(fā)布了應(yīng)用程序,則Android vitals可幫助您了解問題。

Android vitals

當(dāng)您的應(yīng)用程序顯示卡住的部分喚醒鎖時(shí) ,Android vitals可以通過Play Console提醒您,從而幫助提高應(yīng)用程序的性能 。Android vitals主要報(bào)告 partial wake locks卡住至少一個(gè)小時(shí)以上的問題,比如:

  • 至少占整個(gè)電池消耗的0.70%
    或者
  • 僅在后臺(tái)運(yùn)行時(shí),至少有0.10%的電池電量消耗

電池電量是指兩次充滿電的間隔,顯示的電池續(xù)航次數(shù)是該應(yīng)用程序所有測(cè)量用戶的匯總。有關(guān)Google Play如何收集Android生命數(shù)據(jù)的信息,請(qǐng)參閱 Play Console文檔。

一旦知道您的應(yīng)用程序卡住了部分喚醒鎖,下一步就是解決該問題。

二、解決問題

喚醒鎖是在Android平臺(tái)的早期版本中引入的,但是隨著時(shí)間的推移,以前需要喚醒鎖的許多用例現(xiàn)在可以通過諸如WorkManager更新的API更好地解決問題。

本節(jié)包含修復(fù)喚醒鎖的技巧,但從長(zhǎng)遠(yuǎn)來(lái)看,請(qǐng)考慮遷移您的應(yīng)用程序,以遵循 第四部分最佳實(shí)踐 中的建議。

在代碼中標(biāo)識(shí)并修復(fù)需要喚醒鎖的位置,例如newWakeLock(int ,String)WakefulBroadcastReceiver(Android O 已棄用)

  • newWakeLock(int ,String)
 PowerManager pm = (PowerManager)mContext.getSystemService(
                                          Context.POWER_SERVICE);
 PowerManager.WakeLock wl = pm.newWakeLock(
                                      PowerManager.SCREEN_DIM_WAKE_LOCK
                                      | PowerManager.ON_AFTER_RELEASE,
                                      TAG);
 wl.acquire();
 // ... do work...
 wl.release();
 

1.建議在喚醒鎖標(biāo)記包名、類名、方法名

這樣方便您可以輕松地在源碼中標(biāo)識(shí)創(chuàng)建喚醒鎖的位置。以下是一些其他提示:

  • 忽略名稱中的任何個(gè)人身份信息(PII),例如電子郵件地址。否則,設(shè)備將記錄日志,_UNKNOWN 而不是喚醒鎖名稱。

  • 不要以編程方式獲取類或方法的名稱,例如通過調(diào)用 getName() ,因?yàn)?code>Proguard可能會(huì)混淆它們。而是使用硬編碼的字符串。

  • 不要添加計(jì)數(shù)器或唯一標(biāo)識(shí)符來(lái)喚醒鎖定標(biāo)簽。系統(tǒng)將無(wú)法聚合通過相同方法創(chuàng)建的喚醒鎖,因?yàn)樗鼈兌季哂形ㄒ坏臉?biāo)識(shí)符。

2.確保您的代碼釋放了它獲取的所有喚醒鎖

準(zhǔn)確的使用 acquire()release(),避免異常導(dǎo)致無(wú)法是否喚醒鎖。

  • 舉例由于未捕獲的異常導(dǎo)致未釋放的喚醒鎖
    void doSomethingAndRelease() throws MyException {
        wakeLock.acquire();
        doSomethingThatThrows();
        wakeLock.release();  // does not run if an exception is thrown
    }

正確的寫法應(yīng)該如下

    void doSomethingAndRelease() throws MyException {
        try {
            wakeLock.acquire();
            doSomethingThatThrows();
        } finally {
            wakeLock.release();
        }
    }

3.確保喚醒鎖在不再需要時(shí)被釋放

如果您使用喚醒鎖來(lái)允許后臺(tái)任務(wù)完成,請(qǐng)確保該任務(wù)完成時(shí)及時(shí)釋放喚醒鎖。如果喚醒鎖保持的時(shí)間比預(yù)期的要長(zhǎng)而不被釋放,則可能意味著您的后臺(tái)任務(wù)花費(fèi)的時(shí)間比預(yù)期的要多。

三、驗(yàn)證問題

解決了代碼中的問題后,請(qǐng)使用以下Android工具驗(yàn)證您的應(yīng)用正確釋放了喚醒鎖:

1.dumpsys

dumpsys提供設(shè)備上系統(tǒng)服務(wù)狀態(tài)的信息??梢酝ㄟ^使用adb命令看電源服務(wù)的狀態(tài)(包括喚醒鎖列表)adb shell dumpsys power

C:\Users\Administrator>adb shell dumpsys power 
POWER MANAGER (dumpsys power)

Power Manager State:
  ... ...
  mBatteryLevel=46   // 電量信息
  mBatteryLevelWhenDreamStarted=0
  mDockState=0
  mStayOn=false
  mProximityPositive=false //Psensor
  mBootCompleted=true
  mSystemReady=true
  ... ... 

Settings and Configuration:
  
  ... ...
  mScreenBrightnessSettingMinimum=30  //屏幕連讀參數(shù)
  mScreenBrightnessSettingMaximum=255
  mScreenBrightnessSettingDefault=102
  mScreenBrightnessForVrSettingDefault=86
  mScreenBrightnessForVrSetting=86
  mDoubleTapWakeEnabled=false
  mIsVrModeEnabled=false
  ... ...

Suspend Blockers: size=4  //喚醒中斷源
  PowerManagerService.WakeLocks: ref count=0
  PowerManagerService.Display: ref count=0
  PowerManagerService.Broadcasts: ref count=0
  PowerManagerService.WirelessChargerDetector: ref count=0
  ... ...

2.Battery Historian

Battery Historian 一種將 Android Bugreport的輸出解析為與電源相關(guān)的事件的可視表示的工具。
比如:遇到功耗問題,我們可以執(zhí)行以下命令抓取 bugreport,并通過BatteryHistorian分析喚醒源。
具體操作步驟如下:

adb shell dumpsys batterystats --reset
adb shell dumpsys batterystats --enable full-wake-history
adb bugreport bugreport.zip

BatteryHistorian 詳細(xì)使用方法,請(qǐng)點(diǎn)擊下方鏈接。
BatteryHistorian使用詳解

四、最佳實(shí)踐

通常,應(yīng)用應(yīng)避免部分喚醒鎖定,因?yàn)檫@樣很容易耗盡用戶的電池。Android為需要部分喚醒鎖的用例提供了替代API。部分喚醒鎖的另一個(gè)用例是確保屏幕關(guān)閉時(shí)音樂應(yīng)用程序繼續(xù)播放。如果您使用喚醒鎖來(lái)運(yùn)行任務(wù),請(qǐng)考慮在background processing guide.
描述的替代方法。
如果必須使用部分喚醒鎖,請(qǐng)遵循以下建議:

  • 確保您的應(yīng)用程序的某些部分保留在前臺(tái)。例如,如果您需要運(yùn)行服務(wù),請(qǐng)start a foreground service。直觀地向用戶表明您的應(yīng)用仍在運(yùn)行。

  • 確保獲取和釋放喚醒鎖的邏輯盡可能簡(jiǎn)單。當(dāng)您的喚醒鎖邏輯與混淆多種狀態(tài),超時(shí),執(zhí)行程序池和/或回調(diào)事件相關(guān)聯(lián)時(shí),該邏輯中的任何細(xì)微錯(cuò)誤都可能導(dǎo)致喚醒鎖的保存時(shí)間超出預(yù)期。這些錯(cuò)誤很難診斷和調(diào)試。

至此,本篇已結(jié)束。轉(zhuǎn)載網(wǎng)絡(luò)的文章,小編覺得很優(yōu)秀,歡迎點(diǎn)擊閱讀原文,支持原創(chuàng)作者,如有侵權(quán),懇請(qǐng)聯(lián)系小編刪除,歡迎您的建議與指正。同時(shí)期待您的關(guān)注,感謝您的閱讀,謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容