天天看點

Android-電池優化Doze和Standby模式-AlarmManager失效

一.電池省電優化(Doze和App Standby模式)

從Android6.0開始,系統提供了兩種省電功能(延長電池壽命和使用時間):Doze和App Standby
Doze和App Standby模式會延緩CPU和網絡活動實作節能;
           

1.Doze模式

1.進入Doze模式
    在手機未充電,完全靜止且熄屏一段時間後,Android系統會自動進入Doze模式

2.Doze模式效果
    1.網絡通路被挂起
    2.Wake Locks被無視     
    3.AlarmManager被推遲到下一個maintenance window視窗,
    除非使用AlarmManager新方法: setAndAllowWhileIdle(),setExactAndAllowWhileIdle(),setAlarmClock()
    4.WiFi掃描被停止
    5.SyncAdapter同步工作被停止
    6.JobScheduler定時任務被停止

    Doze模式的五種狀态
        ACTIVE:           活動狀态
        INACTIVE:         螢幕關閉進入非活動狀态
        IDLE_PENDING:     每隔30分鐘讓App進入預備狀态
        IDLE:             空閑狀态
        IDLE_MAINTENANCE:處理挂起任務     
    系統進入Doze模式後,每隔一段時間(30分鐘)會有一小段時間(30s)供APP處理被挂起任務,
    但随着時間推移,間隔時間會變長,以此減少電量消耗

3.退出Doze模式
    1.手機充電
    2.手機移動
    3.手機螢幕打開
           

2.App Standby模式

1.進入App Standby模式
    長時間未被使用者使用的App,将進入App Standby狀态(被标志為空閑狀态)

2.退出App Standby模式
    1.使用者主動啟動該App
    2.該App有前台程序(前台activity/前台service),被其它前台程序啟動
    3.該App在鎖屏或通知欄有可見的Notification
    4.Android裝置充電時,會将所有Standby狀态的App釋放,處理挂起任務
    5.如果App空閑時間很長,系統将允許App一天一次通路網絡

3.App Standby和Doze差別
App Standby不需要螢幕關閉,App進入背景一段時間,網絡也會受到限制
Doze模式需要螢幕關閉(通常晚上睡覺或長時間螢幕關閉才會進入)
           

3.阻止電池優化(白名單)

Android6.0及更高版本提供電池優化白名單,App加入白名單可逃脫Doze和App Standby限制,
處于白名單中的App也會受到一定限制: Jobs和Syncs以及正常Alarms也會被推遲;

使用者手動設定App進入白名單: 設定>電池>電池優化白名單

App檢測是否在白名單: PowerManager.isIgnoringBatteryOptimizations()

App請求加入白名單:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    if (pm != null && !pm.isIgnoringBatteryOptimizations(getPackageName())) {
        //1.進入系統電池優化設定界面,把目前APP加入白名單
        //startActivity(new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS));

        //2.彈出系統對話框,把目前APP加入白名單(無需進入設定界面)
        //在manifest添權重限 <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
        Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    }
}
           

二.AlarmManager定時鬧鐘失效

1.App被Kill後,AlarmManager失效(隻有App程序在運作時,才會收到系統定時AlarmManager通知)
    添加守護程序,互相監聽重新開機; 提醒使用者加入鎖屏清理白名單
2.手機重新開機,AlarmManager任務失效
    監聽重新開機廣播,重新設定定時鬧鐘
3.從Android4.4(API19)開始,AlarmManager機制修改,set(),setRepeating()定時不再精确,甚至setRepeating隻生效一次(不會重複)
    新增精确定時方法: setExact(),setWindow(),setAlarmClock(),
4.從Android6.0(API23)開始,進入Doze模式(省電優化),AlarmManager被延緩
    新增精确定時方法: setAndAllowWhileIdle(),setExactAndAllowWhileIdle()

從Android4.4(API19)開始,新增精準定時方法都是一次性鬧鐘,沒有重複定時的方法,
是以當需要重複周期鬧鐘,隻能在下一次喚醒時重新設定定時,間接實作重複鬧鐘!

精确定時一次Demo如下:
void setWakeAtTime(Context cxt, int delay) {
    PendingIntent pi = PendingIntent.getService(cxt,0,new Intent(cxt, xxService.class),PendingIntent.FLAG_UPDATE_CURRENT); 
    AlarmManager alarm = (AlarmManager) cxt.getSystemService(Context.ALARM_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) //Android 6,針對省電優化
        alarm.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pi);
    else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) //Android 4.4,針對set不準确
        alarm.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pi);
    else
        alarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delay, pi);   
}
           

簡書: http://www.jianshu.com/p/585ca251b871

CSDN部落格: http://blog.csdn.net/qq_32115439/article/details/78848386

GitHub部落格: http://lioil.win/2017/12/19/Android-Alarm_Doze_Standby.html

Coding部落格: http://c.lioil.win/2017/12/19/Android-Alarm_Doze_Standby.html