[Android][AlarmManager]

1.AlarmManager作用

AlarmManager提供了訪問(wèn)系統(tǒng)鬧鐘的服務(wù)莫秆。它允許你安排你的應(yīng)用在未來(lái)某個(gè)時(shí)間點(diǎn)運(yùn)行。這就相當(dāng)于定時(shí)任務(wù)慨蛙。對(duì)于少于60s的定時(shí)任務(wù)梆掸,不推薦使用AlarmManager,可以使用更高效的的Handler來(lái)處理頻發(fā)的任務(wù)虎敦。

2.AlarmManager設(shè)置定時(shí)任務(wù)方法解析

1)set(int type, long triggerAtMillis, PendingIntent operation)

該方法用于設(shè)置一次性鬧鐘游岳。type表示鬧鐘類型。triggerAtMillis表示鬧鐘的觸發(fā)時(shí)間其徙。Operation表示要執(zhí)行的操作胚迫。如果已經(jīng)存在相同的鬧鈴安排要執(zhí)行的Intent(也就是PendingIntent)也相同,那么前一個(gè)被設(shè)置的鬧鈴會(huì)被取消唾那。如果定義鬧鈴的觸發(fā)時(shí)間在過(guò)去访锻,那么鬧鈴會(huì)立即被觸發(fā)。如果已經(jīng)有了這個(gè)意圖的(通過(guò)Intent.filterEquals定義兩個(gè)意圖的相等性)闹获,那么舊的意圖將被刪除并替換為當(dāng)前設(shè)置的意圖期犬。
從API 19開始,鬧鈴的觸發(fā)時(shí)間已經(jīng)不精確了避诽,鬧鈴不會(huì)在設(shè)定的觸發(fā)時(shí)間之前被觸發(fā)龟虎,但是有可能會(huì)出現(xiàn)鬧鈴延遲觸發(fā)的現(xiàn)象。這是為了節(jié)能省電(減少系統(tǒng)喚醒和電池使用)沙庐。一般情況下鲤妥,如果設(shè)置的觸發(fā)時(shí)間是在將來(lái)佳吞,而且時(shí)間不久,鬧鈴一般是不會(huì)被延遲棉安。但只要鬧鈴設(shè)置的觸發(fā)時(shí)間比較長(zhǎng)就很有可能會(huì)被推遲觸發(fā)底扳。
在新的批處理策略下,如果應(yīng)用程序設(shè)置了多個(gè)鬧鈴贡耽,那么這些鬧鈴的實(shí)際觸發(fā)順序可能與它們所請(qǐng)求觸發(fā)時(shí)間的順序不匹配衷模。如果你的應(yīng)用程序有強(qiáng)烈的排序需求,那么你可以使用setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent)來(lái)實(shí)現(xiàn)蒲赂。

2)setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)

該方法用于設(shè)置重復(fù)鬧鐘阱冶。type表示鬧鐘類型,triggerAtMillis表示鬧鐘的觸發(fā)時(shí)間凳宙。intervalMillis表示鬧鐘兩次執(zhí)行的間隔時(shí)間熙揍,operation表示鬧鐘執(zhí)行的操作。
當(dāng)調(diào)用這個(gè)方法設(shè)置鬧鈴的時(shí)候氏涩,這個(gè)鬧鈴會(huì)按照設(shè)定的時(shí)間間隔不斷觸發(fā)届囚,直到用cancel顯式地取消這個(gè)鬧鈴。
如果定義的觸發(fā)時(shí)間在過(guò)去是尖,則會(huì)立即觸發(fā)警報(bào)意系,它會(huì)根據(jù)觸發(fā)時(shí)間相對(duì)于重復(fù)間隔的時(shí)間間隔,觸發(fā)鬧鈴計(jì)數(shù)饺汹。
如果一個(gè)鬧鈴被延遲了(例如蛔添,對(duì)于非喚醒類型的鬧鈴遇到系統(tǒng)休眠的時(shí)候),一個(gè)已經(jīng)過(guò)時(shí)的的鬧鈴會(huì)盡快被觸發(fā)兜辞。在此之后迎瞧,未來(lái)的鬧鈴將按原計(jì)劃被觸發(fā);他們不會(huì)隨著時(shí)間的推移而改變。例如逸吵,如果你在每小時(shí)都設(shè)置了一個(gè)重復(fù)的鬧鐘凶硅,但是手機(jī)在7:45到8:45之前已經(jīng)就已經(jīng)休眠了,一旦手機(jī)喚醒扫皱,就會(huì)發(fā)出警報(bào)足绅,然后下一個(gè)鬧鐘將在9點(diǎn)被觸發(fā)。
在API 19中韩脑,所有的重復(fù)鬧鈴都是不準(zhǔn)確的氢妈。如果你的應(yīng)用程序需要精確的觸發(fā)時(shí)間,那么它必須使用一次性的警報(bào)段多,當(dāng)鬧鈴被觸發(fā)后重新再重新安排一個(gè)相同時(shí)間間隔的鬧鈴首量。

3) setInexactRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation)

該方法也用于設(shè)置重復(fù)鬧鐘。type表示鬧鐘類型,triggerAtMillis表示鬧鐘的觸發(fā)時(shí)間加缘。intervalMillis表示鬧鐘兩次執(zhí)行的間隔時(shí)間粥航,operation表示鬧鐘執(zhí)行的操作。這個(gè)方法和setRepeating差不多生百,但是它是不準(zhǔn)確的,它主要用于對(duì)觸發(fā)時(shí)間要求不嚴(yán)格的重復(fù)任務(wù)柄延。相對(duì)于setRepeating方法蚀浆,也更加節(jié)能。因?yàn)橄到y(tǒng)會(huì)將差不多的鬧鐘進(jìn)行合并搜吧,以避免在不必要地喚醒設(shè)備市俊。
在API 19中,所有的重復(fù)警報(bào)都是不準(zhǔn)確的滤奈。
你的鬧鈴的第一個(gè)觸發(fā)器將不會(huì)在請(qǐng)求的時(shí)間之前被觸發(fā)摆昧,但是在此之后可能不會(huì)出現(xiàn)一個(gè)完整的時(shí)間間隔。此外蜒程,盡管重復(fù)報(bào)警的總周期是按要求進(jìn)行的绅你,但兩次連續(xù)兩次的警報(bào)之間的間隔時(shí)間可能會(huì)有所不同。如果你的應(yīng)用程序要求時(shí)間間隔比較嚴(yán)格昭躺,那么可以使用一個(gè)適當(dāng)?shù)拇翱趤?lái)調(diào)用一個(gè)鬧鈴; setWindow(int, long, long, PendingIntent) 和 setExact(int, long, PendingIntent).

4) setWindow(int type, long windowStartMillis, long windowLengthMillis,

PendingIntent operation)
設(shè)置一個(gè)鬧鐘在給定的時(shí)間窗觸發(fā)忌锯。類似于set,該方法允許應(yīng)用程序精確地控制操作系統(tǒng)調(diào)整鬧鐘觸發(fā)時(shí)間的程度领炫。
這里的時(shí)間窗是什么意思偶垮?帶著疑問(wèn)到網(wǎng)絡(luò)上找了一下,貌似時(shí)間窗這個(gè)概念是股票領(lǐng)域一個(gè)叫江恩的人提出的帝洪,網(wǎng)上解釋說(shuō)時(shí)間窗口有兩個(gè)含義:
  一是指時(shí)間周期運(yùn)行到一定的階段時(shí)似舵,便會(huì)發(fā)生轉(zhuǎn)折;
  二是指在時(shí)間周期中的某一關(guān)鍵時(shí)間段,如果對(duì)特定事物施加影響或采取某種行動(dòng)葱峡,成功幾率將增加砚哗。
