Android AlarmManager每日重复闹钟异常:打开应用触发通知问题求助
解决Android AlarmManager打开应用就触发通知的问题
兄弟,我太懂你踩的这个坑了!你现在的问题核心是每次启动App调用setAlarm时,直接把首次触发时间设成了当天9点,但如果当前时间已经过了9点,AlarmManager会立刻触发一次来“补”这次闹钟,然后才开始每天重复;另外如果每次启动都重复设置闹钟,也可能导致重复触发通知。
下面给你一步步解决的方案:
1. 计算正确的首次触发时间
首先要判断当前时间是否已经过了当天9点:
- 如果还没到,首次触发时间就是今天9点
- 如果已经过了,首次触发时间就是明天9点
这样就不会在启动App时立刻触发了。
给你一个计算这个时间的工具方法:
private Calendar getNext9AmTime() { Calendar calendar = Calendar.getInstance(); // 设置时间为今天9点 calendar.set(Calendar.HOUR_OF_DAY, 9); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); // 如果当前时间已经过了9点,就把日期加1天 if (System.currentTimeMillis() > calendar.getTimeInMillis()) { calendar.add(Calendar.DAY_OF_YEAR, 1); } return calendar; }
2. 修改你的setAlarm方法
在设置闹钟时,用上面计算出来的时间作为首次触发时间,而不是直接硬设当天9点。同时注意使用合适的AlarmManager方法,以及避免重复设置闹钟:
private void setAlarm() { AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(this, AlarmReceiver.class); // 这里要注意用唯一的requestCode,避免和其他PendingIntent冲突 PendingIntent pendingIntent = PendingIntent.getBroadcast( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // 获取下一次9点的时间 Calendar nextTriggerTime = getNext9AmTime(); // 设置重复闹钟:API 19之后setRepeating会变成不精确重复,如果需要精确可以考虑WorkManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { alarmManager.setExactAndAllowWhileIdle( AlarmManager.RTC_WAKEUP, nextTriggerTime.getTimeInMillis(), pendingIntent ); // 因为setExactAndAllowWhileIdle不支持重复,所以需要在AlarmReceiver里重新设置下一次闹钟 // 或者如果接受不精确重复,用下面的setInexactRepeating } else { alarmManager.setRepeating( AlarmManager.RTC_WAKEUP, nextTriggerTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent ); } }
3. 避免重复设置闹钟(可选但推荐)
每次启动App都调用setAlarm会导致重复注册闹钟,可能触发多次通知。可以在设置前先检查这个闹钟是否已经存在:
private boolean isAlarmAlreadySet() { Intent intent = new Intent(this, AlarmReceiver.class); return PendingIntent.getBroadcast( this, 0, intent, PendingIntent.FLAG_NO_CREATE | PendingIntent.FLAG_IMMUTABLE ) != null; }
然后在onCreate里调用时判断:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (!isAlarmAlreadySet()) { setAlarm(); } }
补充:关于API 19之后的精确重复闹钟
从Android 4.4(API 19)开始,setRepeating会变成不精确重复,系统会把多个闹钟合并触发来节省电量。如果你的需求是必须精确到9点触发,建议在AlarmReceiver的onReceive方法里处理完通知后,再重新设置下一次的闹钟(也就是用setExactAndAllowWhileIdle,每次触发后再设置第二天的9点)。
比如在AlarmReceiver里:
@Override public void onReceive(Context context, Intent intent) { // 显示你的通知逻辑 showNotification(context); // 设置下一次9点的闹钟 Calendar nextTriggerTime = getNext9AmTime(); // 这里可以把这个工具方法放到Receiver里或者一个公共类中 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent nextIntent = new Intent(context, AlarmReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 0, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { alarmManager.setExactAndAllowWhileIdle( AlarmManager.RTC_WAKEUP, nextTriggerTime.getTimeInMillis(), pendingIntent ); } else { alarmManager.setExact( AlarmManager.RTC_WAKEUP, nextTriggerTime.getTimeInMillis(), pendingIntent ); } }
这样就能保证每天9点精确触发,而且不会在启动App时立刻弹出通知啦!
内容的提问来源于stack exchange,提问作者Traif
相关产品推荐
相关产品推荐

