在 Android 中可以使用警報(Alarm)及通知(Notification)的搭配來提醒使用者。
警報(Alarm)
Alarm 可以在預定的時間或某個時間間隔觸發意圖來提醒使用者。Alarm 是在應用程式之外設定的,也就是即使啟動它的 App 關閉了,仍會在指定的時間到達時發出警報。Alarm 也可使用時間間隔來發出警報,例如每隔 10 分鐘、每天早上 8 點等等。當 Android 裝置(手機)在休眠狀態(螢幕關閉)下,有指定喚醒(螢幕亮起)裝置的 Alarm 將會喚醒裝置並發出警報,例如鬧鐘程式會在指定時間到達時喚醒裝置並發出警報。
有個必須要注意的地方,當 Android 裝置(手機)重新啟動後,所有指定的 Alarm 都會被取消,必須利用其他方法在重開機後將 Alarm 重新設定。
通知(Notification)
Notification 是應用程式提醒使用者的一種方式,它會利用通知管理器進行處理而不需要 Activity 。通知的方式有幾種:建立狀態欄圖示、閃燈 (LED)、振動、鈴聲。Notification 通常會被用在 Broadcast Receiver 或 Service 等不可見的應用程式中,用來提醒使用者執行狀態或結果。如果把 Alarm 結合 Notification 就可以在時間到達時發出通知來提醒使用。
AlarmManager 的使用
要使用 Alarm 可以透過 AlarmManager 來管理 Alarm。AlarmManager 是一個系統服務 (System Service),取得方法如下:AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
要設定一個警報只要使用 set 方法,同時指定一個警報類型、觸發時間及一個待處理意圖。如果這個觸發時間是在過去,那這個警報會被立即觸發。警報類型有 4 種:
- RTC_WAKEUP:在指定時間觸發意圖並喚醒裝置。
- RTC:同上但不喚醒裝置。
- ELAPSED_REALTIME:在裝置啟動(開機)後開始計算經過的時間,在到達指定的經過時間觸發意圖,但不喚醒裝置。
- ELAPSED_REALTIME_WAKEUP:同上,但會喚醒裝置。
//使用Calendar指定時間
Calendar calendar = Calendar.getInstance();
calendar.set(2012, 10, 8, 16, 30);
//建立意圖
Intent intent = new Intent();
//這裡的 this 是指當前的 Activity
//AlarmReceiver.class 則是負責接收的 BroadcastReceiver
intent.setClass(this, AlarmReceiver.class);
//建立待處理意圖
PendingIntent pending = PendingIntent.getBroadcast(context, 0, intent, 0);
//取得AlarmManager
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
//設定一個警報
//參數1,我們選擇一個會在指定時間喚醒裝置的警報類型
//參數2,將指定的時間以millisecond傳入
//參數3,傳入待處理意圖
alarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending);
如果你用相同的待處理意圖(PendingIntent)設定第 2 個警報,那第 2 個警報將會取代原有的警報。那要如何取消警報呢?同樣以待處理意圖為目標,使用 cancel 方法將其傳入,即可取消該警報。如下:
alarm.cancel(pending);
重覆性警報(Repeating Alarm)
相對於一次性警報,重覆性警報會在一定時間內重覆執行,直到被取消。要設定重覆性警報有 2 種方法,setRepeating() 或 setInexactRepeating() ,兩者的差別在於 setRepeating() 可以以精確到毫秒的時間間隔來執行,當然就會比較耗電,使用 setInexactRepeating() 則可以避免耗電。setInexactRepeating() 可以使用較不精確的時間間隔來設定,而這些在 AlarmManager 類別中已有內定的常數可使用,如下:
- INTERVAL_FIFTEEN_MINUTES
- INTERVAL_HALF_HOUR
- INTERVAL_HOUR
- INTERVAL_HALF_DAY
- INTERVAL_DAY
如果設定的多個非精確 (setInexactRepeating) 時間間隔,時間雖未重疊但很接近,Android 會同時觸發它們,避免不斷地發佈警報,在 API 中的解釋為 phase-aligned (相位對齊)。使用範例如下:
精確
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 10 * 1000, 10 * 1000, pending);
非精確
alarm.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 60 * 1000, AlarmManager.INTERVAL_FIFTEEN_MINUTES, pending);
接收警報
當 alarm 被觸發時,需要一個 receiver 來接收它,然後指示要做什麼事,所以我們要繼承一個 BroadcastReceiver 並實作它的 onReceive 方法。如下:public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//....do something
}
}
你可以在此發出通知告知使用者,或執行資料更新的動作等等。
NotificationManager 的使用
NotificationManager 和 AlarmManager 一樣是系統級的服務,所以取得方法一樣,如下:NotificationManager noMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
完整的通知範例:
//取得通知管理器
NotificationManager noMgr = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
//當使用者按下通知欄中的通知時要開啟的 Activity
Intent call = new Intent(this, AlarmDemoActivity.class);
//非必要,可以利用intent傳值
call.putExtra("notiId", 1);
//建立待處理意圖
PendingIntent pIntent = PendingIntent.getActivity(this, 0, call, 0);
//指定通知欄位要顯示的圖示
int icon = R.drawable.ic_launcher;
//指定通知出現時要顯示的文字,幾秒後會消失只剩圖示
String ticket = "電影時刻通知";
//何時送出通知,傳入當前時間則立即發出通知
long when = System.currentTimeMillis();
//建立通知物件
Notification notification = new Notification(icon, ticket, when);
//指定通知標題
String title = "鐵達尼號3D";
//通知內容
String desc = "播放時間17:00 - 新光影城";
//設定事件資訊
notification.setLatestEventInfo(this, title, desc, pIntent);
//非必要,會在通知圖示旁顯示數字
notification.number = 5;
//執行通知
noMgr.notify(1, notification);
收到通知時顯示:
幾秒後文字消失,顯示數字: 如果要消除數字,可以將其設為 0 或 -1,若一開始就沒指定則不會出現。
這邊要記住,只要送出的通知是同一個 PendingIntent ,那就不會產生新的通知,而是覆蓋重覆的通知。你可以建立一個變數,然後在每次發出通知後就加1,只要一直發佈重覆的通知,就只有數字會改變,不會跑出好幾個通知。
通知的內容: 如果你要使用自訂的通知佈局,可以使用 RemoteView 來實作,並指定給 notification.contentView ,如下:
notification.contentView = new RemoteViews(this.getPackageName(), R.layout.notification);
並且要同時把 PendingIntent 指定給 contentIntent 屬性,否則會出錯,如下:
notification.contentIntent = pIntent;
警報的補充
記得當你實作 BroadcastReceiver 時,在 AndroidManifest.xml 要加入你的 Receiver ,如下:<receiver android:name="AlarmReceiver"></receiver>
AlarmReceiver 是你的 Receiver 類別的名稱。此外,在一開始介紹 Alarm 時有說過,當裝置(手機)重新開機後,所有的 Alarm 都將被取消,那該怎麼解決呢?一樣利用 Receiver,我們可以如同建立 AlarmReceiver 一樣,建立一個 AlarmInitReceiver (繼承 BroadcastReceiver 並實作 onReceive),接著在 AndroidManifest.xml 中加入這個 Receiver 來接收開機訊息,如下:
<receiver android:name="AlarmInitReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
BOOT_COMPLETED 是 Android 內建的 action,會在開機後送出廣播,所以我們建立一個接收者去接收這個廣播即可。使用這個 action 必須增加使用權限,如下:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
如此一來就完成了開機廣播的接收,當你收到這個廣播後,就可以重新設定你的 Alarm ,不會因為使用者重開機而遺失了警報。
不好意思 請問一下 這個可以用來做每兩個月的發票兌獎的提醒嗎?
回覆刪除還有 如果要用在Eclipse寫 程式碼要放在那裡呢?
這個功能不是在行事曆裡面自己加提醒就可以了。
刪除請問這個有範例可以下載嗎
回覆刪除這篇好久以前寫的,找不到了~
刪除不好意思,現在還會回覆嗎?我想請問如何建立多個setRepeating的警報,且每個警報都做同樣的發送訊息動作?
回覆刪除且現在android 改版,我制定的鬧鐘時間會在滅屏後延遲發佈訊息,怎麼辦?
太久沒用了,我查了一下資料,不確定可不可行,
刪除可以試試看建立多個 Alarm ,每個 Alarm 有自己的 Repeating 警報,
而不是一個 Alram 多個 Repeating 警報
另外,查API文件
https://developer.android.com/reference/android/app/AlarmManager
找到 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()
這兩個方法,看說明可能符合你的要求,可以試看看