0

In Android, I use the AlarmManager to set a repeating task that is executed once per day. The user can choose the time for this alarm. When he chooses 9:00 o'clock for example, a given task is executed every day at 9 o'clock, i.e. a pending intent is started that puts a notification to the notification bar.

Users of my app say that when their device was switched off at that time, there is no notification at all. Is it true that, when the device is off at the time when an alarm goes off, the alarm isn't repeated after booting again?

If this is normal behaviour, how could that be circumvented? Should I write a shared preference (e.g. "last_execution_time") in the IntentService that triggers the notification? And on boot-up, I can just check if the last execution has been more than 24 hours before, and if so, repeat it?

caw
  • 30,999
  • 61
  • 181
  • 291

1 Answers1

0

Register broadcast receiver for intent with action android.intent.action.BOOT_COMPLETED, which would start the same task as you scheduled with AlarmManager (formerly ensuring that it was not fired in due time by AlarmManager).

EDIT: for keeping track try sth like that (its just a tip - handle exact time around 9 securely on your own ;)

public class KeepTrackReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        SharedPreferences p = context.getSharedPreferences(
                TrackedAlarmService.FILE_ALARM_TRACK, Context.MODE_PRIVATE);
        long lastAlarm = p.getLong(TrackedAlarmService.KEY_LAST_ALARM_MILLIS, -1L);
        if(lastAlarm == -1L || lastAlarm < TrackedAlarmService.getClosest9AM(false)) {
            context.startService(TrackedAlarmService.createIntent(context));
        }

    }
}
public class TrackedAlarmService extends IntentService {

    public static final String FILE_ALARM_TRACK = "alarmTrack";
    public static final String KEY_LAST_ALARM_MILLIS = "lastAlarmMillis";

    public static void schedule(Context context) {
        AlarmManager am = (AlarmManager) context.getSystemService(
                Context.ALARM_SERVICE);

        PendingIntent pi = PendingIntent.getService(context, 0, 
                createIntent(context), PendingIntent.FLAG_CANCEL_CURRENT);

        am.setRepeating(AlarmManager.RTC_WAKEUP, getClosest9AM(true), 
                AlarmManager.INTERVAL_DAY, pi);
    }

    public static long getClosest9AM(boolean futurePastFlag) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(System.currentTimeMillis());
        if(futurePastFlag) {
            if(c.get(Calendar.HOUR_OF_DAY) > 9) {
                c.roll(Calendar.DATE, true);
            }
        }
        else {
            if(c.get(Calendar.HOUR_OF_DAY) < 9) {
                c.roll(Calendar.DATE, false);
            }
        }
        c.set(Calendar.HOUR_OF_DAY, 9);
        c.set(Calendar.MINUTE, 0);
        return c.getTimeInMillis();
    }

    public static Intent createIntent(Context context) {
        return new Intent(context, TrackedAlarmService.class);
    }

    public TrackedAlarmService() {
        super("TrackedAlarmService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        //save last alarm time  
        getSharedPreferences(FILE_ALARM_TRACK, MODE_PRIVATE)
            .edit()
            .putLong(KEY_LAST_ALARM_MILLIS, System.currentTimeMillis())
            .commit();

        // Do your repeating job....
    }
}
Tomasz Gawel
  • 8,379
  • 4
  • 36
  • 61
  • Thank you. My question was actually *how* to ensure that the task has not already been fired before. It's obvious that I need a broadcast receiver for `BOOT_COMPLETED` here. – caw Jul 06 '12 at 22:27
  • just keep track of it, i thought it's much more obvious ;) – Tomasz Gawel Jul 06 '12 at 22:32