16

I am currently trying to write alarm manager that will make an alarm go off within a specified period of time, daily. First I check to see if the user has had an alarm set for that for that day:

      if ((User.getReminderTime(Home.this) > 0)
    && (dt.getDate() != today.getDate() || dt.getDay() != today
      .getDay())) {
   AppointmentManager.setFutureAppointmentCheck(this
     .getApplicationContext());
   User.setLongSetting(this, "futureappts", today.getTime());
  }

Then I go and set the actual alarm to go off between 12 and 12:10 of the next day:

     public static void setFutureAppointmentCheck(Context con) {
  AlarmManager am = (AlarmManager) con
    .getSystemService(Context.ALARM_SERVICE);

  Date futureDate = new Date(new Date().getTime() + 86400000);
  Random generator = new Random();

  futureDate.setHours(0);
  futureDate.setMinutes(generator.nextInt(10));
  futureDate.setSeconds(0);

  Intent intent = new Intent(con, FutureAppointmentReciever.class);

  PendingIntent sender = PendingIntent.getBroadcast(con, 0, intent,
    PendingIntent.FLAG_ONE_SHOT);

  am.set(AlarmManager.RTC_WAKEUP, futureDate.getTime(), sender);

 }

Now I setup a test environment for this to go off every two minutes and it seems to be working fine, however when I deploy to an actual device, the reciever does not seem to be recieving the alarms. I thought it might be an issue with the device being asleep, so I added the power manager. But it still does not work:

      PowerManager pm = (PowerManager) context
    .getSystemService(Context.POWER_SERVICE);
  PowerManager.WakeLock wl = pm.newWakeLock(
    PowerManager.PARTIAL_WAKE_LOCK, "keepAlive");
  wl.acquire();
  setFutureAppointments(context.getApplicationContext());
  AppointmentManager.setFutureAppointmentCheck(context
    .getApplicationContext());
  User.setLongSetting(context.getApplicationContext(), "futureappts",
    new Date().getTime());
  wl.release();

Anyone see anything I am doing blatantly wrong or am I going about this incorrectly? thanks for any and all help.

ninjasense
  • 13,756
  • 19
  • 75
  • 92

2 Answers2

43

I usually do something more along the lines of:

Intent i = new Intent(this, MyService.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.cancel(pi); // cancel any existing alarms
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
    SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY,
    AlarmManager.INTERVAL_DAY, pi);

This way, you don't have to worry about re-setting the AlarmManager in your Service.

I usually run this bit of code when my app starts (onResume in my main activity) and in a BroadcastReceiver that is set up to receive BOOT_COMPLETED.

I've written a guide on creating Services and using the AlarmManager, which is based on my own experience and a few tips & tricks I picked off from watching a Google I/O talk. If you're interested, you can read it here.


To answer your question below, all I can do is quote the docs:

public void setInexactRepeating (int type, long triggerAtTime, long interval, PendingIntent operation)

Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour. These alarms are more power-efficient than the strict recurrences supplied by setRepeating(int, long, long, PendingIntent), since the system can adjust alarms' phase to cause them to fire simultaneously, avoiding waking the device from sleep more than necessary.

Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time. In addition, while the overall period of the repeating alarm will be as requested, the time between any two successive firings of the alarm may vary. If your application demands very low jitter, use setRepeating(int, long, long, PendingIntent) instead.

In conclusion, it's not very clear. The docs only say that the alarm "may vary". However, it should be important for you to know that the first trigger might not occur for almost a full interval after that time.

Felix
  • 88,392
  • 43
  • 149
  • 167
  • I think that a service may be more than I need for what I'm doing, but your blog was a good read! Do you happen to know how much of an offset the SetInexactRepeating is usually? – ninjasense Dec 13 '10 at 17:52
  • 1
    I edited my answer to explain the `setInexactRepeating` problem. – Felix Dec 14 '10 at 10:45
  • 3
    as a bonus, instead of cancelling before setting a new one, you can retrieve the PendingIntent with PendingIntent.FLAG_CANCEL_CURRENT as last parameter, which has the same effect. – nsL Oct 18 '13 at 17:12
  • I have a question about the PendingIntent. suppose other classes use the alarmManager with the same request codes but with different intents that are used for other services/activities/receivers. would this be a problem ? do the request codes have to be unique across the entire app? what really happens in such a case? – android developer Feb 02 '14 at 13:18
  • @Felix i read your blog and do the same but instead of using repeating delay i use calendar ! but every time i open the app alarm triggered ! http://stackoverflow.com/questions/33981142/alarm-manager-trigger-every-time-app-running – user2549089 Nov 29 '15 at 09:44
  • if application is forced closed or removed from recent app then will it fire this recuring alarm manager ? many answer claims that it will but i didnt find any clue how and after trying many times it still didnt worked – KOTIOS Jan 19 '16 at 07:19
  • @Felix: If you cancel/recreate the alarm (in onResume as on your guide) and the first triggering of the alarm might be delayed up to one interval, does that mean it will actually run every *other* day, when set to a daily interval? – BeniBela Aug 29 '17 at 12:08
5

This is working, this will shoot alarm after every 5 seconds

private void setRecurringAlarm() {

        Logger.d(IConstants.DEBUGTAG, "Setting Recurring Alarm");

        Calendar updateTime = Calendar.getInstance();

        updateTime.set(Calendar.SECOND, 5);

        Intent alarmIntent = new Intent(this, AlarmReceiver.class);
        PendingIntent recurringDownload = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarms.cancel(recurringDownload);
        alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 1000 * 5, recurringDownload); //will run it after every 5 seconds.
    }
AZ_
  • 21,688
  • 25
  • 143
  • 191
  • what is the difference between setInexactRepeating and setRepeating ? – Jeff Bootsholz Sep 23 '13 at 07:05
  • 1
    Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour. These alarms are more power-efficient than the strict recurrences supplied by setRepeating(int, long, long, PendingIntent), since the system can adjust alarms' phase to cause them to fire simultaneously, avoiding waking the device from sleep more than necessary. – AZ_ Sep 23 '13 at 07:37