You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么使用AlarmManager实现的年度闹钟在闰年仍按365天触发?

故障原因

直接触发原因

你的代码混用了两种历法实例导致闰年判断失效:
Calendar.getInstance()在部分定制系统、非中文公历地区默认返回的不是公历实例,可能是农历、和历等其他历法,你将非公历的年份传入公历GregorianCalendar的isLeapYear方法判断,会始终返回false,所以永远走365天的分支。

逻辑底层问题

你通过判断当前年份是否为闰年、手动加对应天数的方式实现年度提醒,逻辑本身就不成立:

  • 如果你设置提醒的时间在闰年的2月29日之后,到下一年同一天的实际间隔就是365天,此时就算当前是闰年加366天反而会错后1天
  • 无法处理2月29日的年度提醒在非闰年自动调整到2月28日的需求

修复方案

不要手动计算年度间隔,直接调用Calendar自带的年份增减方法,系统会自动处理历法、闰年、日期调整逻辑,代码如下:

mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
              
Intent intent1 = new Intent(context, AlarmReceiver.class);
intent1.putExtra(ReminderEditActivity.EXTRA_REMINDER_ID, Integer.toString(mReceivedID));
// Android 12及以上必须明确指定FLAG_IMMUTABLE或FLAG_MUTABLE,否则PendingIntent创建失败
mPendingIntent = PendingIntent.getBroadcast(context, mReceivedID, intent1, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);

// 统一使用公历实例避免历法差异
GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
// 直接增加1年,自动处理闰年逻辑
cal.add(Calendar.YEAR, 1);

mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), mPendingIntent);

补充说明:Android 12及以上系统需要申请SCHEDULE_EXACT_ALARM权限才能正常触发精确闹钟。


内容的提问来源于stack exchange,提问作者sai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 20:27:04