63

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?

Shivam Kumar
  • 1,892
  • 2
  • 21
  • 33
Hassy31
  • 2,793
  • 3
  • 21
  • 37
  • Simply use the id field... check documentation for set on alarmmanager. – Warpzit Dec 12 '11 at 08:39
  • See my answer at this post http://stackoverflow.com/questions/12785702/android-set-multiple-alarms/31805171#31805171 – Junaid Aug 04 '15 at 09:14

7 Answers7

176

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.

Ziem
  • 6,579
  • 8
  • 53
  • 86
Parag Chauhan
  • 35,760
  • 13
  • 86
  • 95
  • 5
    how can we eventually cancel all of them ? we need to keep references of _id ? – TootsieRockNRoll Jan 21 '14 at 16:27
  • 1
    @user2427819 yes , for cancel we have to pass same id that we used for PendingIntent.getBroadcast – Parag Chauhan Jan 23 '14 at 17:17
  • @ParagChauhan Your Answers seems good, i didn't try it yet, Did it work if i want to modify my AlarmManager time ? – ULHAS PATIL Aug 06 '15 at 13:43
  • 1
    @ULHASPATIL Ofcourse it should work .its depend on its broadcast id so don't worry about alarmtime you can set any time as per your requirement. – Parag Chauhan Aug 06 '15 at 16:17
  • 5
    @Parag Chauhan: That's right for some reason Google hasn't implemented a simple cancelAll() call. Like in Nearby Messages there is no canceAll() so we have to implement massive amounts of code to achieve something simple. And our managers will not be glad because nobody would calulated that in. – Roel May 23 '16 at 07:59
  • @ParagChauhan Thank You. What does PendingIntent.FLAG_ONE_SHOT do? I road PendingIntent documentation but did not understand any thing about all flags. – hosseinAmini Oct 01 '16 at 15:07
  • In my case I was trying to show a notification using alarmManager, not putting a different `broadcast id` and `FLAG_ONE_SHOT` was causing duplicated notifications. This solved the issue. Thanks! – Isaac Bosca Feb 20 '18 at 11:32
  • can you please help me to fix this https://stackoverflow.com/questions/51267156/alarm-started-when-opening-the-app-instead-of-on-specific-time-in-android @ParagChauhan – Zhu Jul 10 '18 at 14:10
  • 1
    @hosseinAmini, PendingIntent.FLAG_ONE_SHOT - indicates that this PendingIntent can be used only once. – 4xMafole Jun 08 '21 at 13:49
11

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.

Reed
  • 14,703
  • 8
  • 66
  • 110
7

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.

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
2

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);
}
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
1

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())
    }
}
Muhammad Amir
  • 2,326
  • 1
  • 12
  • 13
0

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.

Pablo Valdes
  • 734
  • 8
  • 19
0

use different requestCode for the pending intents and use .FLAG_MUTABLE for type of Flag

int requestCode = (int) System.currentTimeMillis();
Intent intent = new Intent(load.this, AlarmReceiver.class);
return PendingIntent.getBroadcast(this, requestCode , intent, PendingIntent.FLAG_MUTABLE);
Mark Nashat
  • 668
  • 8
  • 9