Android中對鬧鐘Alarm的事件處理

之前的博文一直在持續分享Phone相關的知識也算是知識筆記,但在工作中難免遇到其它模塊的一些問題,因此在解決這些問題的時候順手將這些知識記錄並分享出來。有些知識在不知道的時候會認為很難,當瞭解之後便會覺得很容易。同時部分知識也是具有時效性的,比如隨著Android版本的更迭,Phone的架構變化等等,因此希望自己的筆記能夠幫助到一些童鞋,這樣就足夠瞭。

轉載請務必註明出處:https://blog.csdn.net/yihongyuelan

Android中如果鬧鐘響起時,而應用需要對此做一些處理應該怎麼辦呢?首先我們需要接收到該事件,之後再考慮是關閉(stop)還是小睡(snooze)。在代碼packages/apps/DeskClock/src/com/android/deskclock/alarms/AlarmService.java 中有如下描述:

35    // A public action send by AlarmService when the alarm has started.
36    public static final String ALARM_ALERT_ACTION = "com.android.deskclock.ALARM_ALERT";
37
38    // A public action sent by AlarmService when the alarm has stopped for any reason.
39    public static final String ALARM_DONE_ACTION = "com.android.deskclock.ALARM_DONE";

通過查看註釋可以知道,系統提供瞭兩個Action用於廣播鬧鐘事件,包括:com.android.deskclock.ALARM_ALERT和com.android.deskclock.ALARM_DONE,即當鬧鐘響起時觸發com.android.deskclock.ALARM_ALERT,而當鬧鐘停止或者小睡時觸發com.android.deskclock.ALARM_DONE。也就說需要監聽廣播事件就註冊一個廣播監聽器:

IntentFilter filter = new IntentFilter();
filter.addAction("com.android.deskclock.ALARM_ALERT");
filter.addAction("com.android.deskclock.ALARM_DONE");
registerReceiver(mReceiver, filter);

這裡的mReceiver是BroadCastReceiver的對象,在onReceive中處理事件。當鬧鐘響起時,彈出的界面是AlarmActivity.java路徑位於:packages/apps/DeskClock/src/com/android/deskclock/alarms/AlarmActivity.java,在該類中提供瞭兩個重要的鬧鐘操作接口,即stop和snooze,可以看到如下描述:

49    // AlarmActivity listens for this broadcast intent, so that other applications
50    // can snooze the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION).
51    public static final String ALARM_SNOOZE_ACTION = "com.android.deskclock.ALARM_SNOOZE";
52
53    // AlarmActivity listens for this broadcast intent, so that other applications
54    // can dismiss the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION).
55    public static final String ALARM_DISMISS_ACTION = "com.android.deskclock.ALARM_DISMISS";

該方法提供瞭兩個廣播接收的接口分別是com.android.deskclock.ALARM_SNOOZE和com.android.deskclock.ALARM_DISMISS,前者用於snooze後者用於stop。在AlarmActivity中可以看到對該action的處理,如下:

184        IntentFilter filter = new IntentFilter(AlarmService.ALARM_DONE_ACTION);
185        filter.addAction(ALARM_SNOOZE_ACTION);
186        filter.addAction(ALARM_DISMISS_ACTION);
187        registerReceiver(mReceiver, filter);


118    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
119        @Override
120        public void onReceive(Context context, Intent intent) {
121            String action = intent.getAction();
122            Log.v("AlarmActivity - Broadcast Receiver - " + action);
123            if (action.equals(ALARM_SNOOZE_ACTION)) {
124                snooze();
125            } else if (action.equals(ALARM_DISMISS_ACTION)) {
126                dismiss();
127            } else if (action.equals(AlarmService.ALARM_DONE_ACTION)) {
128                finish();
129            } else {
130                Log.i("Unknown broadcast in AlarmActivity: " + action);
131            }
132        }
133    };

也就是說可以在代碼中通過使用廣播的方式來控制鬧鐘的stop和snooze:

private void stopAlarm() {
    Intent intent = new Intent();
    intent.setAction("com.android.deskclock.ALARM_DISMISS");
    sendBroadcast(intent);
}
    
private void snoozeAlarm() {
    Intent intent = new Intent();
    intent.setAction("com.android.deskclock.ALARM_SNOOZE");
    sendBroadcast(intent);
}

最後附上Demo,當鬧鐘響起時接收並將其Stop/Snooze,代碼如下:

    private void stopAlarm() {
        Intent intent = new Intent();
        intent.setAction("com.android.deskclock.ALARM_DISMISS");
        sendBroadcast(intent);
    }
    
    private void snoozeAlarm() {
        Intent intent = new Intent();
        intent.setAction("com.android.deskclock.ALARM_SNOOZE");
        sendBroadcast(intent);
    }
    Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    Log.i("Seven", "stop alarm");
                    stopAlarm();
                    break;
                case 1:
                    Log.i("Seven", "snooze alarm");
                    snoozeAlarm();
                    break;


                default:
                    break;
            }
        }
    };
    
    private void registerAlarmReceiver() {
        mReceiver = new MyReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.android.deskclock.ALARM_ALERT");
        filter.addAction("com.android.deskclock.ALARM_DONE");
        registerReceiver(mReceiver, filter);
    }


    class MyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("com.android.deskclock.ALARM_ALERT")) {
                Log.i("Seven","ALARM_ALERT");
                mHandler.sendEmptyMessageDelayed(0,15); //stop alarm
                //mHandler.sendEmptyMessageDelayed(1,15); //snooze alarm
            }else if (intent.getAction().equals("com.android.deskclock.ALARM_DONE")) {
                Log.i("Seven","ALARM_DONE");
            }
        }
    }

這裡可能有的人會感覺奇怪,為什麼不直接調用stopAlarm和snoozeAlarm而是使用handler的sendEmptyMessageDelayed方法。如果直接使用stopAlarm和snoozeAlarm方法會沒有效果,最少需要延遲15ms才會有作用。

最後加上一些英文的翻譯,以便國外的童鞋也能獲得一些幫助。

How to stop an alarm in android

How to turn off the alarm clock on the droid

How to cancel the android alarm

Android Alarm not turning off programmatically

Automatically silence the sound volume of Android Phone programmatically

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *