Android 後台調度任務與省電
Android後台調度任務與省電
作者:Jacks Blog
I. Handler:
在進程存活的期間有效使用, Google官方推薦使用。
相關機制可以參見: Android Handler Looper機制
簡單易用。
穩定高效。
II. AlarmManager:
利用系統層級的鬧鐘服務(持有Wake Lock)。
1. 使用場景
在大概的時間間隔(重複)運行指定任務。
在精確的時間間隔(重複)運行指定任務。
需要精確的定時(重複)任務,如鬧鐘。
非網路訪問的,大概時間間隔的定時(重複)任務。
Google官方不建議網路請求相關的業務使用AlarmManager。
2. 特徵
運行在系統的鬧鐘服務上的,註冊以後,無論是自己的應用進程或組件是否存在,都會正常運作。
所有註冊的鬧鐘服務都會在系統重啟後複位,因此如果需要保證任務,就需要註冊RECEIVE_BOOT_COMPLETE廣播,確保重啟後,可以重新將任務註冊到鬧鐘服務中。
AlarmManager處理的是一個PendingIntent。
考慮到電量損耗,建議非特殊情況使用大概時間間隔的規則,這樣Android會盡量讓幾個任務打包在一起執行,防止頻繁的喚起手機。
III. Job Scheduler:
JobScheduler官方文檔
1. 使用場景
在指定特定場景下執行指定任務
Google官方建議網路請求相關業務放到Job Scheduler,由於其的省電的特性。
一些與特定場景(JobInfo)綁定的任務。
2. 特徵
Job Scheduler只有在Api21或以上的系統支持。
Job Scheduler是將多個任務打包在一個場景下執行。
在系統重啟以後,任務會依然保留在Job Scheduler當中,因此不需要監聽系統啟動狀態重複設定。
如果在一定期限內還沒有滿足特定執行所需情況,Job Scheduler會將這些任務加入隊列,並且隨後會進行執行。
3. 介面類型
boolean onStartJob(JobParams params) {n // 開始執行n // 注意這個方法是在主線程執行的,如果是耗時操作請拋到獨立線程中n // jobFinished(JobParameters params) // 在完成任務並且決定是否還需要定時執行更多任務n // return 是否是在獨立現在還有事務要執行n}n nvoid onStopJob(){n // 用於清理數據,在結束任務後被回調。n}n
IV. GCM(FCM)
GCM Network Manager實際上在 Api 21 或以上也是使用了 Job Scheduler,在此之前的版本使用的是Google Play Service中實現Job Scheduler的功能。
在GCMNetworkManager中有很多利於省電的規則。
在中國內地,該服務被牆,無法正常使用。
1. 使用場景
實時消息推送。
非實時消息推送。
2. 特徵
系統級別維護的長鏈接,十分穩定。
3. 介面類型
通過 OneoffTask.Builder()與PeriodicTask.Builder()創建任務。
GcmTaskService#onRunTask(TaskParams params)是在後台線程執行的。
V. Sync Adapter
Transferring Data Using Sync Adapters
1. 使用場景
用於同步服務端與本地設備中的數據。
通常是用於同步較多的數據,如系統聯繫人信息、Dropbox等。
2. 特徵
省電穩定。
可綁定一個賬戶。
利於大數據同步。
通過提供ContentProvider,可以快捷的與服務端同步的資料庫。
只有在存在網路的時候才觸發同步。
不需要依賴Google Play Service。
用戶可以通過設置中主動查看同步的時間,以及觸發同步,或者關閉同步。
Sync Adapter在API7或以上就可以使用,因此在一些場景下這是Job Scheduler在API21之前比較好的替代品。
3. 在一定的場景下觸發同步
儘可能的打包所有需要同步的任務在一個周期中執行,以此來進行儘可能的節省手機電量。
服務端或設備端數據發生變化。
手機閑置時。
一天。
如果同步失敗,會放到同步失敗的隊列中,在儘可能的時候進行同步。
VI. Doze Mode
Deep Doze Mode
API23中直接稱其為Doze Mode。
1. 特徵
旨在: 在用戶離開設備以後,儘可能的減少手機電量的消耗。
無論應用指定的Target SDK是多少,只要設備是Android 6或以上會啟用該模式。
開發人員並不需要做特殊的適配,但是會對上面提到的所有Schedule的方式(Job Scheduler、AlarmManager、Syncs Adapter)產生影響。
所有任務周期通過移動窗口打包任務執行,並且間隔時間會越來越久。
2. 進入條件
會同時滿足以下情況一段時間(大約30分鐘)以後生效:
手機沒有在充電
屏幕被關閉
手機各方狀態保持穩定
退出條件是,進入條件中任意條件狀態發生變化。
3. 在兩個處理窗口之間的手機狀態
對所有應用拒絕網路訪問。
所有JobScheduler、Sync-Adapter、AlarmManager的任務都會被延後到窗口中執行。
系統會拒絕所有來自應用的Wake Lock
停止所有Wifi以及GPS掃描
減少位置事件從設備檢測WiFi熱點。
Light Doze Mode
Android 7或以上會啟用該模式。
1. 特徵
相比Deep Doze Mode,打包執行任務的頻率會更高些。
2. 進入條件
會同時滿足以下情況一段時間(大約幾分鐘)以後生效:
手機沒有在充電
屏幕被關閉
處於穩定狀態/不穩定狀態
或者在Deep Doze Mode的情況下同時滿足以下條件下生效:
屏幕關閉
手機沒有在充電
手機不再處於穩定狀態
3. 退出條件
屏幕打開
手機開始充電
進入Deep Doze Mode
4. 在兩個處理窗口之間的手機狀態
對所有應用拒絕網路訪問。
所有JobScheduler與Sync Adapter的任務都會被延後到窗口中執行。
不會對AlarmManager中的任務進行影響,但是將無網路訪問(如果你的任務需要網路訪問,是時候改用JobScheduler或Sync Adapter了,這樣才會保證在任務窗口執行會有網路)
中斷/避開Doze
以下所有情況,Google官方都建議不在特殊情景,不要去使用,由於中斷了Doze Mode的省電規則。
1. AlarmManager
在精確的時間間隔中運行的任務: setAndAllowWhileIdle()、setExactAndAllowWhileIdle()。但是在非窗口期間並不解除無網路訪問的限制,並且只有10s的時間給予處理。
指定鬧鐘事件AlarmManager.setAlarmClock()的事件會在鬧鐘結束前,令系統短暫的完全退出Doze模式,並且正常處理事件,系統為了突顯該鬧鐘事件,將會在系統的Status Bar上顯示物理鬧鐘的ICON。
2. FCM/GCM
(Firebase Cloud Messaging,舊版中稱為Google Cloud Messaging(GCM))。
FCM/GCM中高優先順序的任務配置中("priority" : "high") 的消息,在Doze模式下可以正常及時到達。
3. 白名單
白名單官方文檔
官方建議可考慮加入白名單的情況
主動請求加入白名單,用戶同意以後才加入白名單;
用戶也可以主動將應用從白名單中刪除或將應用添加到白名單中;
應用可以通過isIgnoringBatteryOptimizations()來獲知是否在白名單中;
白名單的應用可以訪問網路與持有有效的Wake Lock,但是其他Doze的約束依然存在(如延後的Job Scheduler、Syncs-Adapter、AlarmManager);
白名單的請求方式:
通過ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS打開電量優化頁面,用戶可以通過搜索來關閉應用的電量優化,以此加入白名單。
先持有REQUEST_IGNORE_BATTERY_OPTIMIZATIONS許可權,然後通過啟動IntentACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS直接彈出Dialog讓用戶關閉應用的電量優化,以此加入白名單。
4. 特殊情況
前台服務(Foreground Service)將不會受到Doze模式影響。
Doze模式測試
Google官方提供了一些adb命令用於測試Doze模式,而非需要通過等待來進入Doze模式的。
1. 進入Doze模式
準備一台系統是在Android Nougat Developer Preview4或以上版本的設備。
將其連接連接到電腦。
通過執行adb shell dumpsys battery unplug命令讓設備進入未連接充電的模式。
通過執行adb shell dumpsys deviceidle step [light|deep]強行進入Doze模式。
退出Doze模式,讓手機恢復正常需要複位充電模式:adb shell dumpsys battery reset。
2. 其他指令
獲取設備狀態:adb shell dumpsys deviceidle get [light|deep|force|screen|charging|network]。
在Android Nougat Developer Preview 4中,Doze模式的狀態周期是:
Light: ACTIVE -> IDLE -> IDLE_MAINTENANCE -> OVERRIDE
Deep: ACTIVE -> IDLE_PENDING -> SENSING -> LOCATING -> IDLE -> IDLE_MAINTENANCE
閱讀原文
推薦閱讀: