Android為了確保應(yīng)用程序中關(guān)鍵代碼的正確執(zhí)行叽奥,提供了WakeLock的API舱痘,使得應(yīng)用程序有權(quán)限通過(guò)代碼阻止AP進(jìn)入休眠狀態(tài)椅棺。
Wake Lock是一種鎖的機(jī)制, 只要有人拿著這個(gè)鎖,系統(tǒng)就無(wú)法進(jìn)入休眠,可以被用戶(hù)態(tài)程序和內(nèi)核獲得. 這個(gè)鎖可以是有超時(shí)的或者是沒(méi)有超時(shí)的,超時(shí)的鎖會(huì)在時(shí)間過(guò)去以后自動(dòng)解鎖.
如果沒(méi)有鎖了或者超時(shí)了, 內(nèi)核就會(huì)啟動(dòng)休眠的那套機(jī)制來(lái)進(jìn)入休眠.
WakeLock阻止應(yīng)用處理器(ApplicationProcessor)掛起序宦,確保關(guān)鍵代碼的運(yùn)行滥玷,通過(guò)中斷喚起應(yīng)用處理器(ApplicationProcessor)辟癌,可以阻止屏幕變暗寒屯。所有的WakeLock被釋放后,系統(tǒng)會(huì)掛起
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運(yùn)轉(zhuǎn)黍少,屏幕和鍵盤(pán)燈有可能是關(guān)閉的寡夹。
SCREEN_DIM_WAKE_LOCK:保持CPU運(yùn)轉(zhuǎn),允許保持屏幕顯示但有可能是灰的厂置,允許關(guān)閉鍵盤(pán)燈
SCREEN_BRIGHT_WAKE_LOCK:保持CPU運(yùn)轉(zhuǎn)菩掏,保持屏幕高亮顯示,允許關(guān)閉鍵盤(pán)燈
FULL_WAKE_LOCK:保持CPU運(yùn)轉(zhuǎn)昵济,保持屏幕高亮顯示智绸,鍵盤(pán)燈也保持亮度
ACQUIRE_CAUSES_WAKEUP:不會(huì)喚醒設(shè)備,強(qiáng)制屏幕馬上高亮顯示访忿,鍵盤(pán)燈開(kāi)啟瞧栗。有一個(gè)例外,如果有notification彈出的話(huà)海铆,會(huì)喚醒設(shè)備迹恐。
ON_AFTER_RELEASE:WakeLock被釋放后,維持屏幕亮度一小段時(shí)間游添,減少WakeLock循環(huán)時(shí)的閃爍情況
如果申請(qǐng)了partialwakelock,那么即使按Power鍵,系統(tǒng)也不會(huì)進(jìn)Sleep,如Music播放時(shí)如果申請(qǐng)了其它的wakelocks,按Power鍵,系統(tǒng)還是會(huì)進(jìn)Sleep
但如果不領(lǐng)會(huì)Android設(shè)計(jì)者的意圖而濫用Wake Lock
API系草,為了自身程序在后臺(tái)的正常工作而長(zhǎng)時(shí)間阻止AP進(jìn)入休眠狀態(tài),就會(huì)成為待機(jī)電池殺手唆涝。
PS:PowerManager.WakeLock 有加鎖和解鎖兩種狀態(tài)找都,加鎖的方式有兩種,一種是永久的鎖住廊酣,這樣的鎖除非顯式的放開(kāi)能耻,是不會(huì)解鎖的,所以這種鎖用起來(lái)要非常的小心亡驰。第二種鎖是超時(shí)鎖晓猛,這種鎖會(huì)在鎖住后一段時(shí)間解鎖。
在創(chuàng)建了 PowerManager.WakeLock 后凡辱,有兩種機(jī)制戒职,第一種是不計(jì)數(shù)鎖機(jī)制,另一種是計(jì)數(shù)鎖機(jī)制透乾『樵铮可以通過(guò) setReferenceCounted(boolean value) 來(lái)指定磕秤,一般默認(rèn)為計(jì)數(shù)機(jī)制。這兩種機(jī)制的區(qū)別在于捧韵,前者無(wú)論 acquire() 了多少次市咆,只要通過(guò)一次 release()即可解鎖。而后者正真解鎖是在( --count == 0 )的時(shí)候再来,同樣當(dāng) (count == 0) 的時(shí)候才會(huì)去申請(qǐng)加鎖蒙兰,其他情況 isHeld 狀態(tài)是不會(huì)改變的。所以 PowerManager.WakeLock 的計(jì)數(shù)機(jī)制并不是正真意義上的對(duì)每次請(qǐng)求進(jìn)行申請(qǐng)/釋放每一把鎖芒篷,它只是對(duì)同一把鎖被申請(qǐng)/釋放的次數(shù)進(jìn)行了統(tǒng)計(jì)再正真意義上的去操作搜变。一下進(jìn)行了永久鎖的測(cè)試: 從測(cè)試我們可以看到使用計(jì)數(shù)和計(jì)數(shù)鎖的區(qū)別。
AlarmManager
AlarmManage有一個(gè)AlarmManagerService,該服務(wù)程序主要維護(hù)app注冊(cè)下來(lái)的各類(lèi)Alarm,并且一直監(jiān)聽(tīng)Alarm設(shè)備梭伐,一旦有Alarm觸發(fā)痹雅,或者是Alarm事件發(fā)生,AlarmManagerService就會(huì)遍歷Alarm列表糊识,找到相應(yīng)的注冊(cè)Alarm并發(fā)出廣播
AlarmManager會(huì)維持一個(gè)cpu的wakelock。這樣能保證電話(huà)休眠時(shí)摔蓝,也能處理alarm的廣播赂苗。一旦alarmreceiver的onReceive()方法執(zhí)行完,wakelock會(huì)迅速被釋放贮尉。如果在receiver中開(kāi)啟一個(gè)service拌滋,有可能service還沒(méi)啟動(dòng),wakelock已經(jīng)被釋放了猜谚。所以此時(shí)要實(shí)現(xiàn)單獨(dú)的wakelock策略败砂。
有4種Alarm類(lèi)型:
RTC_WAKEUP
在指定的時(shí)刻(設(shè)置Alarm的時(shí)候),喚醒設(shè)備來(lái)觸發(fā)Intent魏铅。
RTC
在一個(gè)顯式的時(shí)間觸發(fā)Intent昌犹,但不喚醒設(shè)備。
ELAPSED_REALTIME
從設(shè)備啟動(dòng)后览芳,如果流逝的時(shí)間達(dá)到總時(shí)間斜姥,那么觸發(fā)Intent,但不喚醒設(shè)備沧竟。流逝的時(shí)間包括設(shè)備睡眠的任何時(shí)間铸敏。注意一點(diǎn)的是,時(shí)間流逝的計(jì)算點(diǎn)是自從它最后一次啟動(dòng)算起悟泵。
ELAPSED_REALTIME_WAKEUP
從設(shè)備啟動(dòng)后杈笔,達(dá)到流逝的總時(shí)間后,如果需要將喚醒設(shè)備并觸發(fā)Intent糕非。