Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SystemClock.elapsedRealtime() drift when the device is in low-power mode

Tags:

android

According to the API docs, as well as previous SO threads, SystemClock.elapsedRealtime() is supposed to keep accurate time even when the device is sleeping. This is not what I observe.

I have written a simple clock which sits in a while (true) loop and updates the time on screen based on the value of SystemClock.elapsedRealtime(). If I synchronize the clocks on two devices, e.g. via NTP, and then proceed to toggle the screen on and off a few times on one of the devices, the displayed time will drift by up to +/- 0.7 seconds. (This only happens when the phone isn't connected to external power, so sleep mode is the likely culprit here).

Is this normal? Is this a bug in Android? Is there any way to keep ~20 millisecond timing accuracy through the sleep/wake cycles?

like image 593
Leo Alekseyev Avatar asked Oct 08 '22 09:10

Leo Alekseyev


2 Answers

I have an application that communicates with a server once every minute. It synchronizes the device clock and server clock by recording the server time and SystemClock.elapsedRealtime() on startup and then calculating the server time using elapsedRealtime (I do this because the devices themselves sync time from the network and that #### can not be trusted at all).

During a one week period, running on a Galaxy Tab 2, the SystemClock.elapsedRealtime() fell behind the server clock just a few minutes under two hours. My logs reveal that the drifting pace isn't constant, so how the device is used does affect it.

While the API requires the clock to provide monotonous time, it does not guarantee accuracy. So it is not a useful method for recording time accurately over a long duration.

like image 107
Torben Avatar answered Oct 10 '22 21:10

Torben


I have been having the same issue, so tonight I tried changing my timing method from SystemClock.elapsedRealtime() to System.currentTimeMillis(). So far so good. The time is not drifting when I click off the app and back.
I have tested it with the Runnable in a service. I am currently testing it with the Runnable in the main activity and using sharedprefs to store everything when the app loses focus. I haven't decided which of these 2 methods is best yet - but the currentTimeMillis seems to not suffer from the drifting time issue elapsedRealtime does.

I know google doesn't recommend using currentTimeMillis for timing purposes, but it seems like it works better for keep correct time when the app loses focus.

like image 21
buzzdalf Avatar answered Oct 10 '22 23:10

buzzdalf