I need to execute code at intervals, sometimes 10 seconds, sometimes 5 minutes. The code should be executed at exact 10 seconds from start, then at exact 5 minutes and 10 seconds from start, etc.
A Chronometer is ticking along from the start, so the execution time must be accurate.
Using Handler.postDelayed does not work, because the code to execute could take some time. The next execution of the code could be late when that happens.
When I wanted to implement AlarmManager, I saw the note
The Alarm Manager is intended for cases where you want to have your
application code run at a specific time, even if your application is
not currently running. For normal timing operations (ticks, timeouts,
etc) it is easier and much more efficient to use Handler.
So I'm a bit confused, how should I do this to guarantee correct execution?
As Chris stated, there's no such thing as exact timing in Android.
But you could try it like this to come near realtime...
some Pseudocode for waiting 5s:
class mJob implements Runnable{
public void run(){
while(System.currentTimeMillis()<myExactTime){ //poll for your time
Thread.sleep(1);
}
//Ok, we are as near as we'll ever get
//call here your 'realtime' function or whatever you need
}
}
mHandler.postDelayed(mJob,4950); //the closer to 5000, the better for the cpu but you could miss your `myExactTime`
I don't now how exact this is, you'll just have to try it. But I see no other way to become more 'realtime' with the normal SDK. You could even remove the sleep(1) to become even closer to your myExactTime.
For the next call use something like this (scratch):
nextCallDelayInMillis = starttimeInMillis+No1_Delay+No2_Delay-System.currentTimeMillis();
Have a look at this post : Time/Date change listener. you can use setRepeating() method, or alternatively set the timer again after each execution.
As android is not a hard-realtime OS, exact timing of execution is not possible without substantial kernel modifications. Even there, you are unlikely on a typical android device to have much in the way of exactly timed means of useful I/O, so just running your code at the perfect time may not be enough.
At best you can determine using the more reliable of the timers the latest point at which your code could have run, and take after-the-fact compensation measures.
In terms of the available timing methods, a major consideration should be if you intend the device to wakeup from sleep to accomplish events, in which case you should use the Alarm Manager, if you intend to keep the device awake, in which case you should use a Wake Lock, or if you are okay with your events happening only when the device is awake and your service or activity is running, in which case you can use a simple Timer.
You didn't specify if your code runs while application is running or as background service. It's important, because after you lock your device, Android goes to sleep mode, where CPU is off and functions like postDelayed wont be activated. Intents asking to start activities too.
But AlarmManager broadcasts will.
I'll quote from here
The AlarmManager is best used for tasks that need to
run even when the application isn’t open. For normal timing operations
that need to run during application use (ticks, timeouts, etc), it is
more efficient to use the postDelayed() and postAtTime() methods of a
Handler. The AlarmManager requires too much overhead to justify it
being used this way.
I suggest you to use postDelay, for any post to handler, handler is opening new thread and code is executing simultaneously.
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
//some code
mHandler.postDelayed(this, 1000);
}
};
Here is my complete code I used postDelay for displaying count down timer: https://github.com/minimaldevelop/antistress/blob/master/src/com/minimaldevelop/antistress/AntiStressExerciseActivity.java
Also here I using AlarmManger but only as remainder to display message at notification bar when application is closed.
Related
Context
I'm working on a screen filter app (like f.lux) for Android. I'm currently working the feature to gradually fade in the filter as the sun sets. The state does not matter when the screen is off, but when the screen is on, it's important that the fade progress be correct (or immediately updated).
Technical requirements
I want to fire a series of intents at semi-regular intervals.
When the screen is off, they can be ignored / discarded, except:
when the screen turns on, the most recent intent must be fired immediately.
I do not want to drain the battery unnecessarily.
Obvious solutions and why they don't work
I could use AlarmManager.setInexactRepeating, which is supposedly the most energy-efficient of the alarms, except:
Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time.
I think this implies that the first trigger will necessarily happen within the first interval, meaning the device will be woken, causing unnecessary battery drain.
I could use AlarmManager.set to schedule the first alarm. When it goes off, I could update the screen, then schedule the next alarm. This would work, but would wake up older devices (without Doze) on each alarm, instead of waiting until the screen turns on. It's also using AlarmManger as a timer, which the documentation explicitly recommends against:
For timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
Okay, so,
I could set a single alarm to starts up a Handler, which would update the UI periodically. But wait: this relies on postDelayed, which says (emphasis mine):
Time spent in deep sleep will add an additional delay to execution.
I think that means, when the device wakes up from sleep, the next update might not happens for a whole interval. Am I reading this right? Forcing the user to wait a minute or two before the next update is a deal-breaker.
CountDownTimer and ValueAnimator both use this method in their implementations, so if my interpretation of Handler is right, they're both out.
I could use a handler-based method and also receive events when the screen is turned off, at which point I'd cancel the existing animation, then start a new one. This looks to be the best solution, but it seems like there should be a simpler way to do it.
Conclusion
There are a ton of other SO questions on this topic. Everyone and their mother recommends using a Handler, but there's absolutely no information about how it behaves when the device goes to sleep, aside from the quote above. It's really weird that (apparently) nobody else has run into this issue -- am I doing something really unusual, or missing something basic?
Can anybody provide insight about how Handler.postDelayed really behaves when the device goes to sleep, and recommend what I should do in this particular instance?
My Application needs to have one (async) task which is always a network operation and the first time a DB query as well.
It needs to be executed with a certain interval amount of time which is not fixed (could be 1 minute or 1 hour or anything in between) and also when the application is not active.
What is the best and the simplest solution in such case between Asynctask/Thread/Service/Alarm/anything not mentioned.
For that you need a service, not an AsyncTask:
http://www.vogella.com/tutorials/AndroidServices/article.html
Services persist even after activities are dismissed. Be careful though, draining the battery will anger your users. Also, services can be destroyed if memory runs low, so be careful.
The scheduling of a task to run in the future should use AlarmManager. The execution of the operation should run in a service since you specify that sometimes it will occur when the app is not active.
You can also use a TimerTask but it's a little more drain on battery and not as precise as AlarmManager. You can also use a handler to postAtTime
Here is a good reference:
difference between timer and alarmmanager
and another one:
What is better in Android? Timer or Alarm?
It really depends on the frequency and use-case. I've used all of these - I view TimerTasks as "keep checking frequently for short time" vs. handlers for "check again in a while" vs. AlarmManager for "I want to keep checking every hour for a long while"
I have programmed an app which uses a handler. Inside the handler there are some network operations.
The handler has an interval of min*1000*60 ms. I used the handler with min=5, so it should repeat after five minutes. But this is the result of my check:
First Handler:
16:20:22
16:25:23
17:01:52
17:13:07
17:20:19
17:25:55
Second Handler:
16:20:26
16:25:26
17:01:35
17:12:51
17:20:02
17:25:37
Third Handler:
16:24:58
16:31:59
17:12:43
17:19:54
17:25:30
All Handlers are running in separate Services. The screen is turned off.
Do you have any ideas or alternatives to a Handler in Android?
The code of the handlers is so simple:
handler.postDelayed(new Runnable() {
public void run() {
// network operations
}
}, interval);
First, assuming that you created your Handler via new Handler(), it will do its work on the main application thread. Do not do network I/O on the main application thread. It also is likely the source of your drift.
Second, most likely you do not need three services. Usually, you need one service. Three services simply makes your app more complicated for no added value to the user.
Third, your Handler will only work while the device is awake, and I do not know whether that is an acceptable limitation or not.
Fourth, using a Handler implies that your service(s) will be running indefinitely, and users do not like this. Only have your services be in memory when they are actively delivering value to the user.
A better way to implement this, therefore, is to use AlarmManager for your scheduled events. If you do not need the events to be processed while the device is asleep, the AlarmManager can directly pass control to your service. Ideally, that would be an IntentService, so that the service will give you a background thread automatically and so that the service will automatically shut itself down when the work is complete.
If you need the events to be processed even while the device is asleep, please give the user control over the event period, including an option of "do not do anything", as waking up the device every 5 minutes to do network I/O will be bad for the battery. Then, use a WakefulBroadcastReceiver or a WakefulIntentService to arrange to have your work be done while keeping the device awake.
Use SheduledThreadPoolExecutor instead of handler.
It has scheduleAtFixedRate function, which does exactly what you need. And no handlers at all)
Are there any major differences between CountDownTimer and AlarmManager? I don't mean syntax or how to use it but wondering if there are such tasks when you certainly can say that I should use one of them, not another?
Simple example, I have to launch some action once a minute. What should I use? CountDownTimer or AlarmManager? How it depends?
AlarmManager generally is used for purposes where your application is closed or must execute some repeating task(s). It is also slightly less precise than Timer or Handler.
CountDownTimer is used more for running a specific task at a duration (onFinish), and being updated periodically until it executes (onTick).
In your specific case, I believe you should be using AlarmManager, since it can repeat indefinitely. If you want something to execute every second for 10 seconds, for example, use CountDownTimer.
CountDownTimer
CountDownTimer will run in the context of your Activity. means It can be killed at any time, If your app is not on forground.
AlarmManager
A total different approach uses Sticky Intents. And tells your Receiver, after some time. It does not depends on the Activity's life Cycle.
So if you want to do some operation every minute, even your app is not on forground then you should use AlarmManager, otherwise CountDownTimer will do the job for you.
As described here :
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
So in your case is better to use CountDownTimer, since you don't want to do the action even if the app is closed.
Would it be better to have a service that is continually running a timer and executing a task every five seconds. Or would it be more efficient to have an alarm manager starting the service every five seconds? How about every second? I'm interested to hear your responses. Thanks!
According to the AlarmManager documentation, it's only for cases where you want to run at a specific time. For what you're talking about, you'll want to use a Handler, with postDelayed().
Note: The Alarm Manager is intended
for cases where you want to have your
application code run at a specific
time, even if your application is not
currently running. For normal timing
operations (ticks, timeouts, etc) it
is easier and much more efficient to
use Handler.