初探AlarmManager:使用

Android鬧鐘服務(wù)

AlarmManager是Android系統(tǒng)提供的一種執(zhí)行定時(shí)任務(wù)的手段播急,一般適用于長時(shí)間或者需要喚醒cpu保證準(zhǔn)時(shí)的定時(shí)任務(wù),提供喚醒和非喚醒, 重復(fù)和一次性等模式。系統(tǒng)源碼中的鬧鐘app就是基于它隘竭。設(shè)備關(guān)閉或是重啟的時(shí)候會(huì)被清除。

使用方式

  1. 獲取AlarmManager實(shí)例
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
  1. 構(gòu)造一個(gè)Intent
Intent intent = new Intent(context, targetClass.class);
//intetn.setAction(action)...
  1. 構(gòu)造一個(gè)PendingIntent
PendingIntent PendingIntent = PendingIntent.getXXX(context, requestCode, intent, flag);

PendingIntent的getXXX方法名根據(jù)targetClass的類型替換, targetClass是除了content provider的其他組件讼渊。

大致解釋一下PendingIntent动看。它是對(duì)Intent的進(jìn)一步封裝,能夠完成更多的操作爪幻。它通過一系列g(shù)etXXX得到菱皆,其中有兩個(gè)參數(shù)比較重要:requestCode和flag。

RequestCode

有時(shí)Notification或AlarmManager會(huì)設(shè)置多個(gè)PendingIntent挨稿,PendingIntent通過requestCode區(qū)分不同仇轻,當(dāng)通過它同時(shí)設(shè)置多個(gè)操作時(shí)需要注意設(shè)置不同的requestCode,否則后設(shè)置的會(huì)把先設(shè)置的覆蓋掉叶组。

Flag

FLAG_CANCEL_CURRENT:如果當(dāng)前系統(tǒng)中已經(jīng)存在一個(gè)相同的PendingIntent對(duì)象拯田,那么就將先將已有的PendingIntent取消,然后重新生成一個(gè)PendingIntent對(duì)象。

FLAG_NO_CREATE:如果當(dāng)前系統(tǒng)中不存在相同的PendingIntent對(duì)象,系統(tǒng)將不會(huì)創(chuàng)建該P(yáng)endingIntent對(duì)象而是直接返回null赦抖。

FLAG_ONE_SHOT:該P(yáng)endingIntent只作用一次骏全。在該P(yáng)endingIntent對(duì)象通過send()方法觸發(fā)過后,PendingIntent將自動(dòng)調(diào)用cancel()進(jìn)行銷毀,那么如果你再調(diào)用send()方法的話,系統(tǒng)將會(huì)返回一個(gè)SendIntentException。

FLAG_UPDATE_CURRENT:如果系統(tǒng)中有一個(gè)和你描述的PendingIntent對(duì)等的PendingInent窃爷,那么系統(tǒng)將使用該P(yáng)endingIntent對(duì)象,但是會(huì)使用新的Intent來更新之前PendingIntent中的Intent對(duì)象數(shù)據(jù)姓蜂,例如更新Intent中的Extras按厘。

  1. 調(diào)用alarmManager的set方法
alarmManager.set(type, triggerAtMillis, pendingIntent);
alarmManager.setExact(type, triggerAtMillis, pendingIntent);
alarmManager.setWindow(type, startTime, lengthTime, pendingIntent);
alarmManager.setRepeating(type, triggerAtMillis, interval, pendingIntent);
alarmManager.setInExactRepeating(type, triggerAtMillis, interval, pendingIntent);
alarmManager.setAndAllowWhileIdle(type, triggerAtMillis, pendingIntent);
alarmManager.setExactAndAllowWhileIdle(type, triggerAtMillis, pendingIntent);
...

先解釋一下type參數(shù)

Type

public static final int RTC_WAKEUP = 0;// 表示鬧鐘在睡眠狀態(tài)下喚醒系統(tǒng)并執(zhí)行提示功能,絕對(duì)時(shí)間钱慢。
public static final int RTC = 1;// 睡眠狀態(tài)下不可用逮京,絕對(duì)時(shí)間。
public static final int ELAPSED_REALTIME_WAKEUP = 2;// 睡眠狀態(tài)下可用束莫,相對(duì)時(shí)間懒棉。
public static final int ELAPSED_REALTIME = 3;// 睡眠狀態(tài)下不可用,相對(duì)時(shí)間览绿。
POWER_OFF_WAKEUP策严,即使在關(guān)機(jī)后還能提醒,但是Android4.0以后就沒有了

不同鬧鐘類型對(duì)應(yīng)的任務(wù)首次時(shí)間的獲取方法:若為ELAPSED_REALTIME_WAKEUP饿敲,那么當(dāng)前時(shí)間就為 SystemClock.elapsedRealtime()妻导;若為RTC_WAKEUP,那么當(dāng)前時(shí)間就為System.currentTimeMillis()。

  1. 取消鬧鐘
alarmManager.cancel(PendingIntent operation);
alarmManager.cancel(AlarmManager.OnAlarmListener listener);
  1. 取得下一次鬧鐘
alarmManager.getNextAlarmClock();

Set方法

單次鬧鐘

1.set

set(type, triggerAtMillis, pendingIntent);
set(int type, long triggerAtMillis, String tag, AlarmManager.OnAlarmListener listener, Handler targetHandler)

