【问题标题】:Android: Get all PendingIntents set with AlarmManagerAndroid:获取所有使用 AlarmManager 设置的 PendingIntents
【发布时间】:2010-11-30 15:50:20
【问题描述】:

我正在设置这样的闹钟:

alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingEvent);

我有兴趣删除之前设置的所有警报,并清除它们。

有没有办法让我这样做或获取当前设置的所有警报以便我可以手动删除它们?

【问题讨论】:

标签: android alarmmanager


【解决方案1】:

您不必一直引用它。只需定义一个新的 PendingIntent,就像您在创建它时定义的一样。

例如:

如果我创建了一个待由 AlarmManager 触发的 PendingIntent,如下所示:

Intent alarmIntent = new Intent(getApplicationContext(), AlarmBroadcastReceiver.class);
alarmIntent.setData(Uri.parse("custom://" + alarm.ID));
alarmIntent.setAction(String.valueOf(alarm.ID));
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

PendingIntent displayIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmIntent, 0);

alarmManager.set(AlarmManager.RTC_WAKEUP, alarmDateTime, displayIntent);

然后在您的其他代码(甚至是另一个活动)中的某个位置,您可以这样做来取消:

Intent alarmIntent = new Intent(getApplicationContext(), AlarmBroadcastReceiver.class);
alarmIntent.setData(Uri.parse("custom://" + alarm.ID));
alarmIntent.setAction(String.valueOf(alarm.ID));
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

PendingIntent displayIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmIntent, 0);

alarmManager.cancel(displayIntent);

这里重要的是使用完全相同的数据和操作以及其他标准设置 PendingIntent 以及此处所述http://developer.android.com/reference/android/app/AlarmManager.html#cancel%28android.app.PendingIntent%29

【讨论】:

  • +1 for alarmIntent.setData(Uri.parse("custom://" + alarm.ID)); alarmIntent.setAction(String.valueOf(alarm.ID));
  • @gilsaints88 :你能解释一下,alarm.ID 的功能是什么,我如何在我的两个活动中声明它?
  • @mas_bejo setData(...) 上的 alarm.ID 用于警报的唯一性,以便我们可以在使用 setAction(...) 时清除任何先前设置的具有相同 alarm.ID 的警报这样当通过 onNewIntent() 返回到 Activity 时,从通知传递的意图是正确的值。我在设置我的警报时使用 setData 和 setAction,当我从来自通知的 Activity 接收它时,我通过覆盖 Activity 的 onNewIntent 来获得意图。由于之前的 setAction(...) ,我得到的意图是正确的。我希望这会有所帮助。
  • 嗨,通过 setData 和 SetAction 通知在我的 OPPO 手机中被取消,但在我的 MOTO 手机中没有被取消。你能建议一下吗?
  • @NiravPatel 请问你的OPPO是什么安卓版本,你的MOTO是什么安卓版本?谢谢
【解决方案2】:

您需要创建待处理的意图,然后将其取消

 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    Intent updateServiceIntent = new Intent(context, MyPendingIntentService.class);
    PendingIntent pendingUpdateIntent = PendingIntent.getService(context, 0, updateServiceIntent, 0);

    // Cancel alarms
    try {
        alarmManager.cancel(pendingUpdateIntent);
    } catch (Exception e) {
        Log.e(TAG, "AlarmManager update was not canceled. " + e.toString());
    }

【讨论】:

  • 无需参考。 alarmManager.cancel 取消所有这些文档:删除具有匹配 Intent 的任何警报。任何类型的警报,其 Intent 与此匹配(由 filterEquals(Intent) 定义)都将被取消。
  • 如何保留对它们的引用我将所有内容都存储在数据库中那么我如何保留对它的引用?
  • 如果我的意图有一些额外的价值或捆绑......我是否需要创建具有相同额外价值的相同意图才能取消意图?
  • 还需要执行pendingUpdateIntent.cancelt()才能使其完全生效
  • @FinalDark extras 在匹配Intents 时不会被考虑在内,所以当你创建Intent 时,它没有什么区别。您可以使用Intent 取消警报,无需额外功能。
【解决方案3】:

要取消警报,您需要重新创建相同的 PendingIntent 并传递相同的请求代码。

因此,我创建了一个 AlarmUtils 来帮助我将所有请求代码保存在首选项中,以便将来在需要时取消它。您只需要使用以下类并调用以下方法:

  • addAlarm 添加新警报并传递请求代码。
  • cancelAlarm要删除警报,您需要重新创建相同的
    意图并传递相同的请求代码。
  • hasAlarm 验证是否添加了警报,您需要重新创建 相同的 Intent 并传递相同的请求代码。
  • cancelAllAlarms 删除所有设置的警报。

我的闹钟工具

public class AlarmUtils {

    private static final String sTagAlarms = ":alarms";

