I want to set alarm for a specific time, I tried the code below. The problem is, most of the time alarm goes off within 10 seconds. I tried getting value of time in a toast and that seems to be perfectly fine.
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());//set the current time and date for this calendar
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DAY_OF_YEAR, cur_cal.get(Calendar.DAY_OF_YEAR));
cal.set(Calendar.HOUR_OF_DAY, 1);
cal.set(Calendar.MINUTE, 54);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.DATE, cur_cal.get(Calendar.DATE));
cal.set(Calendar.MONTH, cur_cal.get(Calendar.MONTH));
long futureInMillis = SystemClock.elapsedRealtime() + delay;
long time = cal.getTimeInMillis()-(System.currentTimeMillis());
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, (1000*60*60*24) , pendingIntent);
Toast.makeText(context, "alarm set for" + time, Toast.LENGTH_SHORT).show();
I also tried,
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pendingIntent);
also,
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 24*60*60*1000, pendingIntent);
and,
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
As I understand your question("I want to set alarm for a specific time"), you want the alarm to sound at--lets say 10 AM tomorrow. However, your code seems to be in contradiction to this statement, because you are calculating a time difference:
long time = cal.getTimeInMillis()-(System.currentTimeMillis());
You may also be experiencing an issue the AlarmManager has by with the setRepeating() method. The Android documentation says:
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.
So, if you do want to set an alarm for a specific time (and not a time difference) just try this:
long time = cal.getTimeInMillis();
You might also consider changing to the setExact() method and creating code to repeat as needed (there are examples on the Internet).
Link to Android documentation:
https://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int,%20long,%20long,%20android.app.PendingIntent)
Related
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 am trying to execute a background process on my android app every day at around 09h10 am. This works fine, but problem is after the first alarm has been fired at 09h10 am, it gets re-fired after 10 - 20 minutes throughout the day. I just want it to fire once a day, and only at that specified time. My code that sets the alarm manager is below:
PendingIntent reviewsPendingIntent = PendingIntent.getBroadcast(this,0,new Intent(this,ReviewReceiver.class),0);
AlarmManager alarmManager = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE));
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());
Calendar cal = new GregorianCalendar();
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 10);
cal.set(Calendar.SECOND, 10);
cal.set(Calendar.MILLISECOND, cur_cal.get(Calendar.MILLISECOND));
long interval = 6000*1440;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(),interval,reviewsPendingIntent);
I have set the interval to 8640000 which is a day(I believe) if not, please advise accordingly. Thank you
1000ms*60s*60m*24h = 86400000 so You missed one 0
You can use
PendingIntent reviewsPendingIntent = PendingIntent.getBroadcast(this,0,new Intent(this,ReviewReceiver.class),PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(),AlarmManager.INTERVAL_DAY,reviewsPendingIntent);
FLAG_CANCEL_CURRENT will prevent the alarm to be set multiple times
AlarmManager.INTERVAL_DAY = 1000 * 60 * 60 * 24
If you keep having some delay, it's because the sleep function is not precise. It's around the time you have set. Try with setExact and reschedule every day, doing the math by hand (initialTime + dayPassed * millsInADay) to have the best approximation.
If what Lindus has posted worked though, just forget it :) but I think that you'll have the same problem.
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.
This is a code that i'm using for running a service once a day .
the problem is this , after 24h , the service keeps calling every 10 to 15 min .
Intent myIntent = new Intent(this, MyService.class);
pendingIntent = PendingIntent.getService(this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.HOUR, 24);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(), 86400, pendingIntent);
I think I'm using a bad code .Could you give me a better code for runnig a service once or twice a day
thanks you
The interval parameter to setRepeating represents millis. It should be 86400000 to get it right.
You are now programming an alarm to start first execution 24h past the current time, but with a period of 86400 millis (less than two minutes).
Morale of the story:
Always read the docs before using an API.
Use AlarmManager.INTERVAL_DAY instead of your own magic numbers
I want the AlarmManager to repeat a task at scheduled time (weekly)
I used the following code:
for (Integer day : daysList) {
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_WEEK, PersonalUtils.getDigitalWeek(day));
c.set(Calendar.HOUR_OF_DAY, task.getHour());
c.set(Calendar.MINUTE, task.getMinute());
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
intent.putExtra("id", task.getId());
PendingIntent operation = PendingIntent.getService(
getApplicationContext(), requestCode, intent, 0);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(),
AlarmManager.INTERVAL_DAY * 7, operation);
}
However the alarm it triggered prematurely.
For example: Assuming that it is 18:30 Wed now. I setup a task which should be triggered at 17:30 Tue next week but instead the alarm is triggered immediately
Can anybody tell me why?
You are trying to do an inexact alarm, which only allows for a few specific constants, INTERVAL_DAY, INTERVAL_FIFTEEN_MINUTES, etc. See Android Docs for more. Those constants are only supposed to be used for InexactRepeatingAlarms, but I see your doing a RepeatingAlarm.
You have a couple of choices, you can either set the alarm to trigger in exactly 1 week, or you can set it to trigger every day inexactly and only pay attention to it if the alarm occurs during the 7th day. To trigger exactly every 7 days from now, try this:
final long WEEK_IN_MILLIS= 604800000;
alarm.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis()+WEEK_IN_MILLIS,
WEEK_IN_MILLIS, operation);
Note that I set it to first trigger in 1 week, then repeat every week after that. That should work for you.