报警管理器:如何安排每日报警并处理时间变化

我需要每天在给定的时间设置闹钟。我正在使用 对警报进行编程,因此它使用系统时间作为参考。我将警报设置为首先在所需的时间执行,然后每天重复:AlarmManager.RTC_WAKEUP

    alarmManager.setRepeating(
        AlarmManager.RTC_WAKEUP,
        getTimestampToday("12:00"),
        AlarmManager.INTERVAL_DAY,
        pendingIntent
    );

该方法在所需的时间返回今天的长时间戳。它通过获取今天的本地日期,然后设置所需的小时,最后将其转换回时间戳(基于UTC)来实现此目的。getTimestampToday

这里的问题是警报应该根据当地时间工作。因此,如果在安排警报后更改了时间(例如,DST 时间更改,或者用户转到了不同的国家/地区,或者他手动更改了日期、时间或时区),则警报将在下次的错误本地时间触发。

例:

  1. 警报设置为上午 8:00 首次点火,每天重复(即间隔 86400 秒)。
  2. 那天晚上,自动 DST 时间更改发生在凌晨 3:00,将时钟移回凌晨 2:00。
  3. 第二天早上,警报器在早上7点响起,这是错误的。

该应用旨在长时间运行(它是仅供企业使用的展台应用)。我正在重新安排应用程序启动时的警报,但这并不能解决我的问题,因为应用程序可以在不重新启动的情况下运行数天。我需要检测时间何时更改,以便根据新的本地时间再次安排警报。

我正在使用这个接收器:

    <receiver android:name="foo.bar.receivers.TimeChangeReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.ACTION_TIMEZONE_CHANGED" />
            <action android:name="android.intent.action.ACTION_TIME_CHANGED" />
            <action android:name="android.intent.action.DATE_CHANGED"></action>
        </intent-filter>
    </receiver>

它检测日期更改,但不适用于时间更改或时区更改。(在运行OS 4.0.3的平板电脑上进行了测试)。这真的很奇怪,因为我可以清楚地看到logcat中广播的事件。

所以我的问题:

  • 为什么我的广播接收者没有收到 和 事件,我该如何解决它。ACTION_TIMEZONE_CHANGEDACTION_TIME_CHANGED
  • 这些意图是否也会检测到 DST 时间变化?
  • 如果不可能,是否有更好的方法在当地时间对警报进行编程并处理时间变化?

提前致谢。


答案 1

您应该使用

<action android:name="android.intent.action.TIMEZONE_CHANGED" /> 
<action android:name="android.intent.action.TIME_SET" />

而不是

  <action android:name="android.intent.action.ACTION_TIMEZONE_CHANGED" />
  <action android:name="android.intent.action.ACTION_TIME_CHANGED" />

请参阅ACTION_TIMEZONE_CHANGEDACTION_TIME_CHANGED。并观察为这些常量给出的值。


对于 DST 更改,请阅读 Android AlarmManager 是否处理夏令时更改?


答案 2

推荐