Android?Doze低電耗休眠模式?與?WorkManager詳解
1. Doze模式下,WorkManager setInitialDelay設(shè)置小于15分鐘,被系統(tǒng)強(qiáng)制到15分鐘執(zhí)行,怎么辦 ?
Android 擁有兩項(xiàng)省電功能,通過管理設(shè)備未連接電源時(shí)應(yīng)用的行為來延長用戶電池續(xù)航時(shí)間:低電耗模式 (Doze) 和應(yīng)用待機(jī)模式 (App Standby)。 低電耗模式 通過延遲設(shè)備長時(shí)間未使用時(shí)應(yīng)用的后臺(tái) CPU 和網(wǎng)絡(luò)活動(dòng)來降低電池消耗。 應(yīng)用待機(jī)模式 延遲沒有近期用戶活動(dòng)的應(yīng)用的后臺(tái)網(wǎng)絡(luò)活動(dòng)。
設(shè)備處于低電耗模式時(shí),應(yīng)用對某些耗電資源的訪問會(huì)被延遲,直到維護(hù)窗口。 具體限制列在電量管理限制中。
低電耗模式和應(yīng)用待機(jī)模式管理在 Android 6.0 或更高版本上運(yùn)行的所有應(yīng)用的行為,無論它們是否專門針對 API 級(jí)別 23。為了幫助確保為用戶提供最佳體驗(yàn),請?jiān)诘碗姾哪J胶蛻?yīng)用待機(jī)模式下測試您的應(yīng)用,并對您的代碼進(jìn)行任何必要的調(diào)整。以下部分提供詳細(xì)信息。
2. 了解低電耗模式(Doze)
如果用戶將設(shè)備拔下電源并長時(shí)間靜置,且屏幕關(guān)閉,設(shè)備就會(huì)進(jìn)入低電耗模式。在低電耗模式下,系統(tǒng)會(huì)嘗試通過限制應(yīng)用對網(wǎng)絡(luò)和 CPU 密集型服務(wù)的訪問來節(jié)省電池電量。它還會(huì)阻止應(yīng)用訪問網(wǎng)絡(luò),并延遲其作業(yè)、同步和標(biāo)準(zhǔn)鬧鐘。
系統(tǒng)會(huì)定期短暫退出低電耗模式,讓應(yīng)用完成其延遲的活動(dòng)。在此 維護(hù)窗口 期間,系統(tǒng)會(huì)運(yùn)行所有待處理的同步、作業(yè)和鬧鐘,并允許應(yīng)用訪問網(wǎng)絡(luò)。

