天天看點

Android中設定定時鬧鐘以及AlarmManager詳解

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);
if(Build.VERSION.SDK_INT>=Build.VERSION.KITKAT){
           

alarmService.setWindow(AlarmManager.RTC_WAKEUP,calMethod(instance.getTimeInMillis()),INTERVAL,broadcast);}else{

alarmService.setRepeating(AlarmManager.RTC_WAKEUP,calMethod(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);