Android闹钟 AlarmManager的使用
轉(zhuǎn)自:http://www.cnblogs.com/mengdd/p/3819806.html
AlarmManager介紹
AlarmManager這個(gè)類(lèi)提供對(duì)系統(tǒng)鬧鐘服務(wù)的訪問(wèn)接口。
你可以為你的應(yīng)用設(shè)定一個(gè)在未來(lái)某個(gè)時(shí)間喚醒的功能。
當(dāng)鬧鐘響起,實(shí)際上是系統(tǒng)發(fā)出了為這個(gè)鬧鐘注冊(cè)的廣播,會(huì)自動(dòng)開(kāi)啟目標(biāo)應(yīng)用。
注冊(cè)的鬧鐘在設(shè)備睡眠的時(shí)候仍然會(huì)保留,可以選擇性地設(shè)置是否喚醒設(shè)備,但是當(dāng)設(shè)備關(guān)機(jī)和重啟后,鬧鐘將會(huì)被清除。
?
在alarm的receiver的onReceive()方法被執(zhí)行的時(shí)候,Alarm Manager持有一個(gè)CPU喚醒鎖,這樣就保證了設(shè)備在處理完廣播之前不會(huì)sleep。
一旦onReceive()方法返回,Alarm Manager就會(huì)釋放這個(gè)鎖,表明一些情況下可能onReceive()方法一執(zhí)行完設(shè)備就會(huì)sleep。
如果你的alarm receiver中調(diào)用了Context.startService(),那么很可能service還沒(méi)起來(lái)設(shè)備就sleep了。
為了阻止這種情況,你的BroadcastReceiver和Service需要實(shí)現(xiàn)不同的喚醒鎖機(jī)制,來(lái)確保設(shè)備持續(xù)運(yùn)行到service可用為止。
?
注意:Alarm Manager主要是用來(lái)在特定時(shí)刻運(yùn)行你的代碼,即便是你的應(yīng)用在那個(gè)特定時(shí)刻沒(méi)有跑的情況。
對(duì)于常規(guī)的計(jì)時(shí)操作(ticks, timeouts, etc),使用Handler處理更加方便和有效率。
?
另:從API 19開(kāi)始,alarm的機(jī)制都是非準(zhǔn)確傳遞,操作系統(tǒng)將會(huì)轉(zhuǎn)換鬧鐘,來(lái)最小化喚醒和電池使用。
有一些新的API會(huì)支持嚴(yán)格準(zhǔn)確的傳遞,見(jiàn)?setWindow(int, long, long, PendingIntent)和setExact(int, long, PendingIntent)。
targetSdkVersion在API 19之前應(yīng)用仍將繼續(xù)使用以前的行為,所有的鬧鐘在要求準(zhǔn)確傳遞的情況下都會(huì)準(zhǔn)確傳遞。
?
鬧鐘Demo
Android Api demos中就有關(guān)于鬧鐘使用的Demo:
com.example.android.apis.app.AlarmController
其中設(shè)定了兩種鬧鐘,一種是一次性的,一種是重復(fù)的。
Manifest中的聲明,process屬性
自定義的receiver,在manifest中聲明如下:
<receiverandroid:name=".OneShotAlarm"android:process=":remote" /><receiverandroid:name=".RepeatingAlarm"android:process=":remote" />?
Demo中兩個(gè)Receiver的onReceive方法中顯示了各自的Toast提示,所以不再列出。
在此討論一下process屬性,它規(guī)定了組件(activity, service, receiver等)所在的進(jìn)程。
通常情況下,沒(méi)有指定這個(gè)屬性,一個(gè)應(yīng)用所有的組件都運(yùn)行在應(yīng)用的默認(rèn)進(jìn)程中,進(jìn)程的名字和應(yīng)用的包名一致。
比如manifest的package="com.example.helloalarm",則默認(rèn)進(jìn)程名就是com.example.helloalarm。
<application>元素的process屬性可以為全部的組件設(shè)置一個(gè)不同的默認(rèn)進(jìn)程。
組件可以override這個(gè)默認(rèn)的進(jìn)程設(shè)置,這樣你的應(yīng)用就可以是多進(jìn)程的。
?
如果你的process屬性以一個(gè)冒號(hào)開(kāi)頭,進(jìn)程名會(huì)在原來(lái)的進(jìn)程名之后附加冒號(hào)之后的字符串作為新的進(jìn)程名。當(dāng)組件需要時(shí),會(huì)自動(dòng)創(chuàng)建這個(gè)進(jìn)程。這個(gè)進(jìn)程是應(yīng)用私有的進(jìn)程。
如果process屬性以小寫(xiě)字母開(kāi)頭,將會(huì)直接以屬性中的這個(gè)名字作為進(jìn)程名,這是一個(gè)全局進(jìn)程,這樣的進(jìn)程可以被多個(gè)不同應(yīng)用中的組件共享。
?
一次性鬧鐘
// When the alarm goes off, we want to broadcast an Intent to our// BroadcastReceiver. Here we make an Intent with an explicit class// name to have our own receiver (which has been published in// AndroidManifest.xml) instantiated and called, and then create an// IntentSender to have the intent executed as a broadcast.Intent intent = new Intent(AlarmController.this, OneShotAlarm.class);PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this, 0, intent, 0);// We want the alarm to go off 10 seconds from now.Calendar calendar = Calendar.getInstance();calendar.setTimeInMillis(System.currentTimeMillis());calendar.add(Calendar.SECOND, 10);// Schedule the alarm!AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);?
重復(fù)鬧鐘
鬧鐘設(shè)置:
// When the alarm goes off, we want to broadcast an Intent to our// BroadcastReceiver. Here we make an Intent with an explicit class// name to have our own receiver (which has been published in// AndroidManifest.xml) instantiated and called, and then create an// IntentSender to have the intent executed as a broadcast.// Note that unlike above, this IntentSender is configured to// allow itself to be sent multiple times.Intent intent = new Intent(AlarmController.this,RepeatingAlarm.class);PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this, 0, intent, 0);// We want the alarm to go off 10 seconds from now.Calendar calendar = Calendar.getInstance();calendar.setTimeInMillis(System.currentTimeMillis());calendar.add(Calendar.SECOND, 10);// Schedule the alarm!AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);am.setRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(), 10 * 1000, sender);?
鬧鐘取消:
// Create the same intent, and thus a matching IntentSender, for// the one that was scheduled.Intent intent = new Intent(AlarmController.this,RepeatingAlarm.class);PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this, 0, intent, 0);// And cancel the alarm.AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);am.cancel(sender);?
AlarmManager說(shuō)明
AlarmManager這個(gè)類(lèi)提供對(duì)系統(tǒng)鬧鐘服務(wù)的訪問(wèn)接口。
對(duì)它的獲取是通過(guò)系統(tǒng)服務(wù):
? Context.getSystemService(Context.ALARM_SERVICE)。
?
相關(guān)方法說(shuō)明:
cancel(PendingIntent?operation)方法將會(huì)取消Intent匹配的任何鬧鐘。
關(guān)于Intent的匹配,查看filterEquals(Intent?other)方法的說(shuō)明可知,兩個(gè)Intent從intent resolution(filtering)(Intent決議或過(guò)濾)的角度來(lái)看是一致的,即認(rèn)為兩個(gè)Intent相等。即是說(shuō),Intent的action,data,type,class,categories是相同的,其他的數(shù)據(jù)都不在比較范圍之內(nèi)。
?
set(int type, long triggerAtMillis,?PendingIntent?operation)方法將會(huì)設(shè)置一個(gè)鬧鐘。
注意:對(duì)于計(jì)時(shí)操作,可能使用Handler更加有效率和簡(jiǎn)單。
設(shè)置鬧鐘的時(shí)候注意:
1.如果聲明的triggerAtMillis是一個(gè)過(guò)去的時(shí)間,鬧鐘將會(huì)立即被觸發(fā)。
2.如果已經(jīng)有一個(gè)相同intent的鬧鐘被設(shè)置過(guò)了,那么前一個(gè)鬧鐘將會(huì)取消,被新設(shè)置的鬧鐘所代替。
?
注意這里說(shuō)的intent相同指的都是Intent在?filterEquals(Intent)的定義下匹配。
鬧鐘是一個(gè)廣播,接收器需要自己定義和注冊(cè),注冊(cè)使用動(dòng)態(tài)注冊(cè)(?registerReceiver(BroadcastReceiver, IntentFilter)?)或者靜態(tài)注冊(cè)(<receiver> tag in an AndroidManifest.xml file)都可以。?
setRepeating(int type, long triggerAtMillis, long intervalMillis,?PendingIntent?operation)方法將會(huì)設(shè)置一個(gè)重復(fù)性的鬧鐘。
比set方法多了一個(gè)間隔參數(shù)。
?
type的類(lèi)型是四種:
ELAPSED_REALTIME,?ELAPSED_REALTIME_WAKEUP,?RTC,?RTC_WAKEUP.
區(qū)分的是時(shí)間標(biāo)準(zhǔn)和是否在睡眠狀態(tài)下喚醒設(shè)備。
具體查看官方文檔吧不再詳細(xì)解釋啦。
?
實(shí)例
比如要設(shè)置一個(gè)每晚21:30喚醒的重復(fù)鬧鐘:
private static final int INTERVAL = 1000 * 60 * 60 * 24;// 24h//... Intent intent = new Intent(context, RequestAlarmReceiver.class);PendingIntent sender = PendingIntent.getBroadcast(context,REQUEST_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT);// Schedule the alarm!AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);Calendar calendar = Calendar.getInstance();calendar.set(Calendar.HOUR_OF_DAY, 21);calendar.set(Calendar.MINUTE, 30);calendar.set(Calendar.SECOND, 10);calendar.set(Calendar.MILLISECOND, 0);am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),INTERVAL, sender);?
?
參考資料
AlarmManager:
http://developer.android.com/reference/android/app/AlarmManager.html
?
鬧鐘Demo解析:
http://blog.csdn.net/mapdigit/article/details/7644134
?
總結(jié)
以上是生活随笔為你收集整理的Android闹钟 AlarmManager的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: Android之用PopupWindow
 - 下一篇: Androi App缓存管理