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. 在兩個處理窗口之間的手機狀態

  1. 對所有應用拒絕網路訪問。

  2. 所有JobScheduler、Sync-Adapter、AlarmManager的任務都會被延後到窗口中執行。

  3. 系統會拒絕所有來自應用的Wake Lock

  4. 停止所有Wifi以及GPS掃描

  5. 減少位置事件從設備檢測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

閱讀原文


推薦閱讀:

TAG:Android | 后台 | Android后台 |