和你一起終身學(xué)習(xí),這里是程序員 Android
本篇文章主要介紹 Android 開發(fā)中的部分知識(shí)點(diǎn),通過閱讀本篇文章,您將收獲以下內(nèi)容:
一、發(fā)現(xiàn)問題
二、解決問題
三、驗(yàn)證問題
四、最佳實(shí)踐
Partial wake locks 是 PowerManager 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)問題
您可能并不總是知道App被 Partial 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)注,感謝您的閱讀,謝謝!