警报未取消
Alarms not cancelled
我正在使用以下代码取消并重置所有闹钟:
for (int i = 0; i < mArrayList.size(); i++) {
Intent receiverIntent = new Intent(mContext, AlarmReceiver.class);
int _id = (int) mArrayList.get(i).getDateMillis(); //(int) System.currentTimeMillis();
PendingIntent sender = PendingIntent.getBroadcast(mContext, _id, receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(mContext.ALARM_SERVICE);
alarmManager.cancel(sender);
setAlarm(mContext, receiverIntent, mArrayList.get(i).getType(), _id, sender, alarmManager);
}
public static void setAlarm(Context context, Intent receiverIntent, String typ, long timeMillis, PendingIntent pendingIntent, AlarmManager
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeMillis);
long sdl = calendar.getTimeInMillis();
String notificationTitle = "My Title";
String notificationText = "My Text";
receiverIntent.putExtra("notificationTitle", notificationTitle);
receiverIntent.putExtra("notificationText", notificationText);
receiverIntent.putExtra("notificationDateTime", sdl);
alarmManager.set(AlarmManager.RTC_WAKEUP, sdl, pendingIntent);
}
问题是,当我第一次调用 CancelAllAlarms()
然后设置我的闹钟时,新的闹钟创建得很好,但旧的没有被删除。
因此,如果我第一次执行 adb shell dumpsys alarm > D:\test.txt
,我有大约 200 个条目,下一个应用程序是 运行 我有大约 400 个,然后是 600 个等等...
编辑
我更改了我的代码很多,因为我现在将生成的 ID 存储在一个工作正常的数据库中。所以我的代码发生了重大变化:
Intent receiverIntent = new Intent(mContext, AlarmReceiver.class);
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(mContext.ALARM_SERVICE);
String[] alarms = getAllAlarmsFromDB(databaseHAlarms, databaseHAlarms.tableName_alarms);
for (int i = 0; i < alarms.length; i++) {
//alarms[i] now holds the ID set before (see codee below)
PendingIntent sender = PendingIntent.getBroadcast(mContext, Integer.parseInt(alarms[i]), receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.cancel(sender);
}
for (int i = 0; i < mArrayList.size(); i++) {
long timeMillis = mArrayList.get(i).getDateMillis();
int _id = Integer.parseInt(String.valueOf(mArrayList.get(i).getDateMillis()).substring(0, 8));
PendingIntent sender = PendingIntent.getBroadcast(mContext, _id, receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
insertAlarmIntoMySQL(databaseHAlarms, getMD5(timeMillis + ""), String.valueOf(mArrayList.get(i).getDateMillis()).substring(0, 8));
alarmManager.set(AlarmManager.RTC_WAKEUP, sdl, sender);
}
您需要将传递给 alarmManager.set()
的 PendingIntent
传递给 alarmManager.cancel()
。
在您的代码中 _id
会有所不同,因此 PendingIntent
不相等,因此取消将不起作用。
ID 应该是唯一的(除非你总是想取消所有这些),但是当你想取消一个特定的警报时,你需要知道你在创建时用于 PendingIntent
的 ID它,并使用完全相同的 ID 取消它。
我建议将 ID 存储在 SQLite 数据库中。
除了 user13 的回答外,您还必须在 PendingIntent
上使用 FLAG_UPDATE_CURRENT
。
所以总而言之,一定要使用相同的Context
和id
并使用FLAG_UPDATE_CURRENT
:
启动闹钟:
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, sender);
停止闹钟:
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_CUPDATE_CURRENT);
alarmManager.cancel(sender);
为什么
嗯,clear/documented 为什么 FLAG_CANCEL_CURRENT
不起作用,但我经常在 SO 中阅读此内容。文档告诉我们,这会取消现有的 PendingIntent
并创建一个新的,如果您想更改 intent
.
中的某些 extra data
,您可以使用它
FLAG_UPDATE_CURRENT
描述如下:
如果您正在创建只有 extras 发生变化的意图,并且不关心任何收到您之前的 PendingIntent 的实体将能够使用您的新 extras 启动它,即使他们没有明确地给它。
从这两个描述中,我看不出如果您使用 FLAG_CANCEL_CURRENT
它不应该与 alarmManager.cancel()
一起工作的原因。也许是因为 PendingIntent
在 alarmManager.cancel()
能够之前通过 FLAG
被取消并重新创建。
棉花糖
棉花糖有一些新情况。取消应该像以前一样工作,没有变化。但是如果设备进入休眠模式,使用 alarmManager.set()
设置闹钟将不起作用。描述您必须使用 setAndAllowWhileIdle()
、setExactAndAllowWhileIdle()
或 setAlarmClock()
的文档。
但仅当您的应用程序需要在打瞌睡时触发警报时才这样做!因此,要为 Marshmallow 准备您的应用程序,您应该检查 API 版本并设置它所依赖的方法。
if (Build.VERSION.SDK_INT >= 23) {
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, sender);
} else {
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, sender);
}
我正在使用以下代码取消并重置所有闹钟:
for (int i = 0; i < mArrayList.size(); i++) {
Intent receiverIntent = new Intent(mContext, AlarmReceiver.class);
int _id = (int) mArrayList.get(i).getDateMillis(); //(int) System.currentTimeMillis();
PendingIntent sender = PendingIntent.getBroadcast(mContext, _id, receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(mContext.ALARM_SERVICE);
alarmManager.cancel(sender);
setAlarm(mContext, receiverIntent, mArrayList.get(i).getType(), _id, sender, alarmManager);
}
public static void setAlarm(Context context, Intent receiverIntent, String typ, long timeMillis, PendingIntent pendingIntent, AlarmManager
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeMillis);
long sdl = calendar.getTimeInMillis();
String notificationTitle = "My Title";
String notificationText = "My Text";
receiverIntent.putExtra("notificationTitle", notificationTitle);
receiverIntent.putExtra("notificationText", notificationText);
receiverIntent.putExtra("notificationDateTime", sdl);
alarmManager.set(AlarmManager.RTC_WAKEUP, sdl, pendingIntent);
}
问题是,当我第一次调用 CancelAllAlarms()
然后设置我的闹钟时,新的闹钟创建得很好,但旧的没有被删除。
因此,如果我第一次执行 adb shell dumpsys alarm > D:\test.txt
,我有大约 200 个条目,下一个应用程序是 运行 我有大约 400 个,然后是 600 个等等...
编辑
我更改了我的代码很多,因为我现在将生成的 ID 存储在一个工作正常的数据库中。所以我的代码发生了重大变化:
Intent receiverIntent = new Intent(mContext, AlarmReceiver.class); AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(mContext.ALARM_SERVICE);
String[] alarms = getAllAlarmsFromDB(databaseHAlarms, databaseHAlarms.tableName_alarms);
for (int i = 0; i < alarms.length; i++) {
//alarms[i] now holds the ID set before (see codee below)
PendingIntent sender = PendingIntent.getBroadcast(mContext, Integer.parseInt(alarms[i]), receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.cancel(sender);
}
for (int i = 0; i < mArrayList.size(); i++) {
long timeMillis = mArrayList.get(i).getDateMillis();
int _id = Integer.parseInt(String.valueOf(mArrayList.get(i).getDateMillis()).substring(0, 8));
PendingIntent sender = PendingIntent.getBroadcast(mContext, _id, receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
insertAlarmIntoMySQL(databaseHAlarms, getMD5(timeMillis + ""), String.valueOf(mArrayList.get(i).getDateMillis()).substring(0, 8));
alarmManager.set(AlarmManager.RTC_WAKEUP, sdl, sender);
}
您需要将传递给 alarmManager.set()
的 PendingIntent
传递给 alarmManager.cancel()
。
在您的代码中 _id
会有所不同,因此 PendingIntent
不相等,因此取消将不起作用。
ID 应该是唯一的(除非你总是想取消所有这些),但是当你想取消一个特定的警报时,你需要知道你在创建时用于 PendingIntent
的 ID它,并使用完全相同的 ID 取消它。
我建议将 ID 存储在 SQLite 数据库中。
除了 user13 的回答外,您还必须在 PendingIntent
上使用 FLAG_UPDATE_CURRENT
。
所以总而言之,一定要使用相同的Context
和id
并使用FLAG_UPDATE_CURRENT
:
启动闹钟:
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, sender);
停止闹钟:
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_CUPDATE_CURRENT);
alarmManager.cancel(sender);
为什么
嗯,clear/documented 为什么 FLAG_CANCEL_CURRENT
不起作用,但我经常在 SO 中阅读此内容。文档告诉我们,这会取消现有的 PendingIntent
并创建一个新的,如果您想更改 intent
.
extra data
,您可以使用它
FLAG_UPDATE_CURRENT
描述如下:
如果您正在创建只有 extras 发生变化的意图,并且不关心任何收到您之前的 PendingIntent 的实体将能够使用您的新 extras 启动它,即使他们没有明确地给它。
从这两个描述中,我看不出如果您使用 FLAG_CANCEL_CURRENT
它不应该与 alarmManager.cancel()
一起工作的原因。也许是因为 PendingIntent
在 alarmManager.cancel()
能够之前通过 FLAG
被取消并重新创建。
棉花糖
棉花糖有一些新情况。取消应该像以前一样工作,没有变化。但是如果设备进入休眠模式,使用 alarmManager.set()
设置闹钟将不起作用。描述您必须使用 setAndAllowWhileIdle()
、setExactAndAllowWhileIdle()
或 setAlarmClock()
的文档。
但仅当您的应用程序需要在打瞌睡时触发警报时才这样做!因此,要为 Marshmallow 准备您的应用程序,您应该检查 API 版本并设置它所依赖的方法。
if (Build.VERSION.SDK_INT >= 23) {
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, sender);
} else {
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, sender);
}