Search code examples
androidbroadcastreceiveralarmmanagerandroid-alarms

BroadcastReceiver fires with a delay


I have a TimePicker and a Button and I want to set an alarm when the user clicks on the Button at the time specified.

It gets the hour well when I click on the button but the alarm is being fired sometimes at the specified time, but not always. It is fired at the specified time less times than it does not fired. Most of the times the BroadcastReceiver does not fire at the specified time, it fires with a delay.

This is the code that I have right now:

On Alarm class (code refered to the BroadcastReceiver)

AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);

Calendar cal= Calendar.getInstance();

cal.set(Calendar.MONTH,cal.get(Calendar.MONTH));
cal.set(Calendar.YEAR,cal.get(Calendar.YEAR));
cal.set(Calendar.DAY_OF_MONTH,cal.get(Calendar.DATE));
cal.set(Calendar.HOUR_OF_DAY,hour);
cal.set(Calendar.MINUTE,minutes);


alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 60 * 5, alarmIntent);

where hour and minutes are the hour and minutes retrieved from the TimePicker.

On AlarmReceiver class

public class AlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("prove", "We enter on BroadcastReceiver");
    }
}

On Manifest.xml

<receiver
    android:name=".AlarmReceiver"
    android:enabled="true" >
</receiver>

For example, I have put a log to see what hour I was retrieving from TimePicker before show the log of BroadcastReceiver. I clicked it at 16:48 (on the TimePicker) and this is the result:

12-06 16:47:02.951 7980-7980/com.project.user.project D/prove: hour: 16:48
12-06 16:50:23.727 7980-7980/com.project.user.project D/prove: We enter on BroadcastReceiver
12-06 17:00:01.070 7980-7980/com.project.user.project D/prove: We enter on BroadcastReceiver

As you can see, the BroadcastReceiver has been fired two times at 16:50 and 17:00 when I suppose that they should fire at 16:48 and 16:53 because I have set that it will be a delay of 5 minutes between them, not 10 minutes as in this case.

So, what can I do to fire the alarm at the exact time and not fire it with a delay? Am I missing some configuration?

Thanks in advance!


Solution

  • As mentioned in the documentation, setRepeating is inexact.

    As of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above. Legacy applications whose targetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact

    So, to fire the alarm at the exact time as of API 19, use setExact, and inside each alarm set the next alarm.

    Schedule an alarm to be delivered precisely at the stated time.