一開始我認(rèn)為這是一個(gè)時(shí)間區(qū)間的概念,也就是說(shuō)鬧鈴會(huì)在[windowStartMillis, windowLengthMillis]區(qū)間內(nèi)的某個(gè)時(shí)間觸發(fā)族沃。但是多次測(cè)試發(fā)現(xiàn)觸發(fā)時(shí)間會(huì)出現(xiàn)在區(qū)間之外频祝。所以我也弄不清楚windowStartMillis和windowLengthMillis的作用了,可以確定的是鬧鈴觸發(fā)時(shí)間肯定是在windowStartMillis之后的脆淹。有清楚的小伙伴麻煩說(shuō)一下常空。
type表示鬧鐘類型,windowStartMillis表示時(shí)間窗的開始點(diǎn)盖溺。windowLengthMillis表示時(shí)間窗的長(zhǎng)度漓糙,operation表示鬧鐘執(zhí)行的操作。
該方法還可用于在多個(gè)鬧鈴中實(shí)現(xiàn)嚴(yán)格的排序保證烘嘱,確保每個(gè)鬧鈴的請(qǐng)求不交叉昆禽。
當(dāng)不需要精確的觸發(fā)時(shí)蝗蛙,應(yīng)用程序應(yīng)該使用set(int,long,PendingIntent)方法。這將給操作系統(tǒng)最大的靈活性醉鳖,以最小化喚醒系統(tǒng)和電池使用捡硅。對(duì)于必須在精確指定的時(shí)間觸發(fā)鬧鈴,應(yīng)用程序可以使用setExact(int,long,PendingIntent)盗棵。
我們需要注意的是setWindow方法是在API>19后才能調(diào)用的壮韭。

5) setExact(int type, long triggerAtMillis, PendingIntent operation)

設(shè)置一個(gè)鬧鐘在給定的時(shí)間內(nèi)準(zhǔn)確的觸發(fā)。這種方法就像set(int, long, PendingIntent),但不允許操作系統(tǒng)調(diào)整觸發(fā)時(shí)間纹因。鬧鈴將盡可能接近給定的觸發(fā)時(shí)間點(diǎn)觸發(fā)喷屋。type表示鬧鐘類型,triggerAtMillis表示鬧鐘的觸發(fā)時(shí)間瞭恰。operation表示鬧鐘執(zhí)行的操作屯曹。
只有當(dāng)迫切需要在鬧鈴在準(zhǔn)確的時(shí)間內(nèi)觸發(fā)才調(diào)用這個(gè)方法。但是不鼓勵(lì)應(yīng)用程序調(diào)用準(zhǔn)確的鬧鈴,因?yàn)樗麄儨p少了操作系統(tǒng)的運(yùn)算能力和耗電惊畏。
這個(gè)方法是在API>19后才能調(diào)用的恶耽。

6)設(shè)置鬧鈴的方法中的type

AlarmManager.RTC,該狀態(tài)下鬧鐘使用絕對(duì)時(shí)間颜启,即當(dāng)前系統(tǒng)時(shí)間驳棱,不喚醒手機(jī)(也可能是其它設(shè)備)休眠;當(dāng)手機(jī)休眠時(shí)不觸發(fā)鬧鐘农曲。
AlarmManager.RTC_WAKEUP社搅,該狀態(tài)下鬧鐘使用絕對(duì)時(shí)間,即當(dāng)前系統(tǒng)時(shí)間乳规,當(dāng)鬧鐘發(fā)躰時(shí)喚醒休眠狀態(tài)的手機(jī)形葬;
AlarmManager.ELAPSED_REALTIME,該狀態(tài)下鬧鐘使用相對(duì)時(shí)間(相對(duì)于系統(tǒng)啟動(dòng)開始)暮的,不喚醒手機(jī)休眠笙以;當(dāng)手機(jī)休眠時(shí)不觸發(fā)鬧鐘。
AlarmManager.ELAPSED_REALTIME_WAKEUP冻辩,該狀態(tài)下鬧鐘使用相對(duì)時(shí)間(相對(duì)于系統(tǒng)啟動(dòng)開始)猖腕,當(dāng)鬧鐘觸發(fā)時(shí)喚醒休眠狀態(tài)的手機(jī);
RTC鬧鐘和ELAPSED_REALTIME最大的差別就是前者可以通過(guò)修改手機(jī)時(shí)間觸發(fā)鬧鐘事件恨闪,后者要通過(guò)真實(shí)時(shí)間的流逝倘感,即使在休眠狀態(tài),時(shí)間也會(huì)被計(jì)算咙咽。