    public static void addAlarm(Context context, Intent intent, int notificationId, Calendar calendar) {

        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId, intent, PendingIntent.FLAG_CANCEL_CURRENT);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        } else {
            alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        }

        saveAlarmId(context, notificationId);
    }

    public static void cancelAlarm(Context context, Intent intent, int notificationId) {
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        alarmManager.cancel(pendingIntent);
        pendingIntent.cancel();

        removeAlarmId(context, notificationId);
    }

    public static void cancelAllAlarms(Context context, Intent intent) {
        for (int idAlarm : getAlarmIds(context)) {
            cancelAlarm(context, intent, idAlarm);
        }
    }

    public static boolean hasAlarm(Context context, Intent intent, int notificationId) {
        return PendingIntent.getBroadcast(context, notificationId, intent, PendingIntent.FLAG_NO_CREATE) != null;
    }

    private static void saveAlarmId(Context context, int id) {
        List<Integer> idsAlarms = getAlarmIds(context);

        if (idsAlarms.contains(id)) {
            return;
        }

        idsAlarms.add(id);

        saveIdsInPreferences(context, idsAlarms);
    }

    private static void removeAlarmId(Context context, int id) {
        List<Integer> idsAlarms = getAlarmIds(context);

        for (int i = 0; i < idsAlarms.size(); i++) {
            if (idsAlarms.get(i) == id)
                idsAlarms.remove(i);
        }

        saveIdsInPreferences(context, idsAlarms);
    }

    private static List<Integer> getAlarmIds(Context context) {
        List<Integer> ids = new ArrayList<>();
        try {
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
            JSONArray jsonArray2 = new JSONArray(prefs.getString(context.getPackageName() + sTagAlarms, "[]"));

            for (int i = 0; i < jsonArray2.length(); i++) {
                ids.add(jsonArray2.getInt(i));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return ids;
    }

    private static void saveIdsInPreferences(Context context, List<Integer> lstIds) {
        JSONArray jsonArray = new JSONArray();
        for (Integer idAlarm : lstIds) {
            jsonArray.put(idAlarm);
        }

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString(context.getPackageName() + sTagAlarms, jsonArray.toString());

        editor.apply();
    }
}

【讨论】:

  • 可能值得将removeAlarmId公开,这样人们就可以在通知到达时删除ID。
  • 您可以使用cancelAlarm() 代替,因为您需要创建pendingIntent 来取消警报
  • 很有趣,所以即使警报过去了它仍然排队?
  • PreferenceManager 现已弃用
  • @VadimKotov 您可能已经在使用 androidx,因此您需要将实现 'androidx.preference:preference:1.1.0' 添加到您的构建 gradle 依赖项以使用未弃用的 androidx PrefenerceManager。
【解决方案4】:

如果将 PendingIntent id 保存在 SharedPreference 或 db 中,当 Android 重启您的包强制停止

时,您将得到错误的值

您可以将之前的所有 PendingIntent 保存到另一个新的 PendingIntent 中,然后再全部取消

例如

    void createSomeAlarmAndSave() {
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, MyReceiver.class).setAction(ACTION_XXX), 0);
        getSystemService(AlarmManager.class).setInexactRepeating(AlarmManager.RTC_WAKEUP, 1000 * 60 * 15, 1000 * 60 * 15, pendingIntent);

        PendingIntent pendingIntent1 = PendingIntent.getBroadcast(this, 1, new Intent(this, MyReceiver.class).setAction(ACTION_XXX), 0);
        getSystemService(AlarmManager.class).setInexactRepeating(AlarmManager.RTC_WAKEUP, 1000 * 60 * 20, 1000 * 60 * 20, pendingIntent1);

        PendingIntent pendingIntent2 = PendingIntent.getBroadcast(this, 2, new Intent(this, MyReceiver.class).setAction(ACTION_XXX), 0);
        getSystemService(AlarmManager.class).setInexactRepeating(AlarmManager.RTC_WAKEUP, 1000 * 60 * 25, 1000 * 60 * 25, pendingIntent2);

        //save all previous PendingIntent to another new PendingIntent
        PendingIntent.getBroadcast(this, 0, new Intent(this, MyReceiver.class).putExtra("previous", new PendingIntent[]{pendingIntent, pendingIntent1, pendingIntent2}), PendingIntent.FLAG_UPDATE_CURRENT);
    }

取消所有之前的 PendingIntent

    void cancelAllPreviousAlarm() {
        //acquire the dedicated PendingIntent
        PendingIntent pendingIntentAllPrevious = PendingIntent.getBroadcast(this, 0, new Intent(this, MyReceiver.class), PendingIntent.FLAG_NO_CREATE);
        if (pendingIntentAllPrevious != null) {
            try {
                pendingIntentAllPrevious.send(this, 0, null, new PendingIntent.OnFinished() {
                    @Override
                    public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras) {
                        for (Parcelable parcelable : intent.getParcelableArrayExtra("previous")) {
                            //alarm will cancel when the corresponding PendingIntent cancel
                            ((PendingIntent) parcelable).cancel();
                        }
                    }
                }, null);
                pendingIntentAllPrevious.cancel();
            } catch (PendingIntent.CanceledException e) {
                e.printStackTrace();
            }
        }
    }

【讨论】:

    【解决方案5】:

    如果您重新创建 PendingIntent:

    PendingIntent pendingIntent = PendingIntent.getBroadcast(
                context, 0, newIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-25
      • 1970-01-01
      • 2022-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多