1. 程式人生 > >Android中AlarmManager詳解以及利用PendingIntent設定鬧鐘

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);