7)其他

Android 6.0最大變化之一就是加入了新的電量管理模式:休眠模式老玛,當(dāng)設(shè)備一段時(shí)間不用的時(shí)候,當(dāng)屏幕關(guān)閉的時(shí)候,系統(tǒng)會(huì)自動(dòng)進(jìn)入休眠模式蜡豹。這樣所有的App都將進(jìn)入掛起模式麸粮,不能進(jìn)行接入網(wǎng)絡(luò)等一些操作。
當(dāng)然系統(tǒng)也會(huì)定期的退出休眠模式镜廉,來(lái)完成App延遲的工作弄诲,在這個(gè)空窗期(我暫且就這么叫),系統(tǒng)會(huì)運(yùn)行所有同步娇唯,工作威根,提醒等,并允許app接入網(wǎng)絡(luò)视乐。
當(dāng)過(guò)了空窗期后,系統(tǒng)會(huì)重新進(jìn)入休眠期敢茁,App也會(huì)隨著掛起狀態(tài)佑淀,隨著時(shí)間的推移,空窗期越來(lái)越少彰檬,是為了幫助沒有接入充電器的長(zhǎng)期閑置的設(shè)備減少電池消耗伸刃。
只要用戶喚醒設(shè)備,打開屏幕或者接入電源逢倍,系統(tǒng)會(huì)自動(dòng)退出休眠模式捧颅,所有的活動(dòng)都會(huì)恢復(fù)正常狀態(tài)。
下面是當(dāng)進(jìn)入休眠期時(shí)的約束:

  1. 延遲網(wǎng)絡(luò)請(qǐng)求较雕;
  2. 系統(tǒng)忽略喚醒鎖碉哑;
  3. 標(biāo)準(zhǔn)的鬧鐘提醒(包括setExat()和setWindow())會(huì)被延時(shí)到下一個(gè)空窗期;
    如果一定要在休眠期喚醒鬧鐘亮蒋,可以用setAndAllowWhileIdle()喚醒不精確鬧鐘或者setExactAndAllowWhileIdle()喚醒精確鬧鐘
    鬧鐘設(shè)置setAlarmClock()則繼續(xù)保持常態(tài)扣典,在喚醒這個(gè)鬧鐘前系統(tǒng)會(huì)退出休眠期一段時(shí)間;
  4. 禁用wifi scan慎玖;
  5. 不允許同步贮尖;
  6. 禁用JobScheduler ;
    休眠容易影響 AlarmManager alarms and timers manage趁怔,因?yàn)楫?dāng)系統(tǒng)進(jìn)入休眠狀態(tài)湿硝,鬧鐘在android5.1(API level 22)或者更低不會(huì)喚醒 ;
    為了幫助管理alarms,android 6.0(API level 23) 介紹了兩個(gè)方法: setAndAllowWhileIdle()和setExactAndAllowWhileIdle(). 這樣即使你再休眠期的時(shí)候 鬧鐘也會(huì)被喚醒润努;
    PS: 即使這兩種方法关斜,每個(gè)App每15分鐘喚醒次數(shù)也不能超過(guò)一次;
    有了休眠铺浇,自然會(huì)影響我們的后臺(tái)服務(wù)蚤吹,比如 推送,google 建議是用GMC( Google Cloud Messaging)。

3.代碼解析(關(guān)于使用AlarmManager實(shí)現(xiàn)定時(shí)任務(wù)的例子)

首先裁着,初始化一個(gè)鬧鈴

