public static void sleep (long time)
This is from android docs in Eclipse;
"Causes the thread which sent this message to sleep for the given interval of time (given in milliseconds). The precision is not guaranteed - the Thread may sleep more or less than requested."
What does it mean thread may sleep more or less than requested. Why it is not absolute while working with this method?
It is not absolute for several reasons, the main one being that we can't measure time all that accurately. Also, it may have to wait for more high priority threads to ease up before it is allowed to cut in again.
This problem is not specific to Android, but to any thread in general even on desktop computers, and the reasons are explained very well over here.
Related
I do not know why but i created a thread where i am using Thread.sleep(1000) and its working in 8 out of 10 devices but not working in rest 2 devices.
Not working means, thread is sleeping for around 0.5 sec instead of 1 sec and i can see it in logs.
So there is no guarantee that thread will sleep for exact amount of time ?
What could be the possible issues ?
Same code is working in almost devices.
There is no guarantee that Thread.sleep will sleep for an exact amount of time. What the javadoc actually says is:
"Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers."
Sleeping longer than expected it not unexpected. For example, it can happen if the device's cores are all busy doing other things when the "sleep" is due to end.
However, a sleep() call returning significantly sooner than requested sleep time is not expected behavior.
I suspect that the real cause is:
Your thread is getting an interrupt and your code is squashing the exception ... so you don't notice it. An interrupt send to a sleeping thread will cause the sleep call to return early.
Your sleep call's argument is different to what you think.
Possibly a system clock adjustment happened at the wrong time ... though I would expect this to be a "once in a blue moon" event.
This is an artifact of an emulator, a debugger or something like that "messing" with the clock.
However, if this is a real effect and not caused by something that you are doing, then I would say that it is a candidate for reporting as a bug to the vendor of the device. But you would need a way to demonstrate the problem repeatably; i.e. a minimal reproducible example to include in your bug report.
The sleep() documentation warns that it's not precise:
https://developer.android.com/reference/java/lang/Thread#sleep%28long%29
Causes the currently executing thread to sleep (temporarily cease
execution) for the specified number of milliseconds, subject to the
precision and accuracy of system timers and schedulers. The thread
does not lose ownership of any monitors.
I'm making a performance analysis of an app as some parts are very slow, for example it takes 0.310 seconds for a database consult. If I do this in the main thread the UI interruption is very noticeable, the app doesn't feel responsive.
But what is the maximum amount of time you should interrupt the app, what is acceptable?
I want to make it as fast as possible but also don't want to get obsessed and spend hours of work in order to cut the time in a few milliseconds.
In case of iOS, the UI renders at 60fps, so the ideal maximum time would be 1/60 seconds so that the UI doesn't skip a frame. You can work out what performance you need from the minimum fps you want to achieve.
Anyways, make full use of all the tools available at your disposal, like XCode's Time Profiler. etc. Start with the slowest chunks of codes and keep going up.
But what is the maximum amount of time you should interrupt the app, what is acceptable?
0
There is no acceptance level defined as such, it all depends on how good the user-experience you can give. Have background threads/NSOperationQueue/GCD. Only when it's an UI-level operation, use the main thread.
In Android
Android will show you Triggers ANR
Generally, the system displays an ANR if an application cannot respond to user input. For example, if an application blocks on some I/O operation (frequently a network access) on the UI thread so the system can't process incoming user input events.
see link ANR
No response to an input event (such as key press or screen touch events) within 5 seconds ANR dialog will pop up.
In what way that I can have a real-time timer for task scheduling on Android?
Currently I am using Java.util.timer for my real-time application? However, the timer is missing firing when garbage collection is running or other other stuff. The description on java.util.timer says "this class does not offer guarantees about the real-time nature of task scheduling.". Then, which class that I should use on Android then? Or are there any other approach to have a real-time guarantee timer on Android?
Forgot to mention that the timer that I need is at 20 - 40 milliseconds precision level. That means, I need it to fire every 20 - 40 milliseconds.
Handler.postDelayed(Runnable r, long delayMillis);
Does not have a note about whether or not it guarantees it to happen on time. I've used this mechanism before and never noticed any inconsistency with it. However, i've only used it for relatively short intervals (less than a minute) If you are looking for something farther out than that I would suggest you take a look at the AlarmClock application in the Android source. That will probably give you a good approach. That being said if you are looking for extreme precision(down to seconds or farther) I doubt you're going to be able to find anything with guarantees. There are too many things that could be going on that could cause potential misfires.
I'm writing a sports app that needs to track the elapsed time of quarter/half/period. Elapsed time needs to be accurate to the second. The game clock needs to continue to run even if the user explicitly places the device in sleep mode by pressing the power button.
My first attempt at this involved using Handler.postDelayed() to trigger the clock ticks every 200ms and WindowManager.LayoutParms.FLAG_KEEP_SCREEN_ON to ensure that the "clock" wasn't stopped by a screen timeout. But I soon learned that it was possible to circumvent this approach by pressing the power button to manually put the device to sleep. In addition, the postDelayed() approach is experiencing some clock drift, apparently a result of the time spent in the run() method. The actual numbers are still accurate, but instead of being aligned, for example, on 5 second boundaries which are easily understood by users - the timers involved start to drift, resulting in some understandable user confusion.
After a bit of research I found techiques for using services, java timers, AlarmManager, and PartialWakeLock to implement timers. Services by themselves won't solve the problem associated with the device going to sleep. Java timers, like services, don't solve the problem with the device going to sleep. AlarmManager seems like a good approach, but I'm concerned that this isn't an appropriate use of AlarmManager (i.e., very short intervals between alarms). Using PartialWakeLock also looks promising, but by itself it doesn't address the clock-drift problem I'm experiencing.
I'm going to try a combination of AlarmManager and PartialWakeLock. The idea is that AlarmManager will help combat clock-drift and PartialWakeLock to help keep the code simple (fingers-crossed). I'm hoping that this approach will result in a reasonable balance between power conservation, code complexity, and user expectations. Any advice is greatly appreciated.
Thanks,
Rich
I've got a partial solution to my original post above. It doesn't yet address the clock drift associated with the time spent in calculations during the postDelayed() processing, but it is a step forward. In addition, it's deceptively simple, always a good sign.
It turns out I was using SystemClock.uptimeMillis() when I should have been using SystemClock.elapsedRealtime(). The difference between the 2 is subtle, but important.
As you might expect, my solution keeps track of elapsed time by accumulating durations between calls to postDelayed() - i.e., elapsed time = elapsedTime + lastClockInterval. As stated above, the original implementation used uptimeMillis(). Careful reading of the javadoc reveals that uptimeMillis() doesn't include time spent in "deep sleep", e.g., when the user presses the power button. But the elapsedRealtime() method does include time spent in "deep sleep" mode. All that was required to track time across deep sleep cycles was to replace the use of uptimeMillis() with elapsedRealtime(). Success! No need to use AlarmManager, PartialWakeLock, or anything else substantially more complicated. Granted, these methods still have uses, but they are overkill when implementing a simple elapsed-time clock or timer.
The next problem to tackle is with the clock-drift caused by the non-zero execution time associated with postDelayed() processing. I'm hoping that spawning a thread to do the processing will address this issue, allowing postDelayed() to more or less mimic an asynchronous call. Another approach would be to adjust the postDelayed() delay time to take into account the time spent in postDelayed(). I'll post my results.
On an unrelated note, during my investigation I treated myself to a CommonsWare Warescription. While I didn't directly use any ideas from this source for this problem, I do think that it is going to be my Android go-to information source for the foreseeable future. I've got an O'Reilly subscription through my day job, but I've found the CommonsWare books to be as least as good, if not better, source of information about Android development as the O'Reilly resources. And I have found the O'Reilly Safari resources to be pretty good. Interesting...
Cheers,
Rich
I'm sorry this is not quite an answer, but I feel your process is similar to mine, but there was little in regards to code to make it clear how you got around the sleep issue. I don't have drift, but the app does hang when it goes into sleep mode,then kind of resets forward when the display is active, then hangs again when the device sleeps. This is the core of the timer process.
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
// do something here to display
processTime(); // process what to be done on a sec by sec basis
try {
timerHandler.postDelayed(this, 1000
} catch (Exception ex){
}
}
};
Is there something here that I can do to allow it to continue when in sleep mode? This use to work on older version of android/devices.
The description for the method uptimeMillis says:
Returns milliseconds since boot, not
counting time spent in deep sleep.
Note: This value may get reset
occasionally (before it would
otherwise wrap around).
How often might this happen and (more importantly) will it affect runnables that should be executed by Handler.postAtTime?
The uptimeMillis call grounds out in systemTime(), which on a Linux system turns into clock_gettime(CLOCK_MONOTONIC, struct timespec *).
The struct timespec holds seconds in a time_t, which appears to be a 32-bit value. If it starts counting near zero, you will not likely be alive when it wraps.
If you need more specific details, you should investigate the behavior of clock_gettime(CLOCK_MONOTONIC) in the Linux kernel.
If you happened to call uptimeMillis right when it wrapped, then yes it would affect your postAtTime call.
A signed long in Java has the range:
-9,223,372,036,854,775,807 to 9,223,372,036,854,775,807 (~9.2E18)
9.2E18 milliseconds is 292,277,266 years. If you are working on a space probe, you probably want to take this into consideration, otherwise you can probably get away with assuming it won't wrap in your lifetime.
The kicker for me is that the Android documentation for uptimeMillis claims
This clock is guaranteed to be
monotonic . . .
Then soon after they say that uptimeMillis will be reset due to variable wrapping - the exact opposite of a monotonic clock!
I was using it for a service and did not ever see it resetting. I would really assume it won't.
The problem with postAtTime() is that it will not be called during sleep (since uptimeMillis() will not update). If that's an issue, then I would use some other method.