維護(hù)窗口結(jié)束后,系統(tǒng)會(huì)再次進(jìn)入低電耗模式,暫停網(wǎng)絡(luò)訪問并延遲作業(yè)、同步和鬧鐘。隨著時(shí)間的推移,系統(tǒng)安排維護(hù)窗口的頻率會(huì)降低,有助于在設(shè)備未充電且長時(shí)間不活動(dòng)的情況下減少電池消耗。
當(dāng)用戶通過移動(dòng)設(shè)備、打開屏幕或連接充電器來喚醒設(shè)備時(shí),系統(tǒng)會(huì)退出低電耗模式,所有應(yīng)用都會(huì)恢復(fù)正?;顒?dòng)。
3. 低電耗模式限制
設(shè)備處于低電耗模式時(shí),系統(tǒng)會(huì)對您的應(yīng)用施加以下限制:
- 暫停網(wǎng)絡(luò)訪問。
- 忽略喚醒鎖。
- 將標(biāo)準(zhǔn) AlarmManager 鬧鐘(包括 setExact() 和 setWindow())延遲到下一個(gè)維護(hù)窗口。
- 如果您需要在低電耗模式下觸發(fā)鬧鐘,請使用 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()。
- 通過 setAlarmClock() 設(shè)置的鬧鐘會(huì)正常觸發(fā)。系統(tǒng)會(huì)在這些鬧鐘觸發(fā)前不久退出低電耗模式。
- 不執(zhí)行 Wi-Fi 掃描。
- 不允許同步適配器運(yùn)行。
- 不允許 JobScheduler 運(yùn)行。
?? WorkManager 內(nèi)部使用 JobScheduler,因此 WorkManager 任務(wù)不會(huì)運(yùn)行。
4. Doze模式下,WorkManager 為何無法精確時(shí)間執(zhí)行 ?
通過上文,我們可以知道,在Doze模式下,WorkManager 任務(wù)不會(huì)運(yùn)行,只有在兩個(gè)Doze間隔期間,系統(tǒng)會(huì)定期短暫退出低電耗模式,讓應(yīng)用完成其延遲的活動(dòng)。在此 維護(hù)窗口 期間,系統(tǒng)會(huì)運(yùn)行所有待處理的同步、作業(yè)和鬧鐘,并允許應(yīng)用訪問網(wǎng)絡(luò)。 這個(gè)時(shí)候WorkManager的任務(wù)才會(huì)被執(zhí)行。但是兩個(gè)Doze之間休眠時(shí)間的間隔是不確定的,所以Doze模式下,WorkManager無法精確時(shí)間被執(zhí)行。
且如果WorkManager.setInitialDelay設(shè)置的時(shí)間小于15分鐘,會(huì)被系統(tǒng)強(qiáng)制替換為15分鐘。
那如果我就想10分鐘后執(zhí)行,需要怎么辦呢 ?
5. Doze模式下,如何精確時(shí)間執(zhí)行 ?
這個(gè)時(shí)候,就需要使用AlarmManager的setExactAndAllowWhileIdle方法了。 (雖然WorkManager在Android低版本上也是用的AlarmManager,但是并沒有使用AlarmManager的setExactAndAllowWhileIdle方法)
那么如何使用呢 ?
5.1 ??聲明權(quán)限?
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
5.2 調(diào)用前需驗(yàn)證是否已授權(quán)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
if (!alarmManager.canScheduleExactAlarms()) {
// 引導(dǎo)用戶前往設(shè)置頁授權(quán)
Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
return;
}
}5.3 創(chuàng)建 BroadcastReceiver? : ??接收鬧鐘觸發(fā)事件
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 執(zhí)行任務(wù)邏輯(如啟動(dòng)服務(wù)、發(fā)送通知)
Log.d("Alarm", "Triggered at exact time!");
}
}別忘了注冊 Receiver?
<receiver android:name=".AlarmReceiver" android:exported="false"/>
5.4 設(shè)置精確鬧鐘?
// 獲取 AlarmManager
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// 創(chuàng)建 Intent 指向 BroadcastReceiver
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
// 設(shè)置觸發(fā)時(shí)間(例如 10 分鐘后)
long triggerTime = System.currentTimeMillis() + 10 * 60 * 1000;
// 根據(jù)版本選擇方法
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP, // 使用 UTC 時(shí)間并喚醒設(shè)備
triggerTime,
pendingIntent
);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
}5.5 設(shè)置了AlarmManager,如果系統(tǒng)時(shí)間變更了,是不是鬧鐘在現(xiàn)實(shí)世界響起的時(shí)間也會(huì)變 ?
- 若用戶將系統(tǒng)時(shí)間??調(diào)快 1 小時(shí)??(從 9:00 改為 10:00),鬧鐘會(huì)??立即觸發(fā)??(因?yàn)橄到y(tǒng)時(shí)間已達(dá)到目標(biāo)值)。
- 若將系統(tǒng)時(shí)間??調(diào)慢 1 小時(shí)??(從 10:00 改為 9:00),鬧鐘會(huì)??延遲 1 小時(shí)觸發(fā)??(需等待系統(tǒng)時(shí)間再次達(dá)到 10:00)
可以監(jiān)聽系統(tǒng)時(shí)間變化的廣播,然后更改鬧鐘
// 在 onResume() 中注冊 IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); registerReceiver(timeChangeReceiver, filter); // 在 onPause() 中注銷 unregisterReceiver(timeChangeReceiver);
5.6 STATE_DOZE和STATE_DOZE_SUSPEND,有什么區(qū)別 ?
在 Android 電源管理機(jī)制中,STATE_DOZE 和 STATE_DOZE_SUSPEND 是兩種不同的休眠狀態(tài),其核心區(qū)別在于系統(tǒng)資源限制的嚴(yán)格程度和CPU活動(dòng)狀態(tài)。以下是兩者的詳細(xì)對比:
6. STATE_DOZE 和 STATE_DOZE_SUSPEND
STATE_DOZE(Doze 模式)- 首次引入于 Android 6.0(Marshmallow),目的是在設(shè)備閑置時(shí)(未充電、屏幕關(guān)閉、靜止?fàn)顟B(tài))減少后臺(tái)活動(dòng)。
- 狀態(tài)描述:系統(tǒng)進(jìn)入低功耗狀態(tài),但CPU仍保持部分活動(dòng),周期性喚醒處理任務(wù)。
STATE_DOZE_SUSPEND(Doze 掛起模式)- 強(qiáng)化版省電機(jī)制,于 Android 9.0(Pie) 引入,作為 Doze 的深度擴(kuò)展。
- 狀態(tài)描述:系統(tǒng)進(jìn)入更深度的休眠,CPU 完全停止運(yùn)行,僅保留最低限度的硬件喚醒能力(如傳感器)。
6.1 CPU 與任務(wù)執(zhí)行機(jī)制**
STATE_DOZE:- CPU 未完全停止,而是周期性喚醒(維護(hù)窗口)。
- 維護(hù)窗口間隔:初始為每 30 分鐘喚醒一次,隨后間隔逐漸延長(如 1 小時(shí)、2 小時(shí))。
- 任務(wù)處理:在維護(hù)窗口內(nèi),系統(tǒng)允許應(yīng)用執(zhí)行延遲的任務(wù)(如同步、AlarmManager 鬧鐘)。
STATE_DOZE_SUSPEND:- CPU 完全掛起,無周期性喚醒。
- 任務(wù)凍結(jié):所有后臺(tái)進(jìn)程被強(qiáng)制暫停(通過 Linux cgroup 的
freezer子系統(tǒng)),不再分配 CPU 時(shí)間片。 - 喚醒條件:僅通過外部事件觸發(fā)(如用戶操作、高優(yōu)先級(jí)鬧鐘
setAlarmClock())。
6.2 網(wǎng)絡(luò)與后臺(tái)資源訪問
STATE_DOZE:- 網(wǎng)絡(luò)限制:禁止后臺(tái)應(yīng)用訪問網(wǎng)絡(luò),僅維護(hù)窗口內(nèi)開放。
- 部分豁免:高優(yōu)先級(jí) GCM 消息、短信/電話可臨時(shí)喚醒網(wǎng)絡(luò)。
STATE_DOZE_SUSPEND:- 完全斷網(wǎng):所有網(wǎng)絡(luò)訪問被禁止,包括 GCM 和短信(僅保留基礎(chǔ)通信服務(wù)如通話)。
- 硬件限制:Wi-Fi/GPS 掃描、傳感器數(shù)據(jù)采集均暫停。
6.3 鬧鐘與任務(wù)調(diào)度行為
STATE_DOZE:- 標(biāo)準(zhǔn)鬧鐘延遲:
setExact()或setWindow()的鬧鐘被推遲至下一個(gè)維護(hù)窗口。 - 豁免鬧鐘:
setAndAllowWhileIdle()或setExactAndAllowWhileIdle()可在 Doze 下觸發(fā)(但受每分鐘 1 次的頻率限制)。
- 標(biāo)準(zhǔn)鬧鐘延遲:
STATE_DOZE_SUSPEND:- 所有鬧鐘凍結(jié):包括
AllowWhileIdle類型的鬧鐘,僅setAlarmClock()(用戶可見的鬧鐘)可喚醒設(shè)備。 - 任務(wù)調(diào)度失效:JobScheduler 和 WorkManager 任務(wù)被無限期推遲,直至退出 SUSPEND 狀態(tài)。
- 所有鬧鐘凍結(jié):包括
6.4 Wakelock 處理
STATE_DOZE:- 部分屏蔽:普通 WakeLock 被忽略(如
PARTIAL_WAKE_LOCK),但高優(yōu)先級(jí)服務(wù)(如媒體播放)可能被豁免。
- 部分屏蔽:普通 WakeLock 被忽略(如
STATE_DOZE_SUSPEND:- 完全無效:所有 WakeLock 被強(qiáng)制釋放,無法阻止 CPU 掛起。
6.5 持續(xù)時(shí)間與退出機(jī)制
STATE_DOZE:- 動(dòng)態(tài)維護(hù)窗口:窗口間隔隨閑置時(shí)間延長而增加(30 分鐘 → 1 小時(shí) → 數(shù)小時(shí))。
- 退出條件:屏幕點(diǎn)亮、設(shè)備移動(dòng)或充電。
STATE_DOZE_SUSPEND:- 持續(xù)掛起:無周期性窗口,直至外部事件喚醒。
- 退出條件更嚴(yán)格:僅用戶交互(如按鍵)、
setAlarmClock()鬧鐘或充電可喚醒。
6.6 對比總結(jié)
| 特性 | STATE_DOZE | STATE_DOZE_SUSPEND |
|---|---|---|
| CPU 狀態(tài) | 周期性喚醒(維護(hù)窗口) | 完全停止 |
| 網(wǎng)絡(luò)訪問 | 僅維護(hù)窗口開放 | 完全禁止 |
| 鬧鐘執(zhí)行 | 允許 AllowWhileIdle 類型 | 僅 setAlarmClock() 有效 |
| 任務(wù)調(diào)度 | 維護(hù)窗口內(nèi)執(zhí)行 | 完全凍結(jié) |
| Wakelock 有效性 | 部分豁免 | 全部釋放 |
| 退出條件 | 移動(dòng)/亮屏/充電 | 僅用戶操作或高優(yōu)先級(jí)鬧鐘 |
| 省電強(qiáng)度 | 中度 | 極端 |
6.7 適配建議
- 后臺(tái)任務(wù):
- 使用
WorkManager或JobScheduler,其任務(wù)在STATE_DOZE的維護(hù)窗口自動(dòng)執(zhí)行,但STATE_DOZE_SUSPEND中仍會(huì)被凍結(jié)。
- 使用
- 實(shí)時(shí)性需求:
- 關(guān)鍵任務(wù)(如鬧鐘)優(yōu)先用
setAlarmClock()(用戶可見),或引導(dǎo)用戶將應(yīng)用加入電池優(yōu)化白名單。
- 關(guān)鍵任務(wù)(如鬧鐘)優(yōu)先用
- 網(wǎng)絡(luò)依賴:
- 在
STATE_DOZE_SUSPEND下網(wǎng)絡(luò)完全不可用,需通過高優(yōu)先級(jí) GCM 消息或短信喚醒設(shè)備(系統(tǒng)服務(wù)如電話/SMS 始終豁免)。
- 在
- 狀態(tài)檢測:
- 通過
PowerManager.isDeviceIdleMode()檢測 Doze 狀態(tài),但無法直接區(qū)分SUSPEND(需依賴行為推斷)。
- 通過
?? 核心結(jié)論:
STATE_DOZE是 周期性喚醒的輕度休眠,適合延遲容忍的任務(wù);STATE_DOZE_SUSPEND是 CPU 完全停止的深度凍結(jié),僅響應(yīng)極高優(yōu)先級(jí)事件。
開發(fā)者需針對兩者設(shè)計(jì)降級(jí)策略,確保關(guān)鍵功能在極端省電下仍可工作。
7. STATE_DOZE_SUSPEND狀態(tài)下設(shè)置setExactAndAllowWhileIdle有效嗎
在 Android 的 STATE_DOZE_SUSPEND(深度掛起模式)狀態(tài)下,setExactAndAllowWhileIdle() 是無效的。以下是具體原因和機(jī)制分析:
7.1STATE_DOZE_SUSPEND的特性
- CPU 完全凍結(jié):
此狀態(tài)下系統(tǒng)進(jìn)入深度休眠,CPU 完全停止運(yùn)行,所有后臺(tái)進(jìn)程被強(qiáng)制暫停,僅保留基礎(chǔ)硬件喚醒能力(如高優(yōu)先級(jí)鬧鐘或物理按鍵)。 - 網(wǎng)絡(luò)與任務(wù)凍結(jié):
所有網(wǎng)絡(luò)訪問被禁止,JobScheduler、WorkManager等后臺(tái)任務(wù)被無限期推遲,標(biāo)準(zhǔn)鬧鐘和AllowWhileIdle類鬧鐘均被凍結(jié)。
7.2setExactAndAllowWhileIdle()的限制
- 僅適用于普通 Doze 模式:
setExactAndAllowWhileIdle()設(shè)計(jì)用于STATE_DOZE(普通休眠),可在維護(hù)窗口外觸發(fā)(但受每分鐘 1 次的頻率限制)。但在STATE_DOZE_SUSPEND下,系統(tǒng)無周期性喚醒機(jī)制,導(dǎo)致該方法失效。 - 深度省電下的喚醒條件:
僅以下事件可喚醒STATE_DOZE_SUSPEND:- 用戶主動(dòng)操作(如點(diǎn)亮屏幕)
- 高優(yōu)先級(jí)鬧鐘
setAlarmClock()(系統(tǒng)會(huì)提前退出休眠并顯示通知) - 設(shè)備充電。
7.3 替代方案
若需在 STATE_DOZE_SUSPEND 下可靠觸發(fā)任務(wù),需采用以下策略:
setAlarmClock():- 用于用戶可見的精確鬧鐘(如鬧鐘應(yīng)用),系統(tǒng)會(huì)強(qiáng)制退出休眠并顯示通知欄圖標(biāo)。
- 無需特殊權(quán)限,但用戶感知明顯。
- 引導(dǎo)用戶加入白名單:
- 用戶手動(dòng)在 設(shè)置→電池優(yōu)化 中將應(yīng)用設(shè)為“未優(yōu)化”,可部分豁免限制(非完全保障,廠商兼容性差異大)。
- 前臺(tái)服務(wù)(Foreground Service):
- 通過持續(xù)通知欄服務(wù)維持進(jìn)程活躍性,但需合理說明用途以避免被系統(tǒng)限制或用戶關(guān)閉。
7.4 總結(jié):不同鬧鐘方法在 Doze 模式下的有效性
| 鬧鐘方法 | STATE_DOZE(普通休眠) | STATE_DOZE_SUSPEND(深度掛起) |
|---|---|---|
setExact() / setWindow() | ? 延遲至維護(hù)窗口 | ? 完全凍結(jié) |
setAndAllowWhileIdle() | ? 可觸發(fā)(精度低) | ? 無效 |
setExactAndAllowWhileIdle() | ? 可觸發(fā)(秒級(jí)誤差) | ? 無效 |
setAlarmClock() | ? 立即觸發(fā) | ? 強(qiáng)制喚醒(需用戶可見通知) |
結(jié)論:
在STATE_DOZE_SUSPEND下,setExactAndAllowWhileIdle()無法觸發(fā)。若需極端省電模式下的可靠性,應(yīng)優(yōu)先使用setAlarmClock()或引導(dǎo)用戶設(shè)置白名單)。
8. 更多內(nèi)容
有關(guān)WorkManager基礎(chǔ)的概念和使用,詳見 : Android WorkManager的概念和使用
到此這篇關(guān)于Android Doze低電耗休眠模式 與 WorkManager詳解的文章就介紹到這了,更多相關(guān)Android Doze低電耗休眠模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)頁面短信驗(yàn)證功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)頁面短信驗(yàn)證功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
解析Android中使用自定義字體的實(shí)現(xiàn)方法
本篇文章是對在Android中使用自定義字體的方法進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下2013-05-05
Android實(shí)現(xiàn)斷點(diǎn)多線程下載
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)斷點(diǎn)多線程下載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
android網(wǎng)絡(luò)圖片查看器簡單實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了android網(wǎng)絡(luò)圖片查看器的簡單實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
Android響應(yīng)事件onClick方法的五種實(shí)現(xiàn)方式小結(jié)
本篇文章主要介紹了Android響應(yīng)onClick方法的五種實(shí)現(xiàn)方式小結(jié),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03
Android中應(yīng)用多進(jìn)程的整理總結(jié)
Android平臺(tái)支持多進(jìn)程通信,也支持應(yīng)用內(nèi)實(shí)現(xiàn)多進(jìn)程,下面這篇文章主要給大家介紹了關(guān)于Android中應(yīng)用多進(jìn)程的相關(guān)資料,文中介紹的很詳細(xì),相信對大家具有一定的參考借鑒價(jià)值,有需要的朋友們下面來一起看看吧。2017-01-01

