AlarmReceiver 應該就是當鬧鈴時間到達時,要執行的程式。而 AlarmInitReceiver 則是當手機重開機,時間被重新設定,或是時區改變時,所要執行的程式。
讓我們先打開 AlarmInitReceiver.java 看看。#31~#42 這個 onReceive() 內的程式就是關鍵。
從其呼叫的函式名稱,不難理解出這段程式的主要工作,就是重新設定下一個鬧鈴。在這裡的 Intent.ACTION_BOOT_COMPLETED ,就是手機重開機時,所發出的系統 Intent。
接著,我們打開 Alarms.java 看看 setNextAlert() 這個函式到底在做些甚麼事。
看起來,enableAlert() 就是負責設定下一個鬧鈴的主要函式。
從程式中,我們了解到他先透過 AlarmManager 的 set() 函式,設定鬧鈴時間,以及鬧鈴時間到達時,所要喚起的程式。由於是透過 PendingIntent.getBroadcast() 取得 PendingIntent 的 instance,因此我們知道這個被喚起的程式應該是個 broadcast receiver。
那到底是那個 broadcast receiver 會被喚起呢?從程式看來,應該就是喚起會接收 ALARM_ALERT_ACTION action 的 broadcast receiver。在此的 ALARM_ALERT_ACTION 就是 "com.android.alarmclock.ALARM_ALERT" 字串。
讓我們再翻開 AndroidManifest.xml 瞧瞧,會接收 com.android.alarmclock.ALARM_ALERT 的 broadcast receiver,不就是 AlarmReceiver?!
打開 AlarmReceiver.java。仔細研讀一下,不難理解這段程式的主要工作就是:
- 先喚醒可能正在沉睡中的 CPU 與螢幕
- 暫時解開鍵盤或螢幕鎖
- 執行 AlarmAlert 這個 Activity,也就是你最終看到的鬧鈴提醒對話框。
最後,你有沒有發現,一般我們設定的 notification icon 都是出現在 status bar 的左手邊。而 AlarmClock 的鬧鈴 icon 卻是出現在右手邊的系統 icon 區?想要知道他是如何做到的?再回頭看 Alarms.java 中的 enableAlert(),其最後會呼叫 setStatusBarIcon() ,我想答案應該就在其中。
打開 setStatusBarIcon(),其內容如下:
竟然是透過送出 ACTION_ALARM_CHANGED Intent,來設定 notification icon 的。看來,這是個未公開的用法。了解這些特別的用法,這不就是你研讀系統原始碼的好處之一嗎?