AlarmManager取消闹钟后PendingIntent.FLAG_NO_CREATE仍返回非空问题
问题分析与解决方案
这个问题我之前也碰到过,核心原因是你只取消了AlarmManager里的闹钟任务,但没有销毁对应的PendingIntent实例。
当你调用alarmMgr.cancel(alarmIntent)时,AlarmManager会移除这个定时任务,但系统里的PendingIntent并不会被自动销毁。所以当你后续调用PendingIntent.getBroadcast(..., FLAG_NO_CREATE)时,依然会拿到之前的PendingIntent实例,导致你判断existingIntent == null为false,从而跳过重新设置闹钟的逻辑,但实际上此时AlarmManager里已经没有这个定时任务了。
修改后的代码
你只需要在取消闹钟的方法里,调用alarmIntent.cancel()来销毁PendingIntent即可:
fun setupAlarm(context: Context) { val alarmMgr = context.applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager val intent = Intent(context.applicationContext, ScheduledCheckReceiver::class.java) val existingIntent = PendingIntent.getBroadcast(context.applicationContext, 100, intent, PendingIntent.FLAG_NO_CREATE) Log.d("AlarmUtil","Should set up repeating alarm: " + (existingIntent == null)) if(existingIntent == null) { val alarmIntent = PendingIntent.getBroadcast(context.applicationContext, 100, intent, PendingIntent.FLAG_UPDATE_CURRENT) Log.d("AlarmUtil", "Setting up alarm to " + Date(System.currentTimeMillis() + 30 * 1000)) alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 30 * 1000, 60 * 1000, alarmIntent) } } fun cancelAlarm(context: Context) { Log.d("AlarmUtil", "Cancel alert called") val alarmMgr = context.applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager val intent = Intent(context.applicationContext, ScheduledCheckReceiver::class.java) // 用FLAG_NO_CREATE获取,避免不存在时创建新实例 val alarmIntent = PendingIntent.getBroadcast(context.applicationContext, 100, intent, PendingIntent.FLAG_NO_CREATE) // 先判断存在再执行取消 if (alarmIntent != null) { alarmMgr.cancel(alarmIntent) // 关键步骤:销毁PendingIntent,确保下次检查返回null alarmIntent.cancel() Log.d("AlarmUtil", "Alarm and corresponding PendingIntent cancelled") } }
补充注意事项
- 取消时用
FLAG_NO_CREATE获取PendingIntent更严谨,避免在目标实例不存在的情况下创建新的PendingIntent。 - 务必确保创建和取消PendingIntent时,Intent的内容、requestCode、目标组件完全一致——你当前的代码已经满足这一点(都是指向
ScheduledCheckReceiver,requestCode=100),这是保证系统识别为同一个PendingIntent的核心。 - 额外提一句:
setRepeating()在API 19及之后是不精确触发的,如果需要高精度的重复闹钟,建议使用setExactAndAllowWhileIdle()配合每次触发后重新设置的逻辑,不过这属于优化点,和你当前的问题无关。
内容的提问来源于stack exchange,提问作者user3626048
相关产品推荐
相关产品推荐

