13

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.

Mister Smith
  • 27,417
  • 21
  • 110
  • 193
  • good question. I am using the ACTION_TIME_CHANGED and sadly not only than is called, when the user change it, but around 2-3 times in 1 hour. I have no idea how to deal with those spaming callbacks –  Oct 17 '13 at 08:27
  • 2
    @matheszabi Maybe the device is actually syncing with the time server 2-3 times per hour? – Mister Smith Oct 17 '13 at 08:29
  • Very good question, +1. Hope anyone has a good answer for this! – Carnal Oct 17 '13 at 08:35
  • @MisterSmith I think `android:exported="true"` can do the task. Add this to receiver.. – Pankaj Kumar Oct 17 '13 at 08:42
  • @PankajKumar Will try. But according to [the docs](http://developer.android.com/guide/topics/manifest/receiver-element.html), the default value is `true` if there's at least one intent filter defined. – Mister Smith Oct 17 '13 at 08:46
  • 1
    Yes you are right. Did you tried `android.intent.action.TIME_SET` action? – Pankaj Kumar Oct 17 '13 at 08:51
  • @PankajKumar Yes, you are right. I was using the Java constant name for `ACTION_TIMEZONE_CHANGED` and `ACTION_TIME_CHANGED`. Should be `TIMEZONE_CHANGED` and `TIME_SET` instead. You might want to post that as an answer. – Mister Smith Oct 17 '13 at 09:06
  • @MisterSmith very nice, I forgot that. I am asking to put the time to auto sync, very probably that is the reason, but I need to handle those changes when he travel to other country and has +/- 1 hour adjustment, not sure if I get ACTION_TIMEZONE_CHANGED callback too –  Oct 17 '13 at 17:55

1 Answers1

8

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?

Community
  • 1
  • 1
Pankaj Kumar
  • 81,967
  • 29
  • 167
  • 186
  • Thanks. Do you know if this would also detect the DST transition? – Mister Smith Oct 17 '13 at 09:15
  • Hey DST changes will be handled by AlarmManager itself. Read more at http://stackoverflow.com/questions/8377853/does-android-alarmmanager-handle-daylight-saving-changes – Pankaj Kumar Oct 17 '13 at 09:28
  • I don't think so, but I can't spend more time testing this. BTW, just finished a test (took me 1 hour to test DST) and these events are not fired. Looks like they only detect user-initiated time changes. What I'm doing now is re-scheduling all alarms on Sunday at 4:30 AM (DST changes here are always on sundays and always in the 2:00-3:00 interval. This should also help with network time syncs during the week. – Mister Smith Oct 17 '13 at 10:38
  • BroadcastReceiver onReceive called mutiple times when changing the date or time manually, in manifest i use this two as intent filters TIME_SET and DATE_CHANGED – Sarath Kumar Aug 04 '17 at 13:09