SystemClock.elapsedRealtime() drift when the device is in low-power mode - 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?

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.

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.

Related

How to determine the time that the device was not being used for?

My application should detect whether the user was sleeping to start itself with a welcome message when the user wakes up and powers up his phone for the first time in the morning, afternoon, or whenever he wakes up, by pressing the power putton and entering the pattern on the homescreen or pin or whatever.
I want to do this by measuring the time the device was used the last time. I presume 8 hours of sleep, so if 8 hours passed since the last switching off, the next time the mobile phone is being switched on, the application starts(respectively a function inside).
The screen going on because of an alarm or anything but user interaction should not count.
I looked at logcat and it gave me the useful information I/PowerManagerService: Going to sleep due to power button. So a PowerManagerServiceListener could be a way. I found https://developer.android.com/reference/android/os/PowerManager.html but it is for actively keeping the display on, not for passively reporting it.
Another candidate is KeyguardViewMediator: onStartedGoingToSleep(2) and KeyguardServiceDelegate: onScreenTurnedOff().
Sure, I could create a polling application, that looks through logcat, but that sounds like a strongly battery draining approach.
Which performance friendly way is there to accomplish what I want?
According to your description, you are interested in a granularity of hours. Then you can schedule a repeating alarm every hour (see Scheduling Repeating Alarms), save the time in a Shared Preference, receive a BOOT_COMPLETED broadcast, compare the times and decide what to do.
However, I guess a lot of users don't turn their devices off, so I would try to find out if the assumption your approach is based on is valid.
You can also try getDetectedActivity() from Snapshot Awareness API and check if DetectedActivity is for example STILL at some specified interval.

android wrong boot up time

I'm developing an app that need to know the moment when the system startup, periodically.
I use System.currentTimeMillis(); to get the current "date" in millis.
I get the system elapsed real tine with SystemClock.elapsedRealTime().
I subtract the total time with the elapsed time, and I retrieve the system bootup time.
I would understand if the value change of milliseconds over time(different times in executing instructions). But for me it changes of seconds!!! Is very strange.
Someone have an idea of why?
Differences of seconds (or even tens of seconds) should not be surprising. "Current Time" corresponds to what the user perceives from the clock displayed. If you watch the displayed clock, it will not always change immediately. Read the docs:
http://developer.android.com/reference/android/os/SystemClock.html
It's pretty clear that you can't depend on currentTimeMillis for much of anything where you need millisecond accuracy. However, in most applications you really don't need that level of accuracy...
If you are trying to determine "exact boot time" from a specific moment in time later, a few seconds probably is the best you will do. Besides, what qualifies as "booted"?? When the kernel is loaded? When the user can interact with the device? When the device screen lights up? When the device can actually be unlocked?
You should probably just listen for RECEIVE_BOOT_COMPLETED (Android - Start service on boot).
Here is the Android doc: http://developer.android.com/reference/android/Manifest.permission.html#RECEIVE_BOOT_COMPLETED

Does time jump in android devices?

