15

Right now, I am setting alarms like this:

        AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, AlarmReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

        timedate = cal.getTime();

        //convert date to milis
        long timeInMilis = (timedate.getTime());

        //Set Alarm to Repeat
        manager.setRepeating(AlarmManager.RTC_WAKEUP, timeInMilis, interval, pendingIntent);

Unfortunately, the scheduled times for repeating are inexact and I read that they could be inexact for a full interval!

So, I would like to switch over to seting an exact repeating alarm. My device requires a minimum only of the latest API 19/Android 4.4, so I can't use setRepeating.

What can I do instead to set an exact repeating alarm?

Kala J
  • 1,958
  • 4
  • 40
  • 77
  • Read this post: http://stackoverflow.com/questions/24298595/how-to-set-an-exact-repeating-alarm-on-api-19-kitkat – Phantômaxx Nov 16 '14 at 16:55

1 Answers1

30

Unfortunately, the scheduled times for repeating are inexact and I read that they could be inexact for a full interval!

If your targetSdkVersion is 19 or higher, yes.

What can I do instead to set an exact repeating alarm?

Use setExact() to get control for your initial delay. Then, as part of your work for processing that event, use setExact() to get control at your next desired time. IOW, you do the "repeating" part yourself.

Yes, this is irritating.

It is intentionally irritating, to steer developers to not use exact repeating alarms, as those are worse for the battery than are their inexact brethren. If the user will perceive the inexact behavior and will not appreciate it, feel free to use setExact() to make the alarms occur when the user wants. However, if the user will not perceive the inexact behavior, please use inexact alarms, as the user may notice the battery impact of your exact alarms.

CommonsWare
  • 910,778
  • 176
  • 2,215
  • 2,253
  • I need to set an exact repeating alarm because that's the point of my application :( I wish I can use inexact. I guess my main question is I can use SetExact() above in my code but where should I schedule the alarm over again? In the broadcast receiver? how? – Kala J Nov 16 '14 at 17:01
  • 4
    @KalaJ: "In the broadcast receiver?" -- given the code in your question, yes. "how?" -- by calling `setExact()` on `AlarmManager` in `onReceive()`, indicating when you want to get control again. Bear in mind that "exact" is a bit of a misnomer, as Android is not a real-time OS, and so you will get control near your initial time, not precisely at that time. Hence, you will want to call `setExact()` in your `BroadcastReceiver` to specify when you want control "for realz", not just by incrementing X time from now, or the cumulative drift over several alarm cycles may cause you some problems. – CommonsWare Nov 16 '14 at 17:04
  • Okay but if i have several alarms that should be repeated exactly? I would just have to differentiate between them using a unique pending intent? and if so, then I would just say if this pending intent... then do this. If this pending intent, than do that? – Kala J Nov 16 '14 at 17:09
  • @KalaJ: Well, yes, but you had to do that anyway. `setExact()` versus `setRepeating()` did not change the requirement that for each distinct alarm, you need a distinct `PendingIntent`. – CommonsWare Nov 16 '14 at 17:10
  • Okay, thanks. I think I understand everything better now. Just one more question, if I put setExact() inside my broadcast receiver, can I still specify the interval/how often it repeats and does it repeat indefinitely after that like setRepeating? Do I need to do anything else that's special? – Kala J Nov 16 '14 at 17:12
  • 3
    @KalaJ: "can I still specify the interval/how often it repeats" -- no. `setExact()` is like the old `set()`. It is a one-off event. That's why you have to call it on each event to set up the next event. "does it repeat indefinitely after that like setRepeating?" -- no. That's why you have to call it on each event to set up the next event. "Do I need to do anything else that's special?" -- you have to call it on each event to set up the next event. – CommonsWare Nov 16 '14 at 17:15
  • 3
    @KalaJ: [My `PowerHungry` sample app](https://github.com/commonsguy/cw-omnibus/tree/master/JobScheduler/PowerHungry) demonstrates using `setExact()` to emulate an exact repeating alarm, though I am not worrying about event time drift. – CommonsWare Nov 16 '14 at 17:16
  • Awesome, thank you. I will take a look. What do you mean by "event time drift"? Thanks again. – Kala J Nov 16 '14 at 17:17
  • @KalaJ: "What do you mean by "event time drift"?" -- you ask for an alarm to go off at 10:05:00.000. In reality, you get control at 10:05:01.234, because it took a bit to get your process forked and so on. Now, when you go to schedule the next event, the simple thing to do is schedule it based on "now, plus my polling period". Suppose your polling period is 5 minutes. You will wind up scheduling the next alarm for 10:10.01.234 or thereabouts, instead of 10:10:00.000. You need to take this into account and schedule your events based on the actual time you want them to occur. – CommonsWare Nov 16 '14 at 17:22
  • If somehow an alarm is skipped(due to device power off) then what would happen(!!??). The pending alarm will be missed as well as the opportunity to set next days alarm. Isn't it? This is suicidal. – Mostafa Imran Oct 25 '16 at 08:08
  • @MostafaImran: No, it will be delayed until the device wakes up of its own accord (or until the next idle maintenance window, if the issue is that Doze mode blocked the alarm). – CommonsWare Oct 25 '16 at 11:19
  • @CommonsWare suppose I set an alarm for today with setExact(). Your strategy suggests that when the alarm today will ring(In receiver) another alarm for tomorrow will be set. If a user shuts his device for whole day today. Then how would the alarm ring today and how would next day's alarm would be set. This scenario explains google's strategical fault on AlarmManager's new APIs. – Mostafa Imran Oct 25 '16 at 12:04
  • @MostafaImran: Then do not use `setExact()`. Use something else that fits your needs better: `setExactAndAllowWhileIdle()`, `setAlarmClock()`, GCM/FCM, etc. If you have additional concerns in this area, search for other answers, and if you do not find one, ask a fresh Stack Overflow question. – CommonsWare Oct 25 '16 at 12:09
  • I am stuck in this situation bro. I need a daily alarm with precise timing. Currently I am following your your strategy :) but it's not that perfect as I explained why. On the other hand Marshmallow Doze mode has joined to ruin my life :(. – Mostafa Imran Oct 25 '16 at 12:15