BiGGZ
BiGGZ

Reputation: 503

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.

EDIT:

Iv managed to schedule my alarms, which arnt exactly repeated time-based alarms in the strictest sense of recurring repeatedly after a set time interval, but "repeating" in the sense of setting multiple alarms. Now when I set my date and time on the Calendar, the month gets set for a month ahead, if i put 10, it sets the month to 11, heres my code:

Calendar cal = Calendar.getInstance();
String date = "23/10/2016";//month set to 10
String[] _date = date.split("/");
String time = "4:33";
String[] _time = time.split(":");

Intent intent = new Intent(test.this,
            AlarmReceiver.class);


intent.setData(Uri.parse("timer:555"));

PendingIntent sender = PendingIntent.getBroadcast(
            test.this, 0, intent,
            0);

cal.set(Integer.parseInt(_date[2]), //year
        Integer.parseInt(_date[1]), //month
        Integer.parseInt(_date[0]), //day
        Integer.parseInt(_time[0]), //hour
        Integer.parseInt(_time[1]));//minute

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);

Toast mToast = Toast.makeText(
            test.this,
            "Reminders added to the calendar successfully for "
                    + android.text.format.DateFormat.format(
                    "MM/dd/yy h:mmaa",
                    cal.getTimeInMillis()),
            Toast.LENGTH_LONG);
mToast.show();//month displayed is 11

Upvotes: 0

Views: 342

Answers (1)

Yasin Kaçmaz
Yasin Kaçmaz

Reputation: 6663

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 :

alarmIntent.putExtra("piRequestCode",piRequstCode);
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 :

@Override
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);
   alarmIntent.putExtra("piRequestCode",piRequstCode);

   // 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.setExact(AlarmManager.RTC_WAKEUP,shiftedTime, pendingIntent);
}

There is one more thing, when device rebooted all alarms will lost. And you must reset your Alarms by manually. So storing pendingIntent request codes in Database (Sqlite, Realm etc...) or SharedPreferences(if you don't have much data) is good strategy. Right now I am using Realm to store requestCodes and all the other things, so I recommend you to use Database.

At the end to be clear if you need more help when doing this steps, create new questions or edit this question and I'll help you.

Upvotes: 1

Related Questions