I'm currently making a native Android app and I have code working to schedule a notification to appear on the device using the AlarmManager class:
Intent intent = new Intent(this, NotifyActivity.class);
AlarmManager alarmMgr = (AlarmManager)getSystemService(Activity.ALARM_SERVICE);
PendingIntent alarmIntent = PendingIntent.getService(this, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24*60*60*1000, alarmIntent);
Two things:
The notification goes off every time the app is opened. I don't want this to happen.
The notifications is suppose to be going off at 9am device time (or so I'm led to believe). This is not happening and it looks like it goes off every 9 hours or so.
Can anyone tell me why the notification goes off every time the app is opened and why the notification is not only being triggered when the device reaches 9am?
Thanks
From the doc of AlarmManager:
If the stated trigger time is in the past, the alarm will be
triggered immediately
You are setting your alarm to 9:00 , if you launch after this hour, trigger time is in the past, so the alarm is going off when the app is opened.
You can check if the current time is after alarm, if so, you add one day to the alarm and it will going off the next day. For example:
Calendar cal = Calendar.getInstance();
Calendar cal_now = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
if (cal.before(cal_now)) {//if its in the past
cal.add(Calendar.DATE, 1);
}
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 24*60*60*1000, alarmIntent);
Hope it helps,
Related
I need to the Android app to send notification to remind users at 8am, 3pm and 8pm every day. So I use the following three lines in onCreate() of the MainActivity, when the application starts. However, when I run the app, all three notification are coming at once instead of at the wanted time.
setRepeatedNotification(1,8,0,0);
setRepeatedNotification(2,15,0,0);
setRepeatedNotification(3,20,0,0);
Why is that? I also attach the setRepeatedNotification function here. Thank you!
private void setRepeatedNotification(int ID, int hh, int mm, int ss) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, ID, alarmIntent, 0);
Calendar calendar = Calendar.getInstance();
// calendar.set();
calendar.set(Calendar.HOUR_OF_DAY, hh);
calendar.set(Calendar.MINUTE, mm);
calendar.set(Calendar.SECOND, ss);
// Clear previous everyday pending intent if exists.
if (null != mEverydayPendingIntent) {
alarmManager.cancel(mEverydayPendingIntent);
}
mEverydayPendingIntent = pendingIntent;
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mEverydayPendingIntent);
}
Here is the updated code:
private void setRepeatedNotification(int ID, int hh, int mm, int ss) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent alarmIntent = new Intent(StartActivity.this, AlarmReceiver.class);
alarmIntent.putExtra("ID",ID);
Log.d("setRepeatedNotification", "ID:" + ID);
PendingIntent pendingIntent = PendingIntent.getBroadcast(StartActivity.this, ID, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
Calendar now = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hh);
calendar.set(Calendar.MINUTE, mm);
calendar.set(Calendar.SECOND, ss);
//check whether the time is earlier than current time. If so, set it to tomorrow. Otherwise, all alarms for earlier time will fire
if(calendar.before(now)){
calendar.add(Calendar.DATE, 1);
}
mEverydayPendingIntent = pendingIntent;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mEverydayPendingIntent);
}
I see two potential problems with your setup with AlarmManager. The first arises when the device goes to sleep.
From AlarmManager's documentation:
If an alarm is delayed (by system sleep, for example, for non _WAKEUP alarm types), a skipped repeat will be delivered as soon as possible. After that, future alarms will be delivered according to the original schedule; they do not drift over time. For example, if you have set a recurring alarm for the top of every hour but the phone was asleep from 7:45 until 8:45, an alarm will be sent as soon as the phone awakens, then the next alarm will be sent at 9:00.
As you can see, if you've set an alarm and the device has gone to sleep, without using AlarmManager.RTC_WAKEUP there could be a long delay depending on how long the device has been in sleep for. If you've never touched your device and no other alarms caused a wakeup, it could cause all your alarms to stack up upon the next hour that the device is awake for.
Another potential issue I see is that you are retrieving a Calendar instance representing the time right now, but then setting the hour, minute and second by yourself. The current day and the current year have been automatically populated from the current time.
Again, from the documentation (emphasis mine):
If the stated trigger time is in the past, the alarm will be triggered immediately, with an alarm count depending on how far in the past the trigger time is relative to the repeat interval.
In this case, if your method was invoked past 8 pm on the given day, calendar.getTimeInMillis() will return a timestamp in the past for all three alarms, causing them to be triggered immediately since 8 am, 3 pm and 8 pm have already past in that day. In this case, you must first evaluate whether the current time is past the alarm interval you are trying to set and add 1 day more onto the time you are setting to make sure the alarm has been set in the future.
I realize that this alarm triggers even after finish time in android is a similar question. However, mine's got a little bit different.
I wonder, for example, if i set time to be 14:40, and launch the app at 15:00 (or any other time after 14:40:00), the alarm manager's onReceive method will be triggered immediately.
Actually, this is a confirmation rather than a question since my application seems to do this.
Thank you !
CODE
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 14);
c.set(Calendar.MINUTE, 40);
c.set(Calendar.SECOND, 0);
//System.out.println();
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pendingIntent);
Try with the AlarmManager.setExact()
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setExact(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pendingIntent);
I am starting my alarm at 8am using below code, repeating at every 1min. I want to stop this alarm repeating at 12pm. I am starting alarm like this:
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent loggerIntent1 = PendingIntent.getBroadcast(this, 0,new Intent(this,AlarmReceiver.class), 0);
Calendar timeOff9 = Calendar.getInstance();
timeOff9.set(Calendar.HOUR_OF_DAY, 08);
timeOff9.set(Calendar.MINUTE, 00);
timeOff9.set(Calendar.SECOND, 00);
long duration = interval * 60 * 1000;
manager.setRepeating(AlarmManager.RTC_WAKEUP,timeOff9.getTimeInMillis(), duration, loggerIntent1);
and stopping with this code:
Calendar timeOff = Calendar.getInstance();
timeOff.set(Calendar.HOUR_OF_DAY,12);
timeOff.set(Calendar.MINUTE,00);
timeOff.set(Calendar.SECOND, 00);
manager.set(AlarmManager.RTC_WAKEUP,timeOff.getTimeInMillis(), loggerIntent1);
manager.cancel(loggerIntent1);
loggerIntent1.cancel();
but the code for stopping causes the app to work the wrong way.
I am writing the code to stop alarm right after first alarm. is it the problem?
Do I need to write another alarm. Please guide.
Maybe there is another logic you could give a try?
Imagine this, carry on with your first portion of code where you trigger an intent for every duration.
But inside your AlarmReceiver.class, that will be the one checking current time, and do the AlarmManager.cancel() when the time is over 12pm.
I´m making a widget app and I want a part of it update once a day with android:updatePeriodMillis="86400000" and another part update every minute with AlarmManager. But I think if you use AlarmManager you have to put to android:updatePeriodMillis="0". Is it possible to do that?
I believe that you can use both updatePeriodMillis and AlarmManager simultaneously. But in any case, you can always rely on AlarmManager for both updates, setting two different "Alarms" for the same widget update.
Finally this work (two alarms, one every minute and another every day):
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.SECOND, 00);
alarmManager.setRepeating(AlarmManager.RTC,
calendar.getTimeInMillis(),
60000, funtion1(context));
Calendar calendar2 = Calendar.getInstance();
calendar2.set(Calendar.HOUR_OF_DAY, 00);
calendar2.set(Calendar.MINUTE, 00);
calendar2.set(Calendar.SECOND, 00);
alarmManager.setRepeating(AlarmManager.RTC,
calendar2.getTimeInMillis(),
86400000, funtion2(context));
I wanted to know How I can set Alarm for a particular time. For example I want to set alarm for
morning 9am daily. I googled a lot but found only the way to set alarm for a given interval only. like after 2 hours or next day.
hope this code helps you
Calendar calendar = Calendar.getInstance();
//9 AM
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, new Intent(context, YourClass.class), PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
you should create BroadcastReceiver to receive intent.
read the documentation for further details
I googled a lot but found only the way to set alarm for a given interval only. like after 2 hours or next day.
The second parameter to setRepeating() on AlarmManager is when you want the alarm to go off first. Set that to be 9am tomorrow using a Calendar object, and use an RTC or RTC_WAKEUP alarm.