Android M新特性Doze and App Standby模式詳解

分類:IT技術 時間:2016-10-17

參考:
Optimizing for Doze and App Standby
android M新特性Doze and App Standby模式詳解
深入android6.0 設備 idle狀態
Android M 的 Doze 模式下第三方推送服務還能用嗎?

一、Optimizing for Doze and App Standby

  1. 從Android6.0開始,Android提供了兩種省電延長電池壽命的功能:Doze和App Standby;

  2. 表現形式:當設備沒有連接到電源,設備進入Doze模式時,系統將通過延遲最近用戶沒有使用的應用程序的後臺CPU運作及網絡活動,讓應用程序處於App Standby狀態,以此來減少電池消耗。谷歌表示,在Nexus5和Nexus6上測試,當屏幕處於關閉狀態,平均續航時間提高30%;

  3. 版本要求:Android6.0(API level 23)及其更高版本;

  4. 開發者影響:為了保證用戶的最佳體驗,開發者有必要在Doze和App Standby模式下測試應用程序,及其對代碼進行相應的調整。

二、Understanding Doze

1.設備進入Doze睡眠模式時機:

  • 用戶不操作設備一段時間

  • 屏幕關閉

  • 設備未連接電源充電

2.Doze模式下應用程序有什麽變化:

  • 系統試圖通過限制應用程序訪問網絡和CPU密集型服務節省電池;

  • 防止應用程序訪問網絡,推延應用程序的工作,同步,和標準的警報;

  • 系統定期提供一個短暫的時間讓應用程序完成延遲的工作活動,之後再次進入Doze模式。在這個時間片裏,系統將提供維持性窗口(maintenance window)應用程序可以在此時執行訪問網絡,同步,和報警等活動。

Doze模式的五種狀態,分別如下:

  1. ACTIVE:手機設備處於激活活動狀態

  2. INACTIVE:屏幕關閉進入非活動狀態

  3. IDLE_PENDING:每隔30分鐘讓App進入等待空閑預備狀態

  4. IDLE:空閑狀態

  5. IDLE_MAINTENANCE:處理掛起任務

如下圖所示,Doze期間提供間隔一小段時間(30s)供應用程序使用網絡和處理掛起的活動。

這裏寫圖片描述

從這張圖我們可以看到,系統進入Doze模式後,系統會隔一段時間處理正在掛起的任務,隨著時間推移,後面間隔的時間會越來越長,以此來減少電量消耗。

3.退出Doze模式:

  • 移動設備
  • 打開屏幕
  • 設備連接電源

以上三種情況會退出Doze模式,之後apps回復正常模式。

4.Doze有哪些限制?

  • 網絡連接會被禁止

  • Wake Lock會被屏蔽

  • AlarmManager定時任務延遲到下一個maintenance window進行處理,除非使用AlarmManager提供的方法:setAndAllowWhileIdle() 或者setExactAndAllowWhileIdle()

  • 系統將不掃描熱點WIFI

  • 同步工作將被禁止

  • 不允許JobScheduler進行任務調度

5.適配Doze模式有什麽方法?

  • Doze影響到AlarmManager鬧鐘和定時器管理活動,在Android6.0引入了兩個新方法:setAndAllowWhileIdle() 和setExactAndAllowWhileIdle(),調用兩個方法可以在Doze模式下讓系統響應定時任務。

  • Doze模式下限制了網絡的連接,如果應用程序依賴於實時信息,那麽這個將影響App的體驗。那麽你需要使用Google Cloud Messaging (GCM)谷歌雲消息(後面詳細講解)

三、Understanding App Standby

當用戶不觸摸使用應用程序一段時間時,該應用程序處於App Standby狀態,系統將把該App標誌為空閑狀態(idle)。除非觸發以下任意條件,應用程序將退出App Standby狀態:

  1. 用戶主動啟動該App;

  2. 該App當前有一個前臺進程(或包含一個活動的前臺服務,或被另一個activity或前臺service使用);

  3. App生成一個用戶所能在鎖屏或通知托盤看到的Notification, 而當用戶設備插入電源時,系統將會釋放App的待機狀態,允許他們自由的連接網絡及其執行未完成的工作和同步。如果設備空閑很長一段時間,系統將允許空閑App一天一次訪問網絡。

四、Doze和App Standby的區別:

Doze模式需要屏幕關閉(通常晚上睡覺或長時間屏幕關閉才會進入),而App Standby不需要屏幕關閉,App進入後臺一段時間也會受到連接網絡等限制。

五、DeviceIdleController

DeviceIdleController是Doze模式的主要驅動。接下來,我將使用device idle mode而不是doze mode來描述“Doze”,因為它更符合代碼的實際情況。

