Search code examples
androidscheduled-tasksandroid-alarms

Android set repeating task at same time everyday using AlarmManager


Have to schedule an event at 8 pm (the clock shows 8 pm) everyday irrespective of the user moving across different timezones. Set repeating with interval of one day will not deliver it at the correct time. How to approach this?

This is the closest I've got so far.

Code snippet:

private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

// Set the alarm to start at 20:00 PM
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 20);
calendar.set(Calendar.MINUTE, 0);

// setRepeating() lets you specify a precise custom interval--in this case,
// 1 day
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        AlarmManager.INTERVAL_DAY, alarmIntent);

Solution

  • To take TimeZonechanges into consideration, you need to register a TIMEZONE_CHANGED broadcast receiver:

    <receiver android:name=".TimeZoneBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.TIMEZONE_CHANGED " />
        </intent-filter>
    </receiver>
    

    I would save the current TimeZone and then retrieve it when the next alarm occurs so we can double check if any changes took place, so the java code will be something like:

    public class TimeZoneBroadcastReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
            String timeZoneOLD = pref.getString(PREF_TIMEZONE, null);
            String timeZoneNEW = TimeZone.getDefault().getID();   
            long now = System.currentTimeMillis();
    
            if (timeZoneOLD == null || TimeZone.getTimeZone(timeZoneOLD).getOffset(now) != TimeZone.getTimeZone(timeZoneNEW).getOffset(now)) {
                    pref.edit().putString(PREF_TIMEZONE, timeZoneNEW).commit();
                    // This means that the TimeZone has changed so we need to update the alarm
                    // Set Alarm method goes HERE ...
        }
    
    }
    

    For more info about how to setup a recurring task using Alarm Manager, the following is a good tutorial: