Android鬧鐘 AlarmManager的使用
Android鬧鐘 AlarmManager的使用
AlarmManager介紹
AlarmManager這個類提供對系統鬧鐘服務的訪問介面。
你可以為你的應用設定一個在未來某個時間喚醒的功能。
當鬧鐘響起,實際上是系統發出了為這個鬧鐘註冊的廣播,會自動開啟目標應用。
註冊的鬧鐘在裝置睡眠的時候仍然會保留,可以選擇性地設定是否喚醒裝置,但是當裝置關機和重啟後,鬧鐘將會被清除。
在alarm的receiver的onReceive()
一旦onReceive()方法返回,Alarm Manager就會釋放這個鎖,表明一些情況下可能onReceive()方法一執行完裝置就會sleep。
如果你的alarm receiver中呼叫了Context.startService(),那麼很可能service還沒起來裝置就sleep了。
為了阻止這種情況,你的BroadcastReceiver和Service需要實現不同的喚醒鎖機制,來確保裝置持續執行到service可用為止。
注意:Alarm Manager主要是用來在特定時刻執行你的程式碼,即便是你的應用在那個特定時刻沒有跑的情況。
對於常規的計時操作(ticks, timeouts, etc),使用Handler處理更加方便和有效率。
另:從API 19開始,alarm的機制都是非準確傳遞,作業系統將會轉換鬧鐘,來最小化喚醒和電池使用。
有一些新的API會支援嚴格準確的傳遞,見 setWindow(int, long, long, PendingIntent)和setExact(int, long, PendingIntent)。
targetSdkVersion在API 19之前應用仍將繼續使用以前的行為
鬧鐘Demo
Android Api demos中就有關於鬧鐘使用的Demo:
com.example.android.apis.app.AlarmController
其中設定了兩種鬧鐘,一種是一次性的,一種是重複的。
Manifest中的宣告,process屬性
自定義的receiver,在manifest中宣告如下:
<receiver android:name=".OneShotAlarm" android:process=":remote" /> <receiver android:name=".RepeatingAlarm" android:process=":remote" />
Demo中兩個Receiver的onReceive方法中顯示了各自的Toast提示,所以不再列出。
在此討論一下process屬性,它規定了元件(activity, service, receiver等)所在的程序。
通常情況下,沒有指定這個屬性,一個應用所有的元件都執行在應用的預設程序中,程序的名字和應用的包名一致。
比如manifest的package="com.example.helloalarm",則預設程序名就是com.example.helloalarm。
<application>元素的process屬性可以為全部的元件設定一個不同的預設程序。
元件可以override這個預設的程序設定,這樣你的應用就可以是多程序的。
如果你的process屬性以一個冒號開頭,程序名會在原來的程序名之後附加冒號之後的字串作為新的程序名。當元件需要時,會自動建立這個程序。這個程序是應用私有的程序。
如果process屬性以小寫字母開頭,將會直接以屬性中的這個名字作為程序名,這是一個全域性程序,這樣的程序可以被多個不同應用中的元件共享。
一次性鬧鐘
// 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);
重複鬧鐘
鬧鐘設定:
// 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說明
AlarmManager這個類提供對系統鬧鐘服務的訪問介面。
對它的獲取是通過系統服務:
Context.getSystemService(Context.ALARM_SERVICE)。
相關方法說明:
cancel(PendingIntent operation)方法將會取消Intent匹配的任何鬧鐘。
關於Intent的匹配,檢視filterEquals(Intent other)方法的說明可知,兩個Intent從intent resolution(filtering)(Intent決議或過濾)的角度來看是一致的,即認為兩個Intent相等。即是說,Intent的action,data,type,class,categories是相同的,其他的資料都不在比較範圍之內。
set(int type, long triggerAtMillis, PendingIntent operation)方法將會設定一個鬧鐘。
注意:對於計時操作,可能使用Handler更加有效率和簡單。
設定鬧鐘的時候注意:
1.如果宣告的triggerAtMillis是一個過去的時間,鬧鐘將會立即被觸發。
2.如果已經有一個相同intent的鬧鐘被設定過了,那麼前一個鬧鐘將會取消,被新設定的鬧鐘所代替。
注意這裡說的intent相同指的都是Intent在 filterEquals(Intent)的定義下匹配。
鬧鐘是一個廣播,接收器需要自己定義和註冊,註冊使用動態註冊( registerReceiver(BroadcastReceiver, IntentFilter) )或者靜態註冊(<receiver> tag in an AndroidManifest.xml file)都可以。
setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)方法將會設定一個重複性的鬧鐘。
比set方法多了一個間隔引數。
type的型別是四種:
ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC, RTC_WAKEUP.
區分的是時間標準和是否在睡眠狀態下喚醒裝置。
具體檢視官方文件吧不再詳細解釋啦。
例項
比如要設定一個每晚21:30喚醒的重複鬧鐘:
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解析: