Android中AlarmManager詳解以及利用PendingIntent設定鬧鐘
AlarmManager是提供一種訪問系統鬧鐘服務的方式,允許你去設定在將來的某個時間點去執行你的應用程式。當你的鬧鐘響起(時間到)時,在它上面註冊的一個意圖(Intent)將會被系統以廣播發出,然後自動啟動目標程式,如果它沒有正在執行。註冊的鬧鐘會被保留即使裝置處於休眠中(如果鬧鐘在給定時間響起可以選擇是否喚醒裝置)。如果鬧鐘關閉或者重啟,鬧鐘將被清除。
比如說我想在在每天的八點鐘給使用者一個通知,這裡都必須用到PendingIntent,PendingIntent可以理解為Intent的封裝包,簡單的說就是在Intent上在加個指定的動作:
private static final int INTERVAL = 1000 * 60 * 60 * 24;// 24h
AlarmManager alarmService = (AlarmManager) getSystemService(ALARM_SERVICE); Calendar instance = Calendar.getInstance(); instance.set(Calendar.HOUR_OF_DAY, 8); instance.set(Calendar.MINUTE, 0); instance.set(Calendar.SECOND, 0); Intent alarmIntent = new Intent(this, AlarmclockReceive.class); PendingIntent broadcast = PendingIntent.getBroadcast(this, 0, alarmIntent, 0); alarmService.setRepeating(AlarmManager.RTC_WAKEUP, instance.getTimeInMillis(),INTERVAL , broadcast);
PendingIntent的getBroadcast中的引數的含義:
這個主要講解第四個引數Flags:
PendingIntent的Flags為0代表該PendingIntent不帶資料
Flags為FLAG_CANCEL_CURRENT :如果AlarmManager管理的PendingIntent已經存在,那麼將會取消當前的PendingIntent,從而建立一個新的PendingIntent
Flags為PendingIntent.FLAG_UPDATE_CURRENT,
PendingIntentcontentIntent = PendingIntent.getBroadcast(context, num,intent,PendingIntent.FLAG_UPDATE_CURRENT);
對於FLAG_UPDATE_CURRENT,如果上面的num為常量, 則所有對應的Intent裡面的資料被更新為最新的, 就是全部為最後一次的。
相反,如果num每次不一樣,則裡面的Intent的資料沒被更新。
所以要通過extra資料來區分intent,應採用PendingIntent.FLAG_UPDATE_CURRENT),且每次num不一樣
AlarmManager的常用方法有三個:
(1)set(int type,long startTime,PendingIntent pi);
該方法用於設定一次性鬧鐘,第一個引數表示鬧鐘型別,第二個引數表示鬧鐘執行時間,第三個引數表示鬧鐘響應動作。
(2)setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
該方法用於設定重複鬧鐘,第一個引數表示鬧鐘型別,第二個引數表示鬧鐘首次執行時間,第三個引數表示鬧鐘兩次執行的間隔時間,第三個引數表示鬧鐘響應動作。
(3)setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
該方法也用於設定重複鬧鐘,與第二個方法相似,不過其兩個鬧鐘執行的間隔時間不是固定的而已。
這裡主要講解第一種方法:
set(int type,long startTime,PendingIntent pi))方法裡面有三個引數:
type:鬧鐘的型別,有五種:
AlarmManager.ELAPSED_REALTIME表示鬧鐘在手機睡眠狀態下不可用,該狀態下鬧鐘使用相對時間(相對於系統啟動開始);
AlarmManager.ELAPSED_REALTIME_WAKEUP表示鬧鐘在睡眠狀態下會喚醒系統並執行提示功能,該狀態下鬧鐘也使用相對時間;
AlarmManager.RTC表示鬧鐘在睡眠狀態下不可用,該狀態下鬧鐘使用絕對時間,即當前系統時間(讓定時任務的觸發時間從1970年1月1日0點開始算起);
AlarmManager.RTC_WAKEUP表示鬧鐘在睡眠狀態下會喚醒系統並執行提示功能,該狀態下鬧鐘使用絕對時間,狀態值為0;
AlarmManager.POWER_OFF_WAKEUP表示鬧鐘在手機關機狀態下也能正常進行提示功能,所以是5個狀態中用的最多的狀態之一,該狀態下鬧鐘也是用絕對時間;不過本狀態好像受SDK版本影響,某些版本並不支援;
intervalTime:鬧鐘的第一次執行時間,以毫秒為單位,它必須和type相對應,比如type是AlarmManager.ELAPSED_REALTIME_WAKEUP型別,代表是使用的是相對時間,所以intervalTime必須也得是相對時間:
SystemClock.elapsedRealtime()。
SystemClock.elapsedRealtime()方法可以獲取到系統開機至今所經歷時間的毫秒數,
System.currentTimeMillis()方法可以獲取到1970年1月1日0點至今所經歷時間的毫秒數
就講解到這裡下面是我的寫的例子:
private static final int INTERVAL = 1000 * 60 * 60 * 24;// 24h
AlarmManager alarmService = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar instance = Calendar.getInstance();
instance.set(Calendar.HOUR_OF_DAY, 8);//小時
instance.set(Calendar.MINUTE, 0);//分鐘
instance.set(Calendar.SECOND, 0);//秒
//這裡是八點鐘提醒一次
//這裡也可以指定哪一年的那一天
//c.set(Calendar.YEAR,2016);//年
//c.set(Calendar.MONTH,3);//月
//c.set(Calendar.DAY_OF_MONTH, 12);//天
Intent alarmIntent = new Intent(this, AlarmclockReceive.class); PendingIntent broadcast = PendingIntent.getBroadcast(this, 0, alarmIntent, 0); alarmService.setRepeating(AlarmManager.RTC_WAKEUP, instance.getTimeInMillis(), INTERVAL,broadcast);//這裡一定要注意,一定要相對時間對應相對時間,
絕對時間對應絕對時間,要不然通知你是收不到的,我就是在這裡試了好幾次都不行,最後發現這裡寫錯了
取消鬧鐘:
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, AlarmclockReceive.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
manager.cancel(pi);