I want to be able to register two alarms to the same BroadcastReceiver. However, the first alarm never gets fired. How can I make this work?
Calendar now = Calendar.getInstance();
now.set(Calendar.SECOND, now.get(Calendar.SECOND) + 5);
long trigger1 = now.getTimeInMillis();
now.set(Calendar.SECOND, now.get(Calendar.SECOND) + 10);
long trigger2 = now.getTimeInMillis();
Intent startIntent = new Intent(AlarmStartReceiver.START_ALARM);
startIntent.putExtra(AlarmStartReceiver.EXTRA_ALARM_ID, 4);
PendingIntent startPIntent = PendingIntent.getBroadcast(context, 0, startIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent startIntent2 = new Intent(AlarmStartReceiver.START_ALARM);
startIntent2.putExtra(AlarmStartReceiver.EXTRA_ALARM_ID, 5);
PendingIntent startPIntent2 = PendingIntent.getBroadcast(context, 0, startIntent2, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, trigger1, startPIntent);
alarm.set(AlarmManager.RTC_WAKEUP, trigger2, startPIntent2);
Only the second one goes off. How can I make them both go off?
EDIT FOR ANSWER: Set the requestCode to something unique. The second param of the PendingIntent.getBroadcast) method
android pending intent notification problem
Set the requestCode to something unique. The second param of the PendingIntent.getBroadcast) method android pending intent notification problem
Are you looking for separate notification event for each alarm you are setting? Or it has to be same notification with number of alarm events showing on the status bar icon?
Look at this post on how you can use "setData()" to the intent to create separate alarms.
Alarm Manager - Scheduling multiple Non-repeating events
Related
I have to send 3 different notification(different content) at different time in a day.
Following the official documentation, https://developer.android.com/training/scheduling/alarms.html#type,
I was able to send notification at specified times, but having some trouble with changing the content of each notification. Following is the method to set notifications and is called in onCreate() method of MainActivity.
public void setNotification() {
Intent intent = new Intent(this, MyBroadcastReceiver.class);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
for (int id = 0; id < 3; id++) {
Calendar calendar = Calendar.getInstance();
// Defining different pendingIntent
switch (id){
case 0:
calendar.set(Calendar.HOUR_OF_DAY, 9);
break;
case 1:
calendar.set(Calendar.HOUR_OF_DAY, 14);
break;
case 2:
calendar.set(Calendar.HOUR_OF_DAY, 20);
break;
}
if(calendar.getTimeInMillis() < System.currentTimeMillis()){
calendar.add(Calendar.DATE, 1);
}
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id, intent, 0);
// setRepeating() schedules an alarm
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
I am aware that I can use Intent.putExtra() features to send data, which can be used to identify the intent, but this data will be lost if app is killed.
I want this to work even if app is not running or app gets killed or device is booted. After some reading I found out that I can use a BOOT_COMPLETE listener to set alarms after device is booted. Because of setting notifications in onCreate() method, notification is appearing everytime I run the app, even though I tried to tackle this by using following code
if(calendar.getTimeInMillis() < System.currentTimeMillis()){
calendar.add(Calendar.DATE, 1);
}
Currently onReceive method looks like this
public void onReceive(Context context, Intent intent) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.app_icon)
.setContentTitle("Title")
.setContentText("Message");
Intent resultIntent = new Intent(context, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
I need help in deciding where should I put setNotification() method so that it registers all alarms once and how to identify which intent is coming so that appropriate actions can be taken. One way to go about it is to define 3 different broadcastReceivers with intent filters and set intent URI while creating them. Is it the correct way or is there any other simple solution?
notification is appearing everytime I run the app,
Keep a check using SharedPreference and set only once if not done.
Also your code
if(calendar.getTimeInMillis() < System.currentTimeMillis()){
calendar.add(Calendar.DATE, 1);
}
should be somewhat like this
Calendar calendar = Calendar.getInstance();
// Get the current time in millis
long currentTime = calendar.getTimeInMillis();
// Set the reminder times
switch(id) {
..
..
}
//Get the reminder time in millis
long intendedTime = calendar.getTimeInMillis();
if (intendedTime < currentTime) {
// Set from next day and to repeat once a day.
// you might consider using calendar.add() for adding one day to the current day
calendar.add(Calendar.DAY_OF_MONTH, 1);
intendedTime = calendar.getTimeInMillis();
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
intendedTime, AlarmManager.INTERVAL_DAY, pendingIntent);
} else {
// Set for today and to repeat once a day.
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, intendedTime,
AlarmManager.INTERVAL_DAY, pendingIntent);
}
how to identify which intent is coming so that appropriate actions can
be taken
You need to set an action to Intent in order to receive data in BroadcastReceiver
Intent intent = new Intent(this, MyBroadcastReceiver.class);
intent.setAction("THIS_IS_MY_ACTION");
Case of BOOT_COMPLETE
Cancel all the alarm on Boot, and reset them. To cancel an alarm Call cancel() on AlarmManager with an same PendingIntent which you have used while setting an alarm using setRepeating().
Take care of context and INTENT_FLAGS while working with AlarmManager.
Use getApplicationContext() for context and Keep records of request_code as they are going to be used while cancelling an alarm, use PendingIntent.FLAG_UPDATE_CURRENT
This might help:-
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), request_code, intent, PendingIntent.FLAG_UPDATE_CURRENT)
I am trying to set repeating alarms in an exact fashion by manually setting an alarm to the next day the moment I receive it in a broadcast. However, I might be missing something and somehow its not working.
The Logic:
When I select the time from a time chooser, I set an exact alarm to the time given and start a pending intent which calls MyBroadCastReceiver.java (extends BroadcastReceiver) when its time. I then forward the intent with another pending intent to AlarmFireActivity. (AlarmFireActivity also has snooze which simply sets a pendingIntent to itself to fire after 5 mins.)
The MyBroadCastReceiver component hence only receives the actual alarms (not snoozes). And its functions are :
a) Get the non-repeating pending intent cancel it, then create another pending intent from the intent and then set it with the milliseconds set to the next day at the same time.
b) Start the AlarmFireActivity and show the alarm.
In AddAlarmActivity
Intent intent = new Intent(context, MyBroadcastReceiver.class);
intent.putExtra(DBHelper.COLUMN_ID,alarm.getId());
AlarmManager alarmManager = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, reminder.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, reminder.getHourOfDay());
calendar.set(Calendar.MINUTE, reminder.getMinuteOfHour());
calendar.set(Calendar.SECOND,0);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
pendingIntent);
BLog("Pending intent added at " + new SimpleDateFormat(utilFunctions.timeFormat).format(calendar.getTime()));
}
Snippet MyBroadCastReceiver.java TaskOne
Logic
Get the intent which MyBroadCastReceiver receives. Reuse the same intent in a new PendingIntent set to the next day at the same time.
Code
AlarmManager alarmManager = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
PendingIntent p1 = PendingIntent.getBroadcast(context, alarmCurrent.getReminderId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
if(p1!=null){
alarmManager.cancel(p1);
}
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, alarmCurrent.getReminderId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
//for test
calendar.add(Calendar.MINUTE,1);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
pendingIntent1);
}
MyBroadCastReceiver.java TaskTwo
Logic
If the time when the alarm was set was after the time the alarm is due, do not forward the pending intent to the AlarmFireActivity.
Else forward it to the AlarmFireActivity which shows the screen to dismiss/snooze the alarm.
Code
Calendar timeSet = alarmCurrent.getAlarmReminderSetTime();
Calendar alarmTime = Calendar.getInstance();
if(timeSet!=null && alarmTime.getTimeInMillis() > timeSet.getTimeInMillis()){
Intent intent1 = new Intent(context, AlarmFireActivity.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.putExtra(DBHelper.COLUMN_ID,id);
String ext = extras.getString(DBHelper.TASK_TITLE);
if(ext!=null){
intent1.putExtra(DBHelper.TASK_TITLE,ext);
}
context.startActivity(intent1);
}else{
}
The BroadCastReceiver is doing the second task just fine. However, not the task one. Its not repeating/ resetting a new pending intent. I am guessing I must have messed up the intent/pendingIntent somewhere. I dont know which. Please help/
The solution is restart the phone. I have seen somewhere that there is a bug in a one of the os' 4.3 or so. A pending intent with a request id of 0 might fail at times. And once I restarted the phone it worked. However, there is a more standard solution which is :
Replacing
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, reminder.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
with
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, A_NUMBER_GREATER_THAN_ZERO + reminder.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
so that you are avoiding a pending intent with 0 at all times. Thanks all!
in my task application, i want to create alarm service for multiple items. Here is the code i followed to create service. Lets assume, if there are more than 5 items present in list. then we will sent alarm service for 5 different times.
What if the user comes and edits the time?, how to update the system and make sure it triggers at new instance?. What if the user delete the task, how to quickly removes the registered alram for the deleted task?
What about uninstalling the app?, how to clear all the entries?, what if the system re-boots?
This is the code i'm following to register the task in alram services
Calendar Calendar_Object = Calendar.getInstance();
Calendar_Object.set(Calendar.MONTH, 8);
Calendar_Object.set(Calendar.YEAR, 2012);
Calendar_Object.set(Calendar.DAY_OF_MONTH, 6);
Calendar_Object.set(Calendar.HOUR_OF_DAY, 14);
Calendar_Object.set(Calendar.MINUTE, 25);
Calendar_Object.set(Calendar.SECOND, 0);
Step 2:
We need to create an alarm which help us to invoke the BroadCastReceiver on our specified time.
// MyView is my current Activity, and AlarmReceiver is the BoradCastReceiver
Intent myIntent = new Intent(MyView.this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
MyView.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
/*
The following sets the Alarm in the specific time by getting the long value of the alarm date time which is in calendar object by calling the getTimeInMillis(). Since Alarm supports only long value , we're using this method.
*/
alarmManager.set(AlarmManager.RTC, Calendar_Object.getTimeInMillis(),
pendingIntent);
Use this method to set Alarm :
public static void startAlarm(Context context, int alarm_code, String time) {
String[] arrTime = time.split(":");
intent = new Intent(context, AlarmReceiver.class);
intent.putExtra("CODE", alarm_code);
PendingIntent mAlarmSender = PendingIntent.getBroadcast(context,
alarm_code, intent, 0);
Calendar cal_alarm = Calendar.getInstance();
cal_alarm.setTimeZone(TimeZone.getDefault());
cal_alarm.set(Calendar.HOUR_OF_DAY, Integer.parseInt(arrTime[0]));
cal_alarm.set(Calendar.MINUTE, Integer.parseInt(arrTime[1]));
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal_alarm.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, mAlarmSender);
}
Here,"int alarm_code" is your unique code for particular item.
And for update alarm first cancel the existing alarm and set new alarm for new time.For that use this method :
public static void cancelAlarm(Context context, int alarm_code) {
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra("CODE", alarm_code);
am.cancel(PendingIntent.getBroadcast(context, alarm_code, intent, 0));
}
Here,"int alarm_code" will be your unique code which you have used to set alarm.So that alarm with particular alarm_id will be cancel.You can also delete alarm with this method.
Same way you can clear all the alarms passing alarm_code to the given function.
You have to register receiver for system reboot and in onReceive of register you have to set all alarms again.
Hope this will help you.
Here's the code I'm using to try and set up an AlarmManager:
feedingIntent = new Intent(this, FeedingAlarmReceiver.class);
feedingPI = PendingIntent.getBroadcast(this, 0, feedingIntent, 0);
feedingAM = (AlarmManager) getSystemService(ALARM_SERVICE);
feedingAM.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60000, feedingPI);
I basically want the feedingIntent to trigger after a minute after a button press. When I check logcat after I press the button it says my intent is null:
V/AlarmManager﹕ sending alarm PendingIntent{435f7ac8: PendingIntentRecord{435b8ed0 com.example.parentingreminders broadcastIntent}}, intent=null, type=ELAPSED_REALTIME_WAKEUP, count=1, when=959128249, repeateInterval=0
This is my first time using AlarmManager and I'm not sure what I'm doing wrong.
Thanks in advance!
You need to set the corresponding action in feedingIntent to trigger the receiver
feedingIntent.setAction(Intent.ACTION_XXXX);
I want to set a multiple alarm in android. please help me in achieving this task.
Thanks &Regards
Pawan Pathak
You probably need to use multiple intents.
In this example I set 2 alarms, one after 10 seconds and another one after 15 seconds.
Hope it helps.
// set first alarm
Calendar time1 = Calendar.getInstance();
time1.add(Calendar.SECOND, 10);
// set intent to be fired
PendingIntent sender1 = PendingIntent.getBroadcast(this, 1, new Intent(this, AlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
// set alarm manager
AlarmManager alarm1 = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarm1.set(AlarmManager.RTC_WAKEUP, time1.getTimeInMillis(), sender1);
// set second alarm
Calendar time2 = Calendar.getInstance();
time2.add(Calendar.SECOND, 15);
// set intent to be fired
PendingIntent sender2 = PendingIntent.getBroadcast(this, 2, new Intent(this, AlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
// set alarm manager
AlarmManager alarm2 = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarm2.set(AlarmManager.RTC_WAKEUP, time2.getTimeInMillis(), sender2);