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
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
I'm trying to implement a fast communication between two android phones at a certain moment by, preferably, going through a server (since it's easier to be consistent).
The phones have to communicate their gps locations every x seconds, with x being as low as possible, with only one of the phone having to be on the app, the other can be idle (but obviously not turned off).
The first solution I tried is a syncadapter in the app which updates every x seconds, sends requests to server writing its location in a DB, and then the other retrieves the location in the same DB.
Note : I've implemented it this way only because I already had the underlying architecture (REST API and all) beforehand, but I don't know how to do this in the real world, so feel free to cricize my initial choice and advise me on a better solution
Thank you in advance :) !
You can look at Firebase https://www.firebase.com/ which is a real time database. It does have active listeners in the sdk to get real time updates for your GPS coordinates.
The problem you mentioned can be addressed with
https://github.com/firebase/geofire-java/tree/master/examples/SFVehicles
I am trying to get the exact Data Usage per Day , or by Range of Time in Android
however from what I searched, I cannot found anything that could do this
Something that I tried
TrafficStats
this one will reset all data every time the device is boot, so I
couldn't use it
NetworkPolicyManager
this one require system permission. So, I can't use it
any help would be appreciate
You need to have a service that will periodically call TrafficStats APIs to get current statistics, and store the results. E.g. the delta between two invocations of getMobileTxBytes() is the number of bytes received during that time period.
Of course, if someone just pulls a battery out of their phone, you'll lose statistics since the last invocation of your service. So set the frequency of updates according to your needs (every hour versus every minute).
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)
This question may be slightly long-winded, but is open for many suggestions.
Problem Statement:
We have several API level 8 (Android 2.2) MyTouch devices that we will be using for recording acceleration data at an amusement park, namely on a roller coaster. We also have a visualization feature that allows us to plot and view the accelerometer points as a function of time that they were recorded at. Here is where we have a dilemma! The system times on the Android devices aren't all the same, nor can they be set to the same time with millisecond precision (only manually with minute precision, which is awful).
Solution Attempts:
So, I first resorted to recording data according to a GPS time found at the start of the app. Long process short: get GPS time, get System time, get difference, and upon recording a data point, get system time again and add the difference back onto the time, label that as starting time of recording, and increment by 200 milliseconds for each recorded data point from there. However, there are 2 problems (for getting GPS time):
Using getLastKnownLocation() isn't too accurate. Actually, it seems very inaccurate. It is giving me times that are 9 minutes off the current GMT/UTC time. Coincidentally, however, system time is also nearly 9 minutes off on the Android device... the difference between GPS time and System time is usually between 1000 and 5000 milliseconds (1 to 5 seconds). I suppose there is a chance my code is wrong. I pasted it below for you to see.
requestSingleUpdate() would be great to use, as it would get a more recent location and perhaps a very accurate time. Problem? Requires API level 9... devices we don't have.
Ideas:
Here's an idea I had though - what if I somehow pulled a global time from a website and used the time pulled from there as the time of recording? Problem here - I have no idea how to do that, it is just wishful thinking of mine...
Another idea - is there some sort of global getTime()-type of function that I simply don't know about?
Reasoning why I want Android's to pull time from a similar clock:
Imagine two people sitting on a roller coaster - one in the front seat, one on the back. When recording data, the person in front will obviously experience accelerations slightly before the person in the back will (and we want to see this on our visualization graph). That is why is it crucial, to millisecond precision, that these points are recorded according to a single, global time.
Code:
Criteria c = new Criteria();
c.setAccuracy(Criteria.ACCURACY_FINE);
if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
mLocationManager.requestLocationUpdates(mLocationManager.getBestProvider(c, true), 0, 0, AmusementPark.this);
Criteria criteria = new Criteria();
String bestProvider = mLocationManager.getBestProvider(criteria, false);
Location location = mLocationManager.getLastKnownLocation(bestProvider);
try {
gpsTime = location.getTime();
systemTime = System.currentTimeMillis();
timeDif = gpsTime - systemTime;
Log.e("timedif", "GPS: " + gpsTime + ", System: " + systemTime +", Dif: " + timeDif);
} catch (NullPointerException e){
}
}
Update:
Here, someone suggests a sort of "server" getTime(). I really like his code/answer, but what is this "server" and/or how do I set one up, if this is the best solution?
I think the "server" the responder is referring to in that post is to set up a dedicated time server. Basically you'd be setting up some hardware that all of the people using your app would connect to in order to get the time. It may be more effort than you are willing to put in.
You'd need the following,
Some spare hardware (could be as simple as a computer running tomcat, or as complex as a dedicated server rack depending on how many people you think will be using your app.) or a subscription to a domain server/web host.
Some web service that just returns the time whenever an app requests it.
You'd need to make your server/webservice public, which is a whole other headache.
I'm not sure that would be your best solution either as it would depend on network connectivity to reach your dedicated server. There are a couple of alternate solutions you can try:
I don't know if your app is going to be public or used specifically for research. If it is the latter and it will be with a group of people you know and can coordinate with, I actually recommend that you just download ClockSync, sync up your phones to the same time server, and then execute your app.
If your app is going to be distributed to people you won't have contact with, then perhaps your best bet is to get your app to do a connection to one ntp server and grab the time that way. Here are a list of public ntp servers you can use: http://www.pool.ntp.org/en/
Here's some more information:
ClockSync
Sample code for making an SNTP connection
I hope that information can be of use to you in making a decision.