I need two devices to have exact same time.
I want to use GPS to get time. It can be done on iOS and Android devices.
Can i be sure that they have exact same time in milliseconds?
No you cannot do that easily.
ios overrides the gps time. If a user adds one hour, and disables auto time sync,
the time is then offset. It will not work that way. If auto time sync is enabled it should work.
However you could query via internet the correct time using a time service, and do the same that NTP do. (network time protocoll). However that looks not to easy.
As an intermediate approach, I would check whether the system time relates to the network time. If yes, one can asume that auto time sync is enabled.
Related
My customer make a request for their commercial app is to automatically expire the content after downloading into the device in 7 days, even in the following cases:
+ without the internet connection to connect and check the expired time from the server
+ stop the customer try to maliciously modify the time in their device to expand the expired time
When the content expired, it will be removed from the device and unavailble to watch any more.
After a few days researching on Google, I still not find out the appropriate approaches.
Why can't you just add an expiration date at the content when you download it? And then check if is expired or not locally, without any control server-side.
There is a few suggestions but not of them is enough to cover all the cases maybe it will be useful if you combined them :
1- get the time based on the last know-location .
2- get the network time so the user
changing their device time wont matter (requires an internet
connection)
There isn't a great solution to this. You do have a couple of options, none of which are perfect.
Option 1 - use date / time from last known location
This will require you to request GPS access in your application, which may concern users, if the app doesn't have a valid need for tracking the users' locations. But basically get the last known position, and in the Location object returned would be the time as of that last location check. Two things could prevent this from working 100%. First, with newer version of Android, users can disable certain app permissions. This means they could disallow GPS access to your app. To combat this, you could check this on app startup and inform the users they cannot access any content unless GPS access is enabled. Second, if the user has no GPS signal, the last known location may have been from days ago, meaning the "current time" will be frozen as of the last GPS signal. Also, some devices don't have GPS chips, so this would not work for them.
Option 2 - Try to detect system date / time changes by keeping a log of the date / time in your app.
Basically, this will take some work to keep track of the system date / time on each launch, as well as the duration of each session in your app. With this log, you could compare to the current / date time and see if the user is rolling back the clock. This wouldn't be perfect, as a smart user who understood your checks could roll it back to the closest time to the last time the app was shut down, but at least this would limit them to having access to the content for 7 days of run time. Also, it would take a really dedicated person to keep track of / exploit your checks. Most users would simply try to roll back their clocks to a past date and it would be simple to catch. With this method, make sure you are capturing / storing all times in UTC time, so that time changes don't trigger a false fraud scenario.
Recommendation
Personally, I would use both options if you are OK with the GPS permissions on your app. If available, and given permission by the user, use the last known location to get the time. If that isn't available, or if the user has removed the permissions, use a local store of run date/times and durations as a fall back.
Can I synchronize one time on several Android devices?
For example current time is 00:00 and through the timeapi (web service) we sent this time to Android1. Due to some delay we get 00:01 instead of 00:00.
We make the same on Android2 but in this time, delay = 2sec and we get 00:02.
So can we sync these time between 2 Android devices?
Maybe you suggest another way without web serivce, via bluetooth or sent several requests to web service every 5 sec to calculate average delay?
At best I have to get 00:00 time at Android1 and Android2.
If what you want is the correct time on all devices, then you usually don't need to do anything except make sure that the built-in time synchronization is not turned off, and the time synchronization will be done via the NITZ protocol.
If your carrier doesn't provide NITZ time sync, you could use NTP.
If you want to have your own, custom time, turn off the NITZ sync, and use NTP with your own custom NTP server.
I've noticed that System.currentTimeMillis() time is device dependent. If I change the time on the device's clock, this method will return a different answer.
For example: If the real time now is 10:00, and I change the clock on my device to 9:30, then System.currentTimeMillis() will return the 9:30 time (in milliseconds..).
I've also tried this answer and some other answers, but didn't find anything useful.
I should state that my app works mostly offline.
Is there a way to get the real current time (device independent) without external API?
If it were not for the 'offline' part, I'd have suggested to use a time server, but given that your app is offline most of the time that might not be a good solution.
If you don't need the actual time but just a time that cannot be messed with, you can use SystemClock.elapsedRealtime() which gives you the time since the device last booted.
You could also combine time server and SystemClock.elapsedRealtime(): Fetch the time from timer server once (e.g. after bootup) and from then on add elapsedRealtime() to that initial value (minus the elapsedRealtime value of when you get the timerserver value).
If you use the GPS location provider, getTime() will return the UTC time derived from the GPS signal, rather than the device time. The GPS location provider can work offline - but it will be much slower to obtain a fix compared to being online when it can access the A-GPS info.
I need to measure long elapsed time on Android and there may be device reboots in between.
From what I've understand, System.nanoTime() is resetted every time the device reboot, and System.currentTimeMillis() is unreliable because user can change it.
The only solution that I came up with is to listen to ACTION_SHUTDOWN and BOOT_COMPLETED, use System.currentTimeMillisec() to calculate the elapsed time (user can't change clock time while the device is off, hopefully :) ) and add it to the last System.nanoTime() I had before shutting down.
I honestly don't like this solution because it's very expensive (I need to listen to 2 broadcast events) and inaccurate, but I couldn't figure out any other way to do this.
Any ideas? Also a native solution would be good for me.
You can get around the user changing time by using an internet time server to get the times when you check. There are a couple of ways to do this.
Get it via NTP server
How to get current time from internet in android
How can I get the "network" time, (from the "Automatic" setting called "Use network-provided values"), NOT the time on the phone?
Get it via HTTP header
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Responses ( see Date header )
If you simply persist this value then the user can do nothing to mess up your calculation.
I'm doing a camera application that will automatically geo-tag each picture taken. Using
LocationManager.requestLocationUpdates() //simply to get the GPS running
LocationManager.getLastKnownLocation() //for each picture, to get coordinates
is mostly enough to simply pluck out coordinates from the phone as fast as possible, since it is still a camera application and you don't want to waste time getting GPS data.
(Assume using GPS_PROVIDER only, not NETWORK_PROVIDER pls)
However the issue will be if the user enters a tunnel for example and the phone is unable to continue getting updates. 10 minutes later when getLastKnownLocation() is called, I will get an outdated location.
I want to find a way in which I can set an 'expiry' time on the Location, depending on individual comfort level.
In other words, keep using getLastKnownLocation(), but if the data is (for example) more than 5 minutes old, don't bother with it, and I rather have a 'null' location. if the data is 2 minutes old however, that still is fine
You can implement this yourself. There's nothing in the underlying API that includes this, but it's perfectly fine to stash the time that you initiated the request (or got the last one) in your app, perhaps in a SharedPreferences. You also have to be weary of things like how fast the user is moving, etc.., so in general you might need to put a fair amount of thought effort into determining how you want to do this. There's not any way (in the API) to find out how fresh the call to .getLastLocation() will get you. For a few minutes it's probably best to employ the technique I mentioned. For a lot longer you might want to consider something like an AlarmManager (which you should be using anyway if your app runs on a timescale that is that long). You seem to be using .getLastLocation more than I do, however. I often simply just request updates and then "put the dot down" whenever I get the first update. In general I've found that .getLastKnownLocation() isn't really all that reliable, but maybe that's just because I don't use apps with my location very often.
Managed to find out that each Location returned had a time variable
long time_a = my_loc.getTime();
We can use this to compare with
Calendar cal = Calendar.getInstance();
long time_b = cal.getTimeInMillis();
long interval = time_a - time_b;
The interval is then the 'validity' of the location fix, and can be easily used for my purpose :)