//這個(gè)方法我是在Acitivity中定義的繁涂,這里舉例設(shè)置鬧鈴用的是set方法
    private void initAlarmManager()
    {
        //創(chuàng)建Intent對(duì)象,action為ELITOR_CLOCK二驰,附加信息為字符串“點(diǎn)擊我了”  
        Intent intent = new Intent("ELITOR_CLOCK");  
        intent.putExtra("msg","點(diǎn)擊我了");
        
        //定義一個(gè)PendingIntent對(duì)象扔罪,PendingIntent.getBroadcast包含了sendBroadcast的動(dòng)作。  
        //PendingIntent不僅可以發(fā)給廣播桶雀,還可以是
        //getActivity(context, requestCode, intent, flags)
        //getActivities(context, requestCode, intents, flags)
        //getService(context, requestCode, intent, flags)
        //只需要AndroidMenifest.xml中注冊(cè)的組件里的意圖過(guò)濾器中添加對(duì)應(yīng)的action標(biāo)簽即可矿酵。
        //也就是發(fā)送了action 為"ELITOR_CLOCK"的intent   
        PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);
        //AlarmManager對(duì)象,注意這里并不是new一個(gè)對(duì)象,Alarmmanager為系統(tǒng)級(jí)服務(wù)  
        AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
        //設(shè)置鬧鐘從當(dāng)前時(shí)間開始矗积,每隔5s執(zhí)行一次PendingIntent對(duì)象pi全肮,注意第一個(gè)參數(shù)與第二個(gè)參數(shù)的關(guān)系  
        // 5秒后通過(guò)PendingIntent pi對(duì)象發(fā)送廣播  
        am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,5*1000,pi);
    }

然后,我們需要定義一個(gè)廣播用來(lái)處理鬧鈴被觸發(fā)后要處理的事務(wù)

public class MyReceiver extends BroadcastReceiver {
    private static final int NOTIFICATION_FLAG = 1;
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        LogUtil.init("TestAlarmManager", "alarmLog.txt");
        //這里獲取的是上面鬧鈴傳遞的值“點(diǎn)擊我了”
        String msg = intent.getStringExtra("msg");
        Log.i("lgy", "onclock......................" + msg);
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();

    }
}

定義了廣播之后別忘了注冊(cè)廣播

注冊(cè)廣播

4.源碼地址

http://download.csdn.net/download/lgywsdy/9995903

5.參考文章

https://plus.google.com/+AndroidDevelopers/posts/GdNrQciPwqo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末棘捣,一起剝皮案震驚了整個(gè)濱河市辜腺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乍恐,老刑警劉巖评疗,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異茵烈,居然都是意外死亡百匆,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門呜投,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)加匈,“玉大人,你說(shuō)我怎么就攤上這事仑荐【囟” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵释漆,是天一觀的道長(zhǎng)悲没。 經(jīng)常有香客問(wèn)我,道長(zhǎng)男图,這世上最難降的妖魔是什么示姿? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮逊笆,結(jié)果婚禮上栈戳,老公的妹妹穿的比我還像新娘。我一直安慰自己难裆,他們只是感情好子檀,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布镊掖。 她就那樣靜靜地躺著,像睡著了一般褂痰。 火紅的嫁衣襯著肌膚如雪亩进。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天缩歪,我揣著相機(jī)與錄音归薛,去河邊找鬼。 笑死匪蝙,一個(gè)胖子當(dāng)著我的面吹牛主籍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逛球,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼千元,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了颤绕?” 一聲冷哼從身側(cè)響起幸海,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屋厘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體月而,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡汗洒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了父款。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溢谤。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖憨攒,靈堂內(nèi)的尸體忽然破棺而出世杀,到底是詐尸還是另有隱情,我是刑警寧澤肝集,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布瞻坝,位于F島的核電站,受9級(jí)特大地震影響杏瞻,放射性物質(zhì)發(fā)生泄漏所刀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一捞挥、第九天 我趴在偏房一處隱蔽的房頂上張望浮创。 院中可真熱鬧,春花似錦砌函、人聲如沸斩披。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)垦沉。三九已至煌抒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乡话,已是汗流浹背摧玫。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绑青,地道東北人诬像。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像闸婴,于是被迫代替她去往敵國(guó)和親坏挠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容