Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AlarmManager triggers PendingIntent too soon

I've searched for 3 days now but didn't find a solution or similar problem/question anywhere else. Here is the deal:

Trigger in 1 hour -> works correct

Trigger in 2 hours -> Goes of in 1:23

Trigger in 1 day -> Goes of in ~11:00

So why is the AlarmManager so unpredictable and always too soon? Or what am I doing wrong? And is there another way so that it could work correctly?

This is the way I register my PendingIntent in the AlarmManager (stripped down):

AlarmManager alarmManager = (AlarmManager)parent.getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(parent, UpdateKlasRoostersService.class);
PendingIntent pendingIntent = PendingIntent.getService(parent, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

//Set startdate of PendingIntent so it triggers in 10 minutes
Calendar start = Calendar.getInstance();
start.setTimeInMillis(SystemClock.elapsedRealtime());
start.add(Calendar.MINUTE, 10);

//Set interval of PendingIntent so it triggers every day
Integer interval = 1*24*60*60*1000;

//Cancel any similar instances of this PendingIntent if already scheduled
alarmManager.cancel(pendingIntent);

//Schedule PendingIntent
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, start.getTimeInMillis(), interval, pendingIntent);
//Old way I used to schedule a PendingIntent, didn't seem to work either
//alarmManager.set(AlarmManager.RTC_WAKEUP, start.getTimeInMillis(), pendingIntent);

It would be awesome if anyone has a solution. Thanks for any help!

Update: 2 hours ago it worked to trigger it with an interval of 2 hours, but after that it triggered after 1:20 hours. It's getting really weird. I'll track the triggers down with a logfile and post it here tomorrow.

Update: The PendingIntent is scheduled to run every 3 hours. From the log's second line it seems like an old scheduled PendingIntent is still running:

[2012-5-3 2:15:42 519] Updating Klasroosters
[2012-5-3 4:15:15 562] Updating Klasroosters
[2012-5-3 5:15:42 749] Updating Klasroosters
[2012-5-3 8:15:42 754] Updating Klasroosters
[2012-5-3 11:15:42 522] Updating Klasroosters

But, I'm sure I cancelled the scheduled PendingIntent's before I schedule a new one. And every PendingIntent isn't recreated in the same way, so it should be exactly the same. If not , this threads question isn't relevant anymore.

like image 700
Wezelkrozum Avatar asked Jun 02 '12 20:06

Wezelkrozum


3 Answers

When using a calendar are you taking into account that the calendar uses the time right down to Milli seconds. Maybe you should set the Milli second field and the seconds field to zero so it's going of on the dot.

Also for a day it would be easier to use this

Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(0);
cal.add(Calendar.DAY_OF_MONTH, 1);

Also when you use getInstance doesn't that set the calendars time to the time it was created so there shouldn't be any need to set the time again right?

like image 187
FabianCook Avatar answered Oct 09 '22 04:10

FabianCook


Rewrite: I eventually saw your error, but unpredictably.

I did changed this:

PendingIntent.getService(parent, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

to this:

PendingIntent.getService(parent, 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);

under the same assumption as you that somehow an old intent is broadcasting. I haven't seen the fluke since...

Also the only times I saw it were during my initial call. Another approach could be to track a current and a previous Calendar object, if the interval isn't what you expected then ignore this "early" broadcast. (While this method seems redundant considering how the alarm should work, it helps prevent those extraneous calls considering how the alarm is working...)

Hope that helps, I'll let you know if I find anything else.

like image 22
Sam Avatar answered Oct 09 '22 04:10

Sam


I know this question is a bit old, but I had this same problem myself. I found out that if I tried to declare the Calendar variable outside of the method, it wouldn't play nicely and the alarms would fire early. Because your class is stripped down it is hard to tell exactly where you're calling the calendar instance.

If I set it up as such, then it would fire right on time:

protected void nextAlarm(Context context, int seconds){
    Calendar nextAlarm = Calendar.getInstance();

    Intent intent = new Intent(context, MyClass.class);
    PendingIntent pending = PendingIntent.getBroadcast(context, MainActivity.REPEATING_ALARM, intent, PendingIntent.FLAG_CANCEL_CURRENT);

    AlarmManager amanager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    nextAlarm.add(Calendar.SECOND, seconds);

    amanager.set(AlarmManager.RTC_WAKEUP, nextAlarm.getTimeInMillis(), pending);

}
like image 24
Rescue9 Avatar answered Oct 09 '22 05:10

Rescue9