第二個(gè)方法是第一個(gè)方法的變體倔韭,區(qū)別就是從觸發(fā)pendingintent變成了觸發(fā)listener回調(diào)暑脆,但和pendingintent一樣,只能和一個(gè)alarm綁定狐肢。后面的handler決定了在哪個(gè)handler中執(zhí)行回調(diào),填null則在主線程回調(diào)沥曹。
2.setExact

setExact(type, triggerAtMillis, pendingIntent);
setExact(int type, long triggerAtMillis, String tag, AlarmManager.OnAlarmListener listener, Handler targetHandler)

3.setWindow

setWindow(type, startTime, lengthTime, pendingIntent);
setWindow(int type, long windowStartMillis, long windowLengthMillis, String tag, AlarmManager.OnAlarmListener listener, Handler targetHandler)

4.setAndAllowWhileIdle

setAndAllowWhileIdle(type, triggerAtMillis, pendingIntent);
setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation)

5.setAlarmClock

setAlarmClock(AlarmClockInfo, pendingIntent);

set方法提供設(shè)置一次性的鬧鐘份名,但隨著Android系統(tǒng)的完善,考慮到功耗等等因素妓美,需要更加精細(xì)地控制鬧鐘僵腺。因此提供了一些其他情況下的set方法『埃看下官方文檔的描述:

Note: Beginning with API 19 (Build.VERSION_CODES.KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, android.app.PendingIntent) and setExact(int, long, android.app.PendingIntent).

在Android api19之前辰如,set方法是精準(zhǔn)的,但在19之后贵试,為了降低頻繁喚醒cpu造成的電量浪費(fèi)琉兜,系統(tǒng)會(huì)自動(dòng)將幾個(gè)alarm放在一起觸發(fā),set方法自然也就無法保證準(zhǔn)確性毙玻。

因此Android又提供了setExact和setWindow來保證準(zhǔn)確性豌蟋。setExact保證精準(zhǔn)觸發(fā),setWindow保證在設(shè)置的時(shí)間段內(nèi)一定觸發(fā)桑滩。
然而在Android api23開始梧疲,Android加入了低電耗模式和應(yīng)用待機(jī)模式。其中低電耗模式明確指出在該模式下setExact和setWindow都會(huì)延遲執(zhí)行运准。但Android也給出了解決辦法:

標(biāo)準(zhǔn) AlarmManager 鬧鐘(包括 setExact() 和 setWindow())推遲到下一個(gè)維護(hù)期幌氮。
如果您需要設(shè)置在設(shè)備處于低電耗模式時(shí)觸發(fā)的鬧鐘,請(qǐng)使用 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()胁澳。
使用 setAlarmClock() 設(shè)置的鬧鐘將繼續(xù)正常觸發(fā)该互,系統(tǒng)會(huì)在這些鬧鐘觸發(fā)之前不久退出低電耗模式。

正如文檔所述听哭,setAndAllowWhileIdle和setExactAndAllowWhileIdle可以在低電耗下觸發(fā)慢洋,或者使用setAlarmClock。
setAlarmClock和setAndAllowWhileIdle基本一致陆盘,都可以在低電耗模式下喚醒普筹,持有mTriggerTime和mShowIntent(pendingIntent)兩個(gè)成員變量,是對(duì)鬧鐘事件的一個(gè)封裝隘马,getNextAlarmClock返回的就是一個(gè)AlarmClockInfo太防。

重復(fù)鬧鐘

1.setRepeating

alarmManager.setRepeating(type, triggerAtMillis, interval, pendingIntent);

2.setInExactRepeating

alarmManager.setInExactRepeating(type, triggerAtMillis, interval, pendingIntent);

這兩個(gè)方法可以重復(fù)執(zhí)行設(shè)定的pendingIntent。區(qū)別同上。

注意事項(xiàng)

7.1系統(tǒng)PendingIntent包裝的Intent不能直接設(shè)置Parcable對(duì)象蜒车,但可以放到bundle中讳嘱。經(jīng)查閱好像是6.0以上會(huì)出現(xiàn),需要注意酿愧。

Further

http://www.reibang.com/p/767412bf2af4
https://cloud.tencent.com/developer/article/1035539
https://www.cnblogs.com/leipDao/p/8203684.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沥潭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嬉挡,更是在濱河造成了極大的恐慌钝鸽,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庞钢,死亡現(xiàn)場離奇詭異拔恰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)基括,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門颜懊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人风皿,你說我怎么就攤上這事河爹。” “怎么了揪阶?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵昌抠,是天一觀的道長。 經(jīng)常有香客問我鲁僚,道長炊苫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任冰沙,我火速辦了婚禮侨艾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拓挥。我一直安慰自己唠梨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布侥啤。 她就那樣靜靜地躺著当叭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盖灸。 梳的紋絲不亂的頭發(fā)上蚁鳖,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音赁炎,去河邊找鬼醉箕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的讥裤。 我是一名探鬼主播放棒,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼己英!你這毒婦竟也來了间螟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤损肛,失蹤者是張志新(化名)和其女友劉穎寒亥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荧关,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年褂傀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了忍啤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仙辟,死狀恐怖同波,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叠国,我是刑警寧澤未檩,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站粟焊,受9級(jí)特大地震影響冤狡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜项棠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一悲雳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧香追,春花似錦合瓢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至峭咒,卻和暖如春税弃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讹语。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工钙皮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓短条,卻偏偏與公主長得像导匣,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子茸时,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

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