I have two handlers running within an Android Service.
handler1 runs every 30 seconds
handler2 runs every 5 seconds
The problem is, handler2 can't run at the same time as handler1.
I mean, when handler2 reaches 30, 60, 90... secs it will run at the same time as handler1.
So, I need to find a way during those 30, 60 90 secs to run one handler after another.
I know a solution for this could be, but it's not elegant, neither accurate:
Run handler1 at second 0
Wait 7 seconds (or any other x # of secs no-multiple of 5)
Since handler2 runs more frequently than handler1 does, you can use counter in handler2 to track when to fire the events that you plan to trigger in handler1.
handler2.postDelayed(new Runnable() {
int count = 0;
#Override
public void run() {
if (count == 0) {
// fire handler1 events
}
count = (count+1) % 6;
}
}, 5);
How about using TimerTask and Timer to schedule repeated executions (every 5 seconds)? Depending on the interval, you run either the job currently done in handler1, or the one in handler2, or both. Perhaps you can break out these jobs into functions that are called from the TimerTask's run method. That would let the handler1 job run before the handler2 job, in a synchronized manner on the same thread.
Related
is it possible to create under Android a real time (timer) task?
I need a high performance timer which runs every 20 ms (without pause).
My Use-Case: Create an audio handler which puts every 20 ms an audio packet into the audio buffer. The audio data will be received in an UDP socket.
I used and testet different timer implemenations.
For example: ScheduledExecutorService, Timer/TimerTask, Handler, pure Loop (with Thread.Sleep), CountDownTimer.
No of this solutions works well for me :(
Example dummy implementations with ScheduledExecutorService and Timer/TimerTask (totally easy, see this code):
Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(new Runnable()
{
#Override
public void run()
{
// TODO here is my timer code
}
}, 0, 20, TimeUnit.MILLISECONDS);
new Timer().schedule(new TimerTask()
{
#Override
public void run()
{
// TODO own Code here
}
}, 0, 20);
My problem is:
Number1: No real time guarantee, my timer will be paused sometimes for 100-200 ms (IMHO the garbage collection or other OS services ...)
Number2: If my timer is in foreground, it works very well (except problem #1), but if my App is in background, the timer interval will be increased to 60 ms (not 20ms)
I've tested it on different android versions (5.x, 6.x, 7.x), on Marshmallow it sometimes works (maybe it depend on vendor driver?)
Some ideas? Or is that not possible under Android?
I'm new to Android development.I want to create a stopwatch with precision of 0.01 seconds.Here is part of my code(which I think the problem lies within):
private void runTimer()
{
final TextView timeView = (TextView) findViewById(R.id.time_view);
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
int seconds = centiseconds / 100;
int centisecs = centiseconds % 100;
int hours = seconds / 3600;
int minutes = (seconds % 3600) / 60;
int secs = seconds % 60;
String time = String.format("%d:%02d:%02d.%02d", hours, minutes, secs, centisecs);
timeView.setText(time);
if (isRunning) {
centiseconds += 1;
}
handler.postDelayed(this, 10);
}
});
}
}
Since postDelayed method's delay is in milliseconds, ten times of it would be 1 centiseconds. So I'm incrementing my centiseconds variable every 10ms.So far so good.
But when I test my app on my device, it seems the seconds are ticking slower than they should. Is is probable that the codes corresponding to division and modulo operations cause so much lag that hinder the increment and reduce the accuracy?
I've rewritten the app for 0.1 seconds(deciseconds) (by: centiseconds / 10 and % 10 and postDelayed(..., 100) ) and it seems it is ticking correctly.
P.S.
Is this the reason my 4.3 Jellybean's Stopwatch has 0.1 seconds accuracy?
What is the limit of precision in android for such app? ( Timely's has 0.01 seconds so I think it is at least 0.01 seconds)
This is wrong approach as you cannot rely on system message queue as source of precise ticks as it does NOT guarantee any precision in delivery. postDelayed() queues your runnable to be delivered no sooner than now + delay but for precise delivery is not quaranteed and additional delays can happen for many reasons which in longer run would give you noticeable cumulative error in measurements.
You can however use postDelayed() to update your UI, but to know how much time passed you should use system clock methods, not own counters.
You also should fire your runnable at least twice per precision, i.e. if you want to update timer display once per minute, you should "tick" twice per minute so if there'd be any delay in message queue handling your UI shall still get at least one tick per second on time.
new Handler().postDelayed(new Runnable() {
public void run() {
//code
}
}, secondsDelayed * 1000);
here even if change value of 1000 to 100 or 10 thread runs for min 1sec.
This method postDelayed, has second parameter to let it know , in how much time it should start to run. not for how much time it should run, See Method info below
public final boolean postDelayed (Runnable r, long delayMillis)
Since: API Level 1
Causes the Runnable r to be added to the message queue, to be run after the
specified amount of time elapses. The runnable will be run on the thread to which this handler is attached.
Parameters
r The Runnable that will be executed.
delayMillis The delay (in milliseconds) until the Runnable will be executed.
Returns
Returns true if the Runnable was successfully placed in to the message queue. Returns false on failure, usually because the looper processing the message queue is exiting. Note that a result of true does not mean the Runnable will be processed -- if the looper is quit before the delivery time of the message occurs then the message will be dropped.
** Please also include "What you want to do" so one can also provide other possible solutions :)
I have a timer in my app which shut's down the app implemented with a handler to which I post a delayed runnable "quit". When user clicks the timer icon it should also show how much time is left. How could I get this data?
Should I implement an object which would count the seconds and use that data?
I prefer to use ScheduledExecutorService with ScheduledFuture, these API are more efficient and powerful than Handler and Timer IMO:
ScheduledExecutorService scheduledTaskExecutor = Executors.newScheduledThreadPool(1);
Runnable quitTask = new Runnable();
// schedule quit task in 2 minutes:
ScheduledFuture scheduleFuture = scheduledTaskExecutor.schedule(quitTask, 2, TimeUnit.MINUTES);
... ...
// At some point in the future, if you want to get how much time left:
long timeLeft = scheduleFuture.getDelay(TimeUnit.MINUTES);
... ...
Hope that helps.
I can run codes after every x seconds, but is there a way to only run a code once after x sec? Ex: I want to refresh a listview once after 1 second when a user click on a button?
Since the delayed operation is a UI Event, use a Handler
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//my events
}
}, 2000); //time in millis
I usually recommend
Timer
class in time related stuffs. but in this case i wont recommend you to use Timer as you need to execute the operation only one.
Why not simply use a
Thread
and sleep it for 1000 millis. There you go. your 1 sec timer. :)