5.1、deviceidle——新的系統服務

如果你已經閱讀了官方文檔,你可能已經註意到下面的命令,開發者可以通過這些命令得知當下設備的應用行為:

adb shell dumpsys battery unplug  
adb shell dumpsys deviceidle step  

對於上面的命令你可能並不熟悉,dumpsys是用來與系統服務交互的(查看它們的狀態)。deviceidle是我們之前沒有看到過的,它是一個新的系統服務。用來檢測是否進入idle mode(Doze模式)

$ adb shell service list | grep deviceidle  
59  deviceidle: [android.os.IDeviceIdleController]  

我們可以使用‘-h’看到所有的deviceidle的所有選項:

$ adb shell dumpsys deviceidle -h  
Device idle controller (deviceidle) dump options:  
  [-h] [CMD]  
  -h: print this help text.  
commands:  
  step  
    Immediately step to next state, without waiting for alarm.  
  disable  
    Completely disable device idle mode.  
  enable  
    Re-enable device idle mode after it had previously been disabled.  
  whitelist  
    Add (prefix with +) or remove (prefix with -) packages. 

5.2、DeviceIdleController的五種狀態

DeviceIdleController維持著設備包含的五種狀態,和上面介紹的Doze的五種狀態是一樣的:

  • ACTIVE – 設備在使用中,或者連接著電源。
  • INACTIVE – 設備已經從ACTIVE狀態中出來一段時間了(使用者關閉了屏幕或者拔掉了電源)
  • IDLE_PENDING – 請留意,我們將進入idle mode.
  • IDLE – 設備進入idle mode.
  • IDLE_MAINTENANCE – 應用窗口已經打開去做處理.

1、當設備被喚醒和正在使用中,控制器就處於ACTIVE狀態,
2、不活躍時間超時,用戶關閉屏幕等等,將會使設備狀態進入到INACTIVE.

3、INACTIVE狀態下,DeviceIdleController將會通過AlarmManager來設置他自己的alarm來驅動進程:

一個alarm會被設置在一個預設的時刻(這個時間在M的預覽中是30分鐘)。
當這個alarm生效後,DeviceIdleController 會進入到IDLE_PENDING然後再次設置同樣的alarm。

4、當觸發下一個alarm後,控制器會進入到IDLE 狀態,進入到這個狀態後,應用特性會被完全限制。

5、IDLE 狀態後,會在IDLE 和IDLE_MAINTENANCE兩個狀態之間周期性的跳轉。IDLE_MAINTENANCE也就是Doze中提到的maintenance window,在這個狀態下,應用程序可以在此時執行訪問網絡,同步,和報警等活動。

這些服務的公共API(由IDeviceIdleController 接口展現)持有全部方法訪問白名單。應用(系統應用或其它第三方應用)任何情況下都不能驅動控制器狀態

5.3、DeviceIdleController 維護著一個應用白名單

正如你在上面的幫助菜單中看到的一樣,DeviceIdleController 維護著一個應用白名單,不需要額外的參數,通過dump服務的狀態,我們能夠看到現在的這個列表:

$ adb shell dumpsys deviceidle  
  Whitelist system apps:  
    com.android.providers.downloads  
    com.android.vending  
    com.google.android.gms  
  Whitelist app uids:  
    UID=10012: true  
    UID=10016: true  
    UID=10026: true  
  …  

這個名單分為兩個部分:系統應用和第三方應用。

系統應用

系統應用會被平臺制作者通過配置定義列在白名單中。下面這個是從Nexus 6中得到的一個配置定義例子,它將GMS核心(在GCM中使用),應用商店,以及一個任意的用於電源監控的app白名單化:

<?xml version="1.0" encoding="utf-8"?>  
<!-- These are configurations that must exist on all GMS devices. -->  
<config>  
    <allow-in-power-save package="com.google.android.gms" />  

    <allow-in-power-save package="com.android.vending" />  

    <allow-in-power-save package="com.google.android.volta" />  
</config> 

其它的系統服務可以通過SystemConfig的實例訪問到這些值。DeviceIdleController使用SystemConfig.getAllowInPowerSave()將這些系統定義的元素放到白名單中。

註意:當設備處於“省電模式”時,同樣也是這個配置文件決定哪個系統應用可以在後臺開啟服務。

第三方應用

白名單中剩下的部分是用戶定義的,這些項可以通過兩種方式被增加和刪除。

第一種:開發者可以通過dumpsys接口使用白名單命令:

