Android AlarmManager setExact() is not exact

The OS chooses how the alarms will work, with consideration of the time you’ve specified. Because of that, when the phone gets into a ‘semi-sleep’ mode, it won’t necessary use the resource at the time you wish it to. Basically, it waits for ‘windows’ that the OS opens for it, and only then the alarm you want to run will run, that’s why you’re experiencing time gaps.

This was introduced on Marshmallow OS and will continue on Nougat OS as well, as part of Google trying to improve the device’s battery.

Here’s the thing, you have 2 options:

  1. Accept the time delays (but maybe consider using JobScheduler which is more recommended and will save you battery).
  2. Use setExactAndAllowWhileIdle which might cause you battery issues (use this carefully, too many alarms will be bad for your battery).
    This method isn’t repeating, so you have to declare the next job to be run at the service which the pendingIntent opens.

If you choose option 2, here’s the start:

AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
int ALARM_TYPE = AlarmManager.RTC_WAKEUP;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    am.setExactAndAllowWhileIdle(ALARM_TYPE, calendar.getTimeInMillis(), pendingIntent);
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
    am.setExact(ALARM_TYPE, calendar.getTimeInMillis(), pendingIntent);
else
    am.set(ALARM_TYPE, calendar.getTimeInMillis(), pendingIntent);

Leave a Comment