AlarmManager: how to schedule a daily alarm and de

2019-03-27 07:56发布

问题:

I need to set up an alarm daily at a given hour. I'm programming the alarm using AlarmManager.RTC_WAKEUP, so it uses the system time as reference. I'm setting the alarm to first execute at the desired hour, then to repeat daily:

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

The getTimestampToday method returns a long timestamp for today at the desired hour. It does so by obtaining the local date for today, then setting the desired hour, finally converting it back to a timestamp (which is UTC based).

The problem here is the alarm should work according to the local time. So if the time changed after the alarm is scheduled (for instance, DST time change, or the user goes to a different country, or he changes the date, time or timezone manually), then the alarm will fire at the wrong local time the next time.

Example:

  1. Alarm set to first fire at 8:00 AM, repeat daily (meaning 86400 seconds of interval).
  2. That night, an automatic DST time change happens at 3:00 AM, shifts the clock back to 2:00 AM.
  3. Next morning, the alarm fires at 7:00 AM, which is wrong.

The app is meant to be running for long periods of time (it is a kiosk app for corporate use only). I'm re-scheduling the alarms when the app starts, but this does not solve my problem, because the app can run for days without being restarted. I need to detect when the time changes to schedule the alarms again according to the new local time.

I'm using this receiver:

    <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>

It detects the date change, but does not work with time changes nor time zone changes. (Tested it on a tablet running OS 4.0.3). It is really odd, because I can clearly see the events being broadcasted in logcat.

So my questions:

  • Why are the ACTION_TIMEZONE_CHANGED and ACTION_TIME_CHANGED events not being received by my BroadcastReceiver, and how could I solve it.
  • Would these intents detect a DST time change as well?
  • If not possible, is there a better approach to program alarms at local times and deal with time changes?

Thanks in advance.

回答1:

You should use

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

Instead-of

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

Refer at ACTION_TIMEZONE_CHANGED and ACTION_TIME_CHANGED. And observe the value given for these Constants.


And for DST changes read Does Android AlarmManager handle daylight saving changes?