首页 > 解决方案 > 如何正确取消时钟应用程序中AlarmManager设置的AlarmClock闹钟?

问题描述

这个问题在这里这里这里已经有了答案。但是他们没有得到 OP 的确认,在我的情况下,由同一个 PendingIntent 设置的警报并没有被取消。有没有办法取消闹钟闹钟?

@Override
protected void onHandleIntent(@Nullable Intent i) {
    Intent i = new Intent(AlarmClock.ACTION_SET_ALARM);
    i.putExtra(AlarmClock.EXTRA_SKIP_UI, true);
    i.putExtra(AlarmClock.EXTRA_HOUR, 6);
    i.putExtra(AlarmClock.EXTRA_MINUTES, 0);
    i.putExtra(AlarmClock.EXTRA_MESSAGE, "Good Morning");
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    AlarmManager alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
    PendingIntent alarmIntent = PendingIntent.getActivity(
                    this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
    alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime(),
                alarmIntent);
    Log.d(TAG, "Alarm set");

    try {
        Thread.sleep(15000);
        alarmMgr.cancel(alarmIntent);
        Log.i(TAG, "Alarm canceled");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

此代码按预期输出:

Alarm set
Alarm canceled

但它不会取消已设置的警报。我究竟做错了什么?

标签: androidalarmmanagerandroid-pendingintentandroid-alarms

解决方案


所以,我发现我需要使用ACTION_DISMISS_ALARM而不是ACTION_SET_ALARM. 它可以让您取消闹钟中已设置的闹钟。

此处此处此处的答案建议取消对我不起作用的 PendingIntent,也未确认对问题作者起作用。

我认为,为什么从 AlarmManager 取消 PendingIntent 不起作用的解释可能是 PendingIntent 可以让你做某事或稍后发送意图。一旦你已经完成了它(已经发送了意图),你就无法撤消它。例如,您可以取消通知,但不能撤消从通知中打开应用程序(执行的意图或操作),因为它已经完成。此外,就我而言,这是我需要取消警报的另一个应用程序,所以也许我不应该期望能够撤消该操作。因此,为了解除或取消警报,您需要发送一个带有 action 的新意图ACTION_DISMISS_ALARM

如下替换 try/catch 块为我正确设置和取消警报:

try {
    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
        return;
    }
    Thread.sleep(15000);
    Intent ci = new Intent(AlarmClock.ACTION_DISMISS_ALARM);
    ci.setData(i.getData());
    alarmIntent = PendingIntent.getActivity(this, 0, ci, 0);
    alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime(),
                alarmIntent);
    Log.i(TAG, "Alarm cancelled");
} catch (InterruptedException e) {
    e.printStackTrace();
}

但是,这仅适用于 API 级别 23+,并且不允许您像ACTION_SET_ALARM.


推荐阅读