Short skippable intro:
I work at a rehabilitation hospital that's a couple kilometers from where I live. The hospital pays a bus service that picks the employees up at certain fixed locations. There's this bus driver, that picks us at 7:00. The guy is FREAKISHLY PUNCTUAL. I mean, this guy has to be in the tenth of a second order. The clock turns from 6:59 to 7:00 EXACTLY when he opens the bus door. And I was thinking of recording his punctuality for like 30 days and make a nice Excel spreadsheet for him. Error propagation and everything. He might even get a raise, who knows?
I'll make a simple app to save time in milliseconds, that seems easy enough, there're like half a dozen solutions for that here in Stackoverflow.
So, to the question:
I hit a button on a widget. It gets a time in ms. It saves it on a file (.txt, .csv, whatever)
How would you estimate the mean error of an NTP synchronized Android phone? What's the most precise and exact way to save a timestamp?
Thanks in advance
First thing that comes to mind is that time is relative, in the Einstein kind of way :) So if your reference is an Android phone synchronized with NTP, what is the driver's time reference? What if synchronization or timing somehow gets off, delayed on your phone and you have the impression that he's late one day, when in fact he's precisely on time relative to his reference?
But for the sake of solving the problem i think you can start by assuming he has the same time reference with you: some place in a network. I don't know the details of Android synchronization via time protocols, but i do know i built a so called Network Synchronization API. In your case i think my Java API might be of help. It tries to make a request for the number of milliseconds since the Unix epoch and then reads the response. The feature is that it gives you a framework on which you can estimate your true time compared to the server's by trying to discard network lag.
One thing to bear in mind: the solution above makes a request to my site (a.k.a. GoDaddy servers) which is probably different than the network location Android phones sync with. Feel free to change the request location.
Second thing to bear in mind: this rabbit hole goes deep :) No measurement can be perfect. You can try to achieve human / reasonable precision but it can never be perfect (e.g. there are other unknowns: what if there's a lag in your Android CPU just as you press the button, or what if your own reaction takes a few milliseconds? The moment you press the button is not the same as the moment the doors actually open and my impression is they're at least a few millis apart)
Related
I found what was wrong:
So apparently http://www.epochconverter.com/ is makes assumptions of the precision of the input values, and from those assumptions values around 841073068 goes to 1996/1997. I'm not sure what is the assumption that leads to that exact date, but honestly I don't care.
Using the attached debugger I called new Date(System.currentTimeMillis()) and it correctly gave me a 10th Jan-1070 date, meaning the clock is not jumping out of the way like crazy.
Original question:
I'm running a single-board computer with Android for and IoT case (this https://developer.qualcomm.com/hardware/dragonboard-410c). The OS running is the plain vanilla Android supplied by Qualcomm.
Currently I'm testing the reliability of the board to be left executing for long periods at once and I'm seeing some very very weird behavior that I can't find an explanation for.
The board was powered up 10 days ago and it have no access to internet (WiFi is on but no access point setup and no Ethernet). The bluetooth is on and there're iBeacons and Eddystone in the office. Also there are WiFi in the area.
If I go now to Settings -> Date and Time, or check the notification shade or enter the clock app, or the calendar app, I see 10th of January 1970. Which is expected and basically showing for how long the board been running.
The app on it have an always running service, which does some data processing and some disk-logging (for debugging).
From the logs, I can see that System.currentTimeMillis() was returning an expected value when the board was initially powered on. That means, the beginning of the logs indicate an epoch time in January 1970.
But at the end of the logs (and also attaching the debugger on the live process), the value of System.currentTimeMillis() is somewhere in Sep/Oct 1996. Example values: 841073068, 841263234, 841579239
So my question is:
What is happening here?
Why System.currentTimeMillis() value changed and what could have changed it?
Why the Android UI (notification, clock app, settings) still shows me 1970? Where are they getting this value from?
edit:
There's been some confusion on the answers, and I can see my question was lacking the details.
I do not want to measure difference of time. I need an actual time stamp. Those values will be reported with bluetooth LE events via POST to our backend. This "no network" thing is a reliability test that we're running on the board, but we do expect to have network most of the time, and the boards should auto-update their times from network using the normal Android ways.
I'm just trying to understand on the current batch of testing, what went wrong and why.
Well, as you already know, the current system time (System.currentTimeMillis()) can be modified by any process if desired, it's perfectly be possible that it was modified by another process. It's not a reliable method to measure up-time.
I would rater use something like:
SystemClock.uptimeMillis()
Which returns the elapsed time (in milliseconds) since the device booted (not including time spent in deep-sleep).
I would also like to mention that I suspect that Bluetooth has something to do with it, I can imagine that Bluetooth uses the system time for pairing and security just like SSL does (but I'm no expert). GPS could also be a problem as GPS can be used to obtain an UTC time value, but I'm not sure if your board has a GPS module.
Regarding your edit:
Obtaining a valid time-stamp would be quite easy: server time minus the elapsed time reported by your board. But I suggest you either choose to accept the time reported by System.currentTimeMillis() or use the elapsed time instead. At the company I work we also work with embedded Android devices and on our server dashboard we can see both the up-time (up since) and the current device time, but they should not be mixed, at least in my opinion, especially since System.currentTimeMillis() is subject to changes and is affected by summer and winter time.
If you want to measure something, better try System.nanoTime(). Here is difference - https://stackoverflow.com/a/351571/2793494
It may sound stupid but. I've set the timeout to 5 seconds and testing with a 3g connection it seems to be too little when in my experience it really sounds like an eternty.
What's a common use value for users not to desperate and keep the things together?
There are really no special, commonly used values for something like timeouts. A value that works for one user may not work for the other. The important thing from a UX perspective is, when the timeout does occur, the user is informed of:
A timeout has occurred.
The next appropriate action to recover from it, such as, restart the app, wait a while, contact support etc.
via unambiguous error message.
Doesn't sound stupid, but it depends on the interaction between your app and the server. Unlike a router based timeout, some routers begin their calculation when they begin to do the work (Heroku comes to mind). In this case, anything under 30 seconds is good.
I'm trying to synchronize the timestamps between multiple Android devices so I can kick off a task at the same time. I figure that I can use Timer and set a Date based on System.currentTimeMillis(), but the problem seems to be that the timestamps of multiple devices are just far enough apart from each other that I'm not getting the precision I want.
I'm looking at somewhere in the range of 50-100 ms, if possible. One idea I had was to use Android Beam to send one device's timestamp to the other device and then calculate a delta, but it turns out that I have to get the timestamp before the message is actually sent and received (i.e., the longer a user waits to send, the bigger the delta will be), which makes that scheme completely fall apart.
How can I sync up two or more devices so that their internal clocks will be no more than 100 ms apart from each other? Is this even possible without using an external server that keeps time?
Any other suggestions for techniques to do something across multiple devices as close to simultaneously as possible would also be welcome.
Why not use the GPS time? The time tags from GPS are pretty accurate.
You could agree on all devices on a certain time and then start it when the GPS tells you to.
Essentially, you have two choices: the simple way or the hard way.
The simple way is to use a single external source for time signals, such NIST, another internet source, or GPS as #Stefan suggests. Internet sources use NTP, see this Java NTP client question.
The hard way is to do Clock synchronization between the devices.
Android GPS hardware generally have only seconds precision. The three last timestamp digits of milliseconds float number are 000.
I am struggling with the same issue right now. I tried gps time, but I cannot guarantee that the user will have gps signal indoors.
My solution was to have all devices retrieve the time from a nist server and then just add or subtract the time difference with System.currentTimeMillis()
If the devices are rooted you could try to sync the clocks.
https://play.google.com/store/apps/details?id=ru.org.amip.ClockSync&hl=en
So I will describe what I am trying to doing general.
I have customers(the number of customers available varies at times due to weather, events, or location)
I have a drink stand ( depending on certain factors serving times vary and added time to refill pitcher)
The amount of customers coming to stand vary based on price, events, and popularity.
Customers come to stand and if another customer is still at stand getting served then the others wait in line behind each other. (after so much time in line they complain about wait times)
I want there to be a day timer so even if stand isnt finished serving customers then he loses them because wait time.
So I am not sure if using the Wait()/Notify() way would be best. I was thinking that maybe if I setup Customers as a class and brought it into the activity I am running the sales day in with the Stand info. I would appreciated help with finding a way to do this. I am still going through some other tutorials to see if I can understand a way to do this without screwing up.
Found out that I need to send the customers into a queue when I have them arrive at the stand.
Then also, the day timer will need to be set up to work off a countdown timer.
Hello
In my android application i would like to get Time since when the app is opened.
Initially what i tried was getting the time when the app is loaded from the server and then taking the difference with the current time from the device.But by doing that if the user changes the time then i willnot be getting the actual time.
Its not posiible to hit the server again for the same.
Is there any way to achieve this in android?
Please share your valuable suggestions.
Thanks in advance:)
Try the "SystemClock" class, "uptimeMillis()" method.
Store the result in a variable when the app starts.
Echoing what I said for your other question, you first need to become familiar with the activity lifecycle and understand the novel meanings (almost meaninglessness) of common words like "open" and "start" in the life of an android app.
There isn't any way you can prevent the user from changing the system time - you just don't have the right to do that to users. Normally this should be a rare event, unless you do something that makes them want to, such as lock them out of a free version of your app after so many minutes. (However if the phone is on a mobile network, presumably the mobile network occasionally adjusts its time to correct for errors in the device's oscillator, or administrative time changes)
What you can do is check the system time on every entry point to your application. If it ever goes backwards, well... something is going on. If the clock has been set back, you could assume no time between the calls with the negative time difference and resume your time meter from there, at least keeping all the previous used time in your record.
It may be that there are cpu cycle counters which you could query and correlate to system time, but this may be highly device specific and may in fact be resettable. And it may get weird if the cpu frequency is demand throttled.
You might be able to set a countdown timer as a bound on the maximum possible time between entry points at which you could meter. I don't know if these work reliably across system time changes or not - ideally they would. Testing or reading the source will reveal.
Use elapsedRealtime in your onCreate() store it. More reliable.