alarmmanager – How to set multiple alarms using alarm manager in android-ThrowExceptions

Exception or error:

I’m building an alarm application. I have successfully implemented basic alarm functions.

Calendar calendar = Calendar.getInstance();
calendar.set(calendar.HOUR_OF_DAY, sHour);
calendar.set(calendar.MINUTE, sMin);
calendar.set(calendar.SECOND, 0);
calendar.set(calendar.MILLISECOND, 0);
long sdl = calendar.getTimeInMillis();

Intent intent = new Intent(AlarmList.this, AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(AlarmList.this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager ALARM1 = (AlarmManager)getSystemService(ALARM_SERVICE);
ALARM1.set(AlarmManager.RTC_WAKEUP, sdl, sender);

In my application, user can select days (sunday,monday...) to repeat the alarm weekly.
I’m trying to create multiple alarms to repeat weekly but don’t know how to do it.
Can I create it using (repeat) interval or should I create multiple alarm managers?

How to solve:

You need to use different Broadcast id's for the pending intents. Something like
this:

Intent intent = new Intent(load.this, AlarmReceiver.class);
final int id = (int) System.currentTimeMillis();
PendingIntent appIntent = PendingIntent.getBroadcast(this, id, intent, PendingIntent.FLAG_ONE_SHOT);

Using the system time should be a unique identifier for every pending
intent you fire.

###

From the docs:

If there is already an alarm for this Intent scheduled (with the
equality of two intents being defined by filterEquals(Intent), then
it will be removed and replaced by this one

Multiple AlarmManagers would not resolve your issue. If they have multiple different alarms (different times and different days), then you would need to set the alarm within the BroadcastReceiver every time you fire off a previous alarm.

You would also need to hold RECEIVE_BOOT_COMPLETED and have a BroadcastReceiver to receive the boot so that if the phone is rebooted you can re-schedule your alarms.

###

To set multiple alarms you need to define your Intent each time so that it is distinguishable from the others. The easiest way I find to do this is to set the data field of your Intent something as follows:

// give your alarm an id and save it somewhere
// in case you want to cancel it in future
String myAlarmId = ...;

// create your Intent
Intent intent = new Intent(AlarmList.this, AlarmReceiver.class);
intent.setData(Uri.parse("myalarms://" + myAlarmId));
...

The rest of your code @Hassy31 is fine as is and remains unchanged.

Note that the requestCode parameter in the PendingIntent.getBroadcast() method (as suggested by @parag) is unused according to the documentation so this ain’t the right way to go about it.

###

set Broadcast id for pendingIntent

for (int id = 0; id < 3; id++) {
        // Define pendingintent
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id,ntent, 0); 
        // set() schedules an alarm 
        alarmManager.set(AlarmManager.RTC_WAKEUP, alertTime, pendingIntent);
}

###

Set multiple alarms using android alarm manager

//RC_ARRAY is store all the code that generate when alarm is set 
private lateinit var RC_ARRAY:ArrayList<Int>
//tick is just hold the request when new alarm set
private var tick :Int=0

//setAlarm method set alarm
fun setAlarm(c: Calendar, context: Context) {
    val manager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

//when alarm store set the request assign to tick variable
    tick = System.currentTimeMillis().toInt()
//Add all the alarm Request into RC_ARRAY for just cancel the alarm
    RC_ARRAY.add(tick)

//Notification Broadcast intent
    val intentAlarm = Intent(context, AlaramFireReceiver::class.java).let {
        PendingIntent.getBroadcast(context, tick, it, PendingIntent.FLAG_ONE_SHOT)
    }


//alarm fire next day if this condition is not statisfied 
    if (c.before(Calendar.getInstance())) {
        c.add(Calendar.DATE, 1)
    }
//set alarm
    manager.setExact(AlarmManager.RTC_WAKEUP, c.timeInMillis, intentAlarm)


}
//remove specific alarm
private fun removeAlarm(context: Context) {
    val manager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    //remove specific alarm according to alarm request code
    for (i in RC_ARRAY){
        val intentAlarm = Intent(context, AlaramFireReceiver::class.java).let {
            PendingIntent.getBroadcast(context, i, it, 0)
        }
//cancel alarm
        manager.cancel(intentAlarm)
    }
}



//delivers notification for alarm
class AlaramFireReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
//Notification ID
       val channelid="channelId"
        val manger=context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//check for device only available for Oreo and above  
        if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.O){
            val channel= NotificationChannel(channelid,"alarm notification",NotificationManager.IMPORTANCE_HIGH)
            channel.enableLights(true)
            manger.createNotificationChannel(channel)
        }
//build notification
        val build=NotificationCompat.Builder(context,channelid)
            .setSmallIcon(R.drawable.ic_access_time_black_24dp)
            .setContentTitle("alarm")
            .setContentTitle("time done")
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setColor(Color.RED)
//Deliver notification 
        manger.notify(0,build.build())
    }
}

###

What I do is something similar to how you move to the next element in a linked list. I keep in database a ReminderEntity that has all the days of the week the user enabled the Alarm to go off.
Then I schedule the first day only. When the first day triggers then in that moment I schedule the next day and so on.
Same thing if the user deletes the first coming Alarm before it happens. In this case I clear the removed day from the entity and schedule an alarm for the next one available.

Leave a Reply

Your email address will not be published. Required fields are marked *