I have a service that I would like to be executed daily in my application. The service should only be executed ONCE per day. For some reason my service gets fired several times throughout the day, I do not know what is going on. Here is my alarmmanger set up:
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,new Intent(this,ReviewReceiver.class),PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE));
Random random = new Random();
int hour = random.nextInt(22 - 7) + 7;
int minute = random.nextInt(60 - 1) + 1;
Calendar cal = new GregorianCalendar();
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE,minute);
cal.set(Calendar.SECOND,5);
cal.set(Calendar.MILLISECOND,5);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(),AlarmManager.INTERVAL_DAY,
pendingIntent );
I have set the alarm to randomly set itself between 7 am and 10 pm upon installation of the application.
So for example, when the alarm sets itself at 13h30, the service will be fired at that time properly. But therafter, it will get fired over and over at random intervals throughout the day. What am I doing wrong. Please help.
P.S. I have already tried using ELAPSED_TIME, ELAPSED_TIME_WAKEUP and they do not work
For Lollipop and greater (M preview also have this behavior), the alarm have a strange behavior if you don't set it in the future and at least adding 5s.
alarmManager.setInexactRepeating(
AlarmManager.RTC_WAKEUP,
now + 5s,
AlarmManager.INTERVAL_DAY,
pendingIntent );
The 5s is a known issue. and since this problem occurred (especially with my nexus 5), I am just using set() that a recall every day instead of setInexactRepeating()
Related
I have had several frustrations with setting alarms in Android. I have tried setting repeating/non-repeating alarms and exact/inexact alarms but it does not matter, if the alarm is ever set for a time in the past, it executes as soon as it is set. I have tested this as far back as setting an alarm for 5 hours in the past and is still executes immediately.
For example:
The time is 7 AM and I set an alarm to execute at 2 AM. This is obviously meant for the next time the clock reads 2:00 AM but it does not matter, the alarm goes off at 7 AM, right after it is set.
The code below should select a random time between 1:00 AM and 3:59 AM to set/execute the alarm for the next calendar day and then the logic circles back around to set itself again after execution. The alarm will execute repeatedly, forever.
int randomHour = new Random().nextInt((3 - 1) + 1) + 1;
int randomMinute = new Random().nextInt((59 - 1) + 1) + 1;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, randomHour);
calendar.set(Calendar.MINUTE, randomMinute);
calendar.set(Calendar.SECOND, 0);
calendar.add(Calendar.DAY_OF_MONTH, 1);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Questions:
At what point does Android stop executing alarms in the past?
Is there any way to stop this?
"This is obviously meant for the next time" Does not work for computers, they will do exactly what you tell them to do.
calendar.getTimeInMillis() returns the number of milliseconds since January 1, 1970 at 00:00:00 GMT. You need to specify not just the time but also the date that you want the alarm to go off. Instead you are always calling calendar.add(Calendar.DAY_OF_MONTH, 1); (the first day of the current month)
I want to trigger a notification each day at a specific time choosen by the user, like 6' / 7' / 8'.
For this, I created a WakefulBroadcastReceiver, that pass to an IntentService to create the notification.
And this is how I setup my AlarmsManager. timeInHours is an integer passed as parameter, between 6 and 12 :
Intent i = new Intent(context, StepCountNotifyBroadcast.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
// Get the next day at timeInHours hours'.
Calendar cal = Calendar.getInstance();
cal.setTime(new Date()); // compute start of the day for the timestamp
cal.set(Calendar.HOUR_OF_DAY, timeInHours);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.AM_PM, Calendar.AM);
if (new Date().getTime() > cal.getTime().getTime())
cal.add(Calendar.DAY_OF_YEAR, 1);
long nextDay = cal.getTime().getTime();
// Setup the alarm.
long timeBetween = AlarmManager.INTERVAL_DAY; // Each day.
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarms.cancel(pi);
alarms.setRepeating(AlarmManager.RTC_WAKEUP, nextDay, timeBetween, pi);
Date nextDayAsDate = new Date(nextDay);
GLog.d("AlarmUtils", "scheduleNotifiation for next date: " + nextDayAsDate.toString());
It works well 50% of the time, but still do crazy things like... Trigger the notification at 2:00 AM ?!
I know the system will not trigger the notification at the specific time I want and this is ok. But here we talk about approximately 18 hours later.
In logs, it seems that my IntentService code is effectively running in the middle of the night in some cases. So that's not an issue with the notification itself.
I can switch this line :
alarms.setRepeating(AlarmManager.RTC_WAKEUP, nextDay, timeBetween, pi);
to another line of code :
alarms.setExact(AlarmManager.RTC_WAKEUP, nextDay, pi);
But this is not good for the battery life I'm afraid.
Now my questions :
Can somebody tell me a reason about the way Android devices works with AlarmsManager ?
Do you find another solution than will not drain battery life and be sure the notification will be triggered in maximum 2 or 3 hours later?
Do you have any ideas, in this particular case, to debug and do code testing without waiting a day or two to detect issues?
Thanks in advance.
After API Level 23, Doze mode was introduced on the Android System to reduce battery consumption. Go through below link:
How to make Alarm Manager work when Android 6.0 in Doze mode?
I have followed the following link https://developer.android.com/training/scheduling/alarms.html.
RTC examples first one, to set an alarm for a specific time on all days. Even after following the same code, the alarm is not triggered at the time it is suppose to get triggered. Instead the notification gets triggered immediately after setting the time which is done with the help of a time picker. Following is my code snippet,
AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, NotificationReceiver.class);
PendingIntent intentalarm = PendingIntent.getBroadcast(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY,4);
calendar.set(Calendar.MINUTE, 30);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, intentalarm);
Instead of setRepeating I also tried setInexactRepeating but there was no luck.I would also like to add that when I changed the
calendar.getTimeInMillis() and used SystemClock.elapsedRealtime() + 120 * 1000 the alarm triggered exactly after 2 minutes from the time it was set.
But when calendar.getTimeInMillis() is being used the intended working does not happen instead immediate triggering occurs.
Would be indeed very helpful if anyone can help me out find a solution.Only for a note, I could learn if alarm is set before current device time the alarm would be triggered immediately but that is not the case here.
NotificationReceiver.class is working fine as it is generated and appears on the title. But the time it appears is the cause of concern.
You are using both setTimeInMillis and hourofday and minute.
If you want your alarm to be triggered at 4:30 just add hourofday and minute.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY,4);
calendar.set(Calendar.MINUTE, 30);`
I could Identify the issue I was facing. I was using a TimePicker with 24 hour format. But I used SimpleDateFormat "hh:mm". What 'h' stands for is as follows "h->Hour in am/pm (1-12) ". So any alarm that I set at AM triggers correctly. When I set a time at PM since I had used 1-12 'h' format, alarm gets set for a AM time and since that time is already passed when compared to the device time the alarm/notification got triggered immediately.The right format to use was "HH:MM" where 'H' stands for "H->Hour in day (0-23)". This resolved my issue.
Checking the TimeinMillis on online epoch time converter helped me identify this issue.Once again thanks for helping me.
I know that this topic is explained fairly well and there are a lot of tutorials. But maybe I'm too new in android to understand what I'm doing wrong.
I need to implement support of set of reminders. And notification should be shown exactly every Monday at 15 pm. I checked a lot of tutorials and similar questions on this site but anyway notification shows, somehow, randomly.
How do I test implementation:
Current time is 14:55
I set reminder on Monday at 15:00
And right after SAVE notification is shown.
Because of (just for example) I set repeat period in 20 sec, this notification is shown again and again with delay of 20 sec. But current time is still between 14:55 and 15:00.
And my task is to run notification at 15:00 or a liitle later. But not before.
set repeating notification
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, NotifyService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, (int) reminder.id, intent, 0);
final Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.DAY_OF_WEEK, 2);
calendar.set(Calendar.HOUR_OF_DAY, reminder.time.hour);
calendar.set(Calendar.MINUTE, reminder.time.minute);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP,
Calendar.getInstance().getTimeInMillis(), 20000, pendingIntent);
BTW
my min SDK version is 7, so I cannot use methods like setExact()
android version on tested device is 4.4.2
Thanks
When you set the alarm you set it with Calendar.getInstance().getTimeInMillis() instead of calendar.getTimeInMillis(). Simple bug ;).
Basically setting the alarm to 'now' every time, ignoring your calendar object.
Im trying to set and run an alarm that run every hour, and is set by a few variables so as it will not run instantly, if the time is greater then the 58th minute
The idea is to set it # X hour and 58 minute, so it will run every hour, at the given minute(58).
Calendar calCurrent = Calendar.getInstance();
int time = 58 ;
Calendar calx = Calendar.getInstance();
calx.set(Calendar.MINUTE, time);
calx.set(Calendar.SECOND, 5);
if (calCurrent.get(Calendar.MINUTE) > time) {
calx.add(Calendar.HOUR, +1);
}
System.out.println("Alarm is set to - " + calx.get(Calendar.HOUR)+":"+
calx.get(Calendar.MINUTE));
alarmSwap = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmSwap.setRepeating(AlarmManager.RTC_WAKEUP,
calx.getTimeInMillis(), 60 * 60 * 1000, pintent);
The code works and runs correctly for the 1st instance, then the alarm will for some reason run # 0 minute the following hour.
Timeline looks like
1:23 - Repeating Alarm Set for 1:58 (1 hour intervals)
1:58 - alarm is triggered
3:00 - alarm is triggered
I have no idea why this alarm is being triggered # :00 for the last alarm. It is not being called from anywhere else.
Any help is greatly appreciated.
All alarms are resetting after the hour clocks over the hour-
Calendar calnew = Calendar.getInstance(); calnew.add(Calendar.SECOND, +5);
alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, calnew.getTimeInMillis(),900000 , pintent);
Timeline-
1:20 triggered
1:35 triggered
1:50 triggered
2:00 triggered
2:15 triggered
2:30 triggered
From android documentation.
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.
repeating alarms are not exact after API 19. This improves androids performance as android groups alarms which are at close interval and wakes system once and finishes all alarms(from other applications also).
If you really want exact alarms the you will have to set normal one time alarm, and then set alarm again in first alarm's call.
Try this code to repeat alarm every hour
alarmSwap.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
calx.getTimeInMillis(),
AlarmManager.INTERVAL_HOUR, pintent);
Hope this will help.You can ask if you have any further queries.
This worked for me to trigger alarm after every 1hour
alarmmgr = (AlarmManager) getSystemService(ALARM_SERVICE);
long interval = 60 * 60 * 1000; // 1 hour
xassert alarmmgr != null;
alarmmgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);