Vernon Clive Kawonza Vernon Clive Kawonza - 2 months ago 6x
Android Question

Scheduling repeated time-based alarms

I'd like to schedule multiple repeated time-based alarms. According to this android dev doc, "Repeating alarms that are based on a precise trigger time don't scale well", why that is, i dont understand. But i need this precise type of functionality. So what are my options? My main goal is to schedule the alarms using the AlarmManager class, and when the scheduled time occurs, issue a notification, but considering the dev doc, im not too sure about how to go about it.


I am using AlarmManager like you want to do in my project. In project I can schedule alarms for single time or daily, weekly, monthly, yearly. Actually its working good but OS can shift alarms for battery efficiency and some times could late like 1 minute. If you read this in AlarmManager.html#setRepeating :

Note: 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.

If you read accepted answer in there you get understand : alarmmanager-fires-alarms-at-wrong-time

And please read this selected answer too : alarmmanager-setexact-with-wakefulbroadcastreceiver-sometimes-not-exact

If you want to know which I am using : I am using Inexact Alarms because I don't want to consume battery cuz time is not critical in my app.

Please note that ; inexact Alarms more battery efficient. If time is not critical for you use inexact instead.

So, at the end if you want to see some code samples I have history in Bitbucket. I can give you my existing codes for reference, or if you update your question with your tries I can guide you.

@Edit for setExact:

First of all you must declare your alarms like that :

Intent alarmIntent = new Intent(getApplicationContext(), YourAlarmReceiver.class);
//this is important for you you must store this value
// you need this request code when shifting your Alarms
int piRequstCode=(int) System.currentTimeMillis();

For simple way you can store your pending intent request code like :

PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),piRequstCode,alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
//use mCalendarNotification to set your date for trigger
alarmManager.setExact(AlarmManager.RTC_WAKEUP, mCalendarNotification.getTimeInMillis(), pendingIntent);

Then in your BroadcastReceiver :

public void onReceive(Context context, Intent intent) {
    //right now you have your intent and context, so you can shift your alarm
   Bundle extras=intent.getExtras();
   int piRequestCode=extras.getInt("piRequestCode");
   Intent alarmIntent=new Intent(context, YourAlarmReceiver.class);

   // this will return your existing pending intent because your Intent and request code is same 
   // and FLAG_UPDATE_CURRENT updates pendingIntent with new config. 
   // If there is no pending Intent that matches with this requestCode and intent it will create new one.
   PendingIntent pendingIntent = PendingIntent.getBroadcast(context,piRequestCode,alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);

   //use AlarmManager with context
   AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
   alarmManager.set(AlarmManager.RTC_WAKEUP,shiftedTime, pendingIntent);