$ adb shell dumpsys deviceidle whitelist +com.example.myapplication  
$ adb shell dumpsys deviceidle  
  Whitelist system apps:  
    com.android.providers.downloads  
    com.android.vending  
    com.google.android.gms  
  Whitelist user apps:  
    com.example.myapplication  
  Whitelist app uids:  
    UID=10012: true  

第二種:用戶可以通過設置(Settings -> Battery -> Ignore optimizations)來修改白名單。

這裏寫圖片描述這裏寫圖片描述

另外:在小米手機中,神隱模式中把應用設置為無限制或者在近期任務中下拉鎖定,就會出現在上述的白名單中。

六、測試Doze和App Standby模式的方法(Adb命令)

測試Doze模式

1、 首先確保你的硬件或虛擬設備是Android6.0或更高版本系統;

2、 連接設備到開發機上並安裝你的app;

3、 運行app並讓其運行活動;

4、 關閉設備的屏幕;

5、運行以下adb命令使系統進入Doze模式:

$ adb shell dumpsys battery unplug

$ adb shell dumpsys deviceidle step

你可能需要多次執行第二條命令,直到設備處於idle 狀態。註意,第一條命令的意思是,拔去電源,即使現在正在插著usb調試,也不會充電。建議運行

$ adb shell dumpsys battery reset
,否則會出現手機充不上電的情況。

6、 觀察你的app表現行為是否有需優化改進的地方。

測試App Standby模式

步驟1-3同測試Doze模式

4、 運行以下adb命令迫使系統進入App Standby模式:

$ adb shell dumpsys battery unplug

$ adb shell am set-inactive <packageName> true

5、 模擬喚醒你的應用程序使用以下命令:

$ adb shell am set-inactive <packageName> false

$ adb shell am get-inactive <packageName>

6、 觀察你的App,確保應用程序可以從standby mode優雅得恢復,應該檢查App的通知及後臺能按預期的繼續工作。

七、客戶端使用方法:

  1. App程序可發送action為ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS的intent引導用戶進入設置界面將應用程序設置進白名單列表裏。

  2. 應用程序還可以使用AREQUEST_IGNORE_BATTERY_OPTIMIZATIONS 權限來觸發一個系統對話來讓用戶添加到白名單裏,而無需進入設置界面去設置。

當然,官方也提供用戶把你的App移除電池優化白名單的選項。這個白名單也會被Android M的另一個新特性 App Standby使用,所以用戶只能簡單的進行控制,也就是說設備並不會完全相信這個白名單。

這個白名單只是谷歌的一個建議,就是說在下面這些情況下,你可以使用上面兩張方法,來引導用戶把你的app設為白名單

官方舉了一下白名單例子:

這裏寫圖片描述

總結:

我認為Doze 模式和 APP Standby模式,限制app的權限種類都是一樣的。都是進入idle狀態。只是各自模式的進入和退出所需要的條件不一樣、進入模式後控制APP的周期也不一樣。

Doze模式的推出本身是為了減少電池的消耗,且Google希望統一使用GCM來傳遞消息進行通訊,而對於國內開發來講,確實帶來了很大的麻煩:

  1. 國內開發的一些消息推送機制(PUSH)將受到影響;

  2. 若使用GCM,在國內使用GCM延遲高,對於即時通訊產品來說選擇還需勇氣啊;

  3. 國內第三方手機廠商如華為、小米、三星,定制的Rom也將使用定制的推送消息機制。這讓同一款App如何選擇哪種推送機制才能兼容呢?

解決方法:

  1. 用戶添加應用程序到電池優化白名單列表;

  2. 開發者使用Google提供的ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS意圖和AREQUEST_IGNORE_BATTERY_OPTIMIZATIONS權限設置以此忽略(推薦);

  3. 使用Google提供的GCM;

  4. 通過so繞過Doze模式。


我使用MIUI 7.5(Android 6.0.1)測試過程中發現,自己維持長連接一進入standby模式,網絡就斷了(手機其它app網絡正常),但是運行在後臺的代碼還是一直在跑,log也能正常輸出到手機的文件上,就是連不上網。按照官方的描述進入standby模式,工作應該被掛起,但是為什麽後臺代碼還是正常運行呢??請高人指點一下

  • 微信的主進程可以手動設置為standby 模式,
  • APP的子進程都是無法設置為standby 模式,但是如果主進程是standby 模式,子進程也會是standby 模式。即使使用命令查看子進程的standby 狀態也是false。
  • 在正常使用手機的情況下,微信的主進程無法進入standby 模式,感覺是使用so繞過standby模式。具體so文件是怎麽實現的,還請大神指點一下。

Tags: Android 應用程序 window 谷歌 第三方

文章來源:


ads
ads

相關文章
ads

相關文章

ad