應用程序耗電的實質,是所啟用的硬件在消耗電量。
手機的耗電單元
CPU: 應用處理器(AP)和基帶處理器(BB或BP)
GPU(圖形處理單元)
外設:wifi,BT, GPS,LCD等
AP是ARM架構的處理器,用於運行Android系統;
BP用於運行實時操作系統(RTOS),通訊協議棧運行於BP的RTOS之上.
耗電量對比:
BP非通話時間的能耗基本上在5mA左右; 而AP只要處於非休眠狀態,能耗至少在50mA以上,執行圖形運算時會更高, 另外 LCD, WIFI等更高。
一般手機待機時,AP、LCD、WIFI均進入休眠狀態,這時Android中應用程序的代碼也會停止執行,只會有基帶處理器(BP)的耗電。
為什么微信比短信耗電嚴重很多呢? 答案就是短信使用BP耗電小, 而微信使用AP耗電大.
WakeLock機制:
Android為了確保應用程序中關鍵代碼的正確執行,提供了Wake Lock的API,使得應用程序有權限通過代碼阻止AP進入休眠狀態。
WakeLock阻止應用處理器(AP)掛起,確保關鍵代碼的運行,通過中斷喚起應用處理器(AP),可以阻止屏幕變暗。所有的WakeLock被釋放后,系統會掛起。
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
WakeLock sCpuWakeLock = pm.newWakeLock(
PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP,"okTag");
if (sCpuWakeLock!= null) {
sCpuWakeLock.release();
sCpuWakeLock = null;
}
PARTIAL_WAKE_LOCK:保持CPU 運轉,屏幕和鍵盤燈有可能是關閉的。
SCREEN_DIM_WAKE_LOCK:保持CPU 運轉,允許保持屏幕顯示但有可能是灰的,允許關閉鍵盤燈
SCREEN_BRIGHT_WAKE_LOCK:保持CPU 運轉,保持屏幕高亮顯示,允許關閉鍵盤燈
FULL_WAKE_LOCK:保持CPU 運轉,保持屏幕高亮顯示,鍵盤燈也保持亮度
ACQUIRE_CAUSES_WAKEUP:不會喚醒設備,強制屏幕馬上高亮顯示,鍵盤燈開啟。有一個例外,如果有notification彈出的話,會喚醒設備。
ON_AFTER_RELEASE:WakeLock 被釋放后,維持屏幕亮度一小段時間,減少WakeLock 循環時的閃爍情況
如果申請了partial wakelock,那么即使按Power鍵,系統也不會進Sleep,如Music播放時; 如果申請了其它的wakelocks,按Power鍵,系統還是會進Sleep.(參見api文檔)
但如果不領會Android設計者的意圖而濫用Wake Lock API,為了自身程序在后台的正常工作而長時間阻止AP進入休眠狀態,就會成為待機電池殺手。
AlarmManager
AlarmManage有一個AlarmManagerService,該服務程序主要維護app注冊下來的各類Alarm, 並且一直監聽Alarm設備, 一旦有Alarm觸發,或者是Alarm事件發生,AlarmManagerService就會遍歷Alarm列表,找到相應的注冊Alarm並發出廣播. 首先,Alarm是基於RTC實時時鍾計時, 而不是ap計時; 其次, Alarm會維持一個CPU的wake lock, 確保Alarm廣播能被處理.
AlarmManager在Alarm指定的Receiver的onReceive()方法執行期間持有一個CPU喚醒鎖(參見:AlarmManagerService#AlarmThread申請的wakelock), 這樣能保證電話休眠時也能處理Alarm發出的PendingIntent指定的廣播。一旦alarm receiver的onReceive() 方法執行完,wake lock會迅速被釋放。如果在receiver中開啟一個service,有可能service還沒啟動,wake lock已經被釋放了, 所以此時要實現單獨的wake lock策略。
有4種Alarm類型:
1)RTC_WAKEUP
在指定的時刻(設置Alarm的時候),喚醒設備來觸發Intent。
2)RTC
在一個顯式的時間觸發Intent,但不喚醒設備。
3)ELAPSED_REALTIME
從設備啟動后,如果流逝的時間達到總時間,那么觸發Intent,但不喚醒設備。流逝的時間包括設備睡眠的任何時間。注意一點的是,時間流逝的計算點是自從它最后一次啟動算起。
4)ELAPSED_REALTIME_WAKEUP
從設備啟動后,達到流逝的總時間后,如果需要將喚醒設備並觸發Intent。