I have a service which doing some works periodically. I'm not sure if it is a good practising but I'm setting an alarm and calling service itself. I'm working on android 4.4.2 and so far I couldn't make it work at intended times. For example if I set alarm for 1 minute, it can be run at 5 or 10 minutes later. I can ignore few seconds of delay but 9 minutes delay is hard to accept.
Here is my code
Intent myIntent = new Intent(TimerService.this, this.getClass());
pendingIntent = PendingIntent.getService(TimerService.this, 101,
myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + onTime,1000, pendingIntent);
I also tried alarmManager.set() and setExact() but the result is still same.
Is there anything wrong with the code or I'm doing something wrong with calling service itself?

- 1,144
- 1
- 13
- 18
-
Try to set a `targetSdkVersion is earlier than API 19`. – Phantômaxx Dec 19 '14 at 16:15
-
"Try to set a targetSdkVersion is earlier than API 19." even if I'm going to use it on android 4.4 ? – mbaydar Dec 19 '14 at 16:21
-
Yes, why not? Android is back-compatible (old apps will run on newer devices). Try setting `targetSdkVersion = 18`. Note: `target` **doesn't** mean `not any further than this`. – Phantômaxx Dec 19 '14 at 16:30
-
Have a look at this answer : http://stackoverflow.com/questions/4459058/alarm-manager-example I hope it helps... – Abhinav Puri Dec 19 '14 at 16:42
-
`targetSdkVersion` barely means `compile using the specified API Level`. – Phantômaxx Dec 19 '14 at 16:43
-
@AbhinavPuri Here the question is not `how to make an Alarm fire`, but `why it fires inexactly on KitKat and later`. – Phantômaxx Dec 19 '14 at 16:46
-
I've tried setting targetSdkVersion to 18 still have the same problem. – mbaydar Dec 19 '14 at 19:20
2 Answers
The documentation says that setting the targetSDK below 19 will give you exact timing.
It also sounds like setExact should give you the timing you want ( I know you said it did not work :) ).
I use something like this and it always kicks off within about 30 seconds of the requested time.
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + DEFAULT_INITIAL_RUN,
DEFAULT_RUN_INTERVAL, pi);
If your interval is that short have you considered using handler.postDelayed to kick off
your periodic code?
Below is from the AlarmManager set method documentation.
Note: Beginning in API 19, the trigger time passed to this method is treated as inexact: the alarm will not be delivered before this time, but may be deferred and delivered some time later. The OS will use this policy in order to "batch" alarms together across the entire system, minimizing the number of times the device needs to "wake up" and minimizing battery use. In general, alarms scheduled in the near future will not be deferred as long as alarms scheduled far in the future.
With the new batching policy, delivery ordering guarantees are not as strong as they were previously. If the application sets multiple alarms, it is possible that these alarms' actual delivery ordering may not match the order of their requested delivery times. If your application has strong ordering requirements there are other APIs that you can use to get the necessary behavior; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent).
Applications whose targetSdkVersion is before API 19 will continue to get the previous alarm behavior: all of their scheduled alarms will be treated as exact.

- 1,049
- 1
- 6
- 5
-
Another strange behaviour is when I set alarm for short time of period like 15 seconds it works good but when I set more than a minute than it seems problem occurs. Can I use handler.postDelayed for a long time ? – mbaydar Dec 19 '14 at 19:28
-
You should be registering just once when the service starts. If you are setting it up for repeat periodic calls. The entire point of the AlarmManager is to ensure your service will be invoked even if it is not currently running. If you can guarantee that your application is up and only want to run while your application is active you can just leave the service up or use handler.postDelayed to invoke your code at regular intervals. – mjstam Dec 19 '14 at 19:34
I did quite some research about that. Generally, setExact works on the devices I tested (LG), except on some Samsung devices (S4, Note). On Samsungs I used JobScheduler: http://code.tutsplus.com/tutorials/using-the-jobscheduler-api-on-android-lollipop--cms-23562
This works consistently on all devices with API after 21. I tested periodic run on 30s.
Eidit: it doesn't work consistently. It wanders off, to fire at 2mins. But what works, is teh setExact every 15s. My solution was, to fire alarms every 15 seconds, but then doing nothing, set another iteration and go back to sleep if it's not yet the time I want.

- 542
- 7
- 16