System.currentTimeMillis() is giving wrong time.
It returns time values from 1980
Also time value taken through this function differs from actual time sometimes.
Some sample values returned by the function
315977198121
315965244789
316002166580
315982533137
Yes, time returned by System.currentTimeMillis() can jump around, for example because the device clock may have drifted, and is being reset due to fetching an accurate time from the network
Time as observed through other APIs may also jump around even more, for example due to changing time zones, or due to daylight saving.
(However that doesn't explain why you are seeing times suddenly in the 1980. That frankly sounds like a device error.)
You state that you are using the value to get a duration. That's an error - you should be using SystemClock.elapsedRealtime() for duration calculations.
See the docs at SystemClock, which specifically note:
Three different clocks are available, and they should not be confused:
System.currentTimeMillis() is the standard "wall" clock (time and date) expressing milliseconds since the epoch. The wall clock can be set by the user or the phone network (see setCurrentTimeMillis(long)), so the time may jump backwards or forwards unpredictably. This clock should only be used when correspondence with real-world dates and times is important, such as in a calendar or alarm clock application. Interval or elapsed time measurements should use a different clock. If you are using System.currentTimeMillis(), consider listening to the ACTION_TIME_TICK, ACTION_TIME_CHANGED and ACTION_TIMEZONE_CHANGED Intent broadcasts to find out when the time changes.
uptimeMillis() is counted in milliseconds since the system was booted. This clock stops when the system enters deep sleep (CPU off, display dark, device waiting for external input), but is not affected by clock scaling, idle, or other power saving mechanisms. This is the basis for most interval timing such as Thread.sleep(millls), Object.wait(millis), and System.nanoTime(). This clock is guaranteed to be monotonic, and is suitable for interval timing when the interval does not span device sleep. Most methods that accept a timestamp value currently expect the uptimeMillis() clock.
elapsedRealtime() and elapsedRealtimeNanos() return the time since the system was booted, and include deep sleep. This clock is guaranteed to be monotonic, and continues to tick even when the CPU is in power saving modes, so is the recommend basis for general purpose interval timing.
Try using System.nanoTime() instead of System.currentTimeMillis().
The documentation of System.currentTimeMillis() seems to indicate that it shouldn't be used for calculating time elapsed!
you can create broadcastreceiver on action 'android.intent.action.TIME_SET'. You can know when time on your device change (by another applications).

Timing bug in our game, currentTimeMillis freeze?

When testing our game, that is heavily dependent on System.currentTimeMillis(), we are experiencing an annoying bug.
Our game uses an array of delta timestamps that indicates when certain things should happen. These timestamps matches a piece of music that is being played.
Testing at home gives us no problems at all. It's impossible to reproduce the bug while testing from our home.
But testing while driving around in the car, between cities, gives us sync problems between the timestamps and the music. My best guess is that Android freeze up the system, including the system timer because it's switching network, or looking for a signal?
I've tried inserting a fake hick-up in the game, by making the thread sleep a few seconds when I press a certain button. This freezes the screen (obviously), but everything is still syncing fine when the sleep is over.
The only way to reproduce this bug, is to take a trip by car or bus or train - which of course is most probably where most people will be when playing our game.
The question is of course,
what to do about it?
Does anyone have any ideas?
Read SystemClock.
System.currentTimeMillis() is the standard "wall" clock (time and
date) expressing milliseconds since the epoch. The wall clock can be
set by the user or the phone network (see setCurrentTimeMillis(long)),
so the time may jump backwards or forwards unpredictably.
uptimeMillis() is counted in milliseconds since the system was booted.
This clock stops when the system enters deep sleep (CPU off, display
dark, device waiting for external input), but is not affected by clock
scaling, idle, or other power saving mechanisms. This is the basis for
most interval timing such as Thread.sleep(millls),
Object.wait(millis), and System.nanoTime(). This clock is guaranteed
to be monotonic, and is suitable for interval timing when the interval
does not span device sleep.
I think it's better to use System.nanoTime().

Reliable repeating background task on android

I'm trying to run a background task which runs every minute or so for an android application but I am struggling to ensure that the task actually runs every minute. I've tried a variety of approaches from using SystemClock.sleep() to the AlarmManager (both repeating alarm and a fixed alarm) but it seems that unless the device is charging any kind of repeating system has a variable repeat rate once the device is unplugged. Is there any way to run a stable consistently repeating service?
Have you implemented Timer? It works very well for what I use it for, but then again I haven't worried about the precision at all. For all I know it may be varying a bit but I doubt it. It seems pretty consistent to me.
Edit: I am not liable for your responsible or irresponsible use of this facility ;)
If you need to have a service that runs every minute, on the minute, you have two options:
Use AlarmManager.setRepeating(RTC_WAKEUP, ...). In this case, the phone will sleep, but the RTC inside the phone will wake it up every minute to handle the repeating event. This will work, but will not be terribly exact as a lot of things are happening after the phone wakes up so your code might not get execution time right away.
Obtain a WakeLock from PowerManager and use whatever you want to time your code (Timer, Handler, etc.). This forces the phone to never sleep, which means that it is most likely free to run your code almost exactly when you request.
Both approaches will definitely drain the battery of the phone fast. Normally, the phone can sleep for 4 or even 9 minutes between wakes, so waking up once per minute is a big change from that.

Categories

Resources