Mobile App: how to get correct time when offline - android

We're building an App using Ionic/cordova that will need to run on Android, iOS and Windows 10 Mobile.
The goal is to register start and stop events, we'll need the exact time and location when this events are registered.
There is a serious concern that the users will modify the timesettings on their phone to send false data.
As long as these events are sent immediately to the server, we can use the server time to validate what the user is sending us. But there is also a requirement to be able to work when offline.
Our first thought was to use the GPS time. In cordova the position object has a timestamp.
https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-geolocation/
But after further reading, here and here, that this isn't necessarily the time of the GPS server but also just the local time. I've read about work arounds using the uptime of the device, but this won't work as soon as there is a reboot. But most of these conversations are a few years old.
For now we think the simples approach will be to flag events that are sent offline as 'suspicious'.
Is there any other way to accurately determine the time when you're offline without risk that the user tampered with it?

Haven't tried it myself,but what about getting the time from the Network Provider, as said in this SO: I want to get time from GSM network
long networkTS = locMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER).getTime();
Time returned by getLastKnowLocation could be old if you want current
time use
locMan.requestSingleUpdate() and pass the network provider
Though, this may not work in iOS or Windows.

Related

Android Time Synchronization in UTC

I have an application that relies heavily on current timestamps. Currently, when user submits a request, I get the current timestamp in UTC using System.currentTimeMillis(). While this works fine, it becomes a problem when the user starts manipulating their Date/Time on their device and would result as inaccurate timestamps.
Why do it on the client then? Why not just handle it on the server? Well, my application needs to work offline. All my requests get pushed into a jobQueue when connectivity to the internet is unavailable. In these cases, I must have the original time wherein the user did the action so if I submit a request at 4:02pm, but due to network problems, server will only receive it around 7:30pm, server MUST know that I sent the request at 4:02pm.
Now what options have I considered?
Upon user login, I sync the device time with the server time and store that time locally. If any user manipulation occurs while the user is logged in, I'll have a BroadcastReceiver listening in onto any intents of Date/Time manipulation, then store the offset so that whenever a user submits a request, I will calculate the synced time with the offset to ensure the timestamp is accurate.
Have a server sync api done in the backend and set up a service within my application to continuously sync up with the server time and look for any drift while also listening in onto any user manipulation.
Use push notifications and listen downstream for time synchronization adjustments while also listening onto any user manipulation.
I could also make use of the NTP servers to synchronize time with my device.
I'm not entirely sure which would be the most optimal (assuming I have listed down all the possible solutions). If there are other solutions I haven't thought of, please let me know.
P.S. If I happen to use the BroadcastReceiver to listen onto any datetime manipulation on the device, how would I even calculate the offset in that?
It has been some time since I asked this question and there hasn't been any elegant answers to the problem so after some research and some trial and error, I decided to take the NTP route and after some digging around, I found a nice library that does the entire thing for you.
It can be found here:
NTP TRUE TIME
Credits to these guys who had made life a lot easier.
You must sync with the ntp servers just once and from there on, they will calculate the Delta for us giving us accurate UTC regardless of SystemClock time.
For time synchronization you can implement like getting time zone from server. Once we have timzone we can get the current time of server.

How to my mobile app automatically expire the content even being in offline mode?

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.

Manage offline hour in Android

I want to do an Android app that submits data to a web server. This application needs to run offline and the hour of the submitted info is crutial. We can't rely on the hour provided by the client, so we are always setting it in the server side. But, when android app goes offline, we need to keep a private clock separated from the system hour (because it can be modified by the user). My question is how can i achieve this? The first solution that cames to my mind is to keep a private clock in our app, but this is going to crash when someone closes it or when shutdown occurs. There is something done to achieve this in Android? Also, we are going to use Ionic framework (suggestions accepted ;))
Thanks.
You can achieve that by using SystemClock.
It allow you to know the time elapsed from the System startup.
Store the server timestamp and wake up you're app with AlarmService. Then check if the elapsed time is correct.

android notify User on when his data changes in the server

We are working on app which is for fixing their appointment with a doctor. We will have to notify the user on that date by saying if the doctor is available or not.
How can we notify the user when the data changes in the server?
The usual workflow for sending push messages from your server to the application, is the Google Cloud Messaging, or the so-called Push Notification in Android.
Simply put, you send your message to the Google and the Google will notify your application. The actual heavily lifting is done by the Google Play Services Library and its corresponding application, which is installed on every android device. For more information on how to implement it, you may refer to the following links.
Official Documentation on Cloud Messaging
Android Push Notification Tutorial
I used http://pusher.com/ "Pusher" for a doc app a couple years ago. It was easy to do and light weight.
Simplest way I would believe is through a polling technique. However, it would not work for real time updates as there is an update interval. Depending on your application's requirements, this might work!
In order to do that.
You would have to publish a web service which would provide a Unix
timestamp. e.g. https://Your-base-url/status.aspx
Each time there is any change on the server, you change the value to a new one on the server.
Your Android device will poll that web service(status) each say 60 seconds
to see if there is an update.
The device would save the timestamp in his device and would check
whether the two timestamps match.
If not, then he will call the relevant web services to get updated
data.
However, you should note that the Android device will only get to know whenever it polls. So, the device might not know the update until his next polling cycle.
The most accurate way is to maintain a persistent Socket connection with your server at all times. Whenever an update occurs, you can immediately send the updates to the device via the open socket. However, this is more complicated as you will have to deal with the socket connections.
GCM uses socket connections internally. Therefore, a solution including GCM is an easier approach.

Get accurate time from android/iphone to server

We have an android(or iphone) client we are developing. The client allows the android user to send entries to a server which we also develop. If the client does not have data services (GPRS) at the moment the user sends the entry to the server, the client also supports saving the entry to an offline database and sending it later to the server.
One important aspect of the whole process is accuracy of the timestamps on which the user sent the entry to the server (whether the entry is made in real time or sent by the client from the offline database)
When available on the client, we get a GPS location and are able to use the GPS timestamp to send that to the server (or save the GPS timestamp on the offline DB and send it later to the server). However if the user has turned off the GPS (and all other location services), the device will not have a GPS fix and therefore the server can not determine accurately when an entry was made.
We can not use the local device clock as the user may change the clock to make entries on different times than they actually occurred (these entries are part of the users salary so he might have an interest to "fix" them).
So basically I am searching for a way to determine as best I can the time some entry was made when I can not trust the internal clock of the mobile. The algorithm should support both entries sent in real time or entries sent from an offline DB. the algorithm should also support cases where the user changes the time of the mobile, turns the mobile on/off, turns the GPS on/off while the application is running on the mobile etc...
Few ideas that I thought of:
Although I can not trust the mobile's time, it can still perform as a stop watch:
Have a class that will loop until the application exists, the loop will sleep 1 second and increase an internal clock variable by 1 second. On every GPS location my code gets we update the internal clock variable. This way I have an absolute clock that came from outside the device (from the GPS) and when the client sends an entry to the server, we can use the internal clock as an absolute time.
PROS: the user can not modify this clock as it is only updated when we get a location from the GPS
CONS: the application needs at least one GPS fix before the user can make any reliable entries
I can take advantage of the fact that the server has an accurate clock which is correct. If the client would send to the server info that the age of the entry is 10 minutes, the server could use its internal time and know the exact time the entry was made on.
The biggest problem is how to know the entry age? I thought about saving the entries to the offline DB with an age of 0, then every 1 second increase the age of the entry in the DB. The problem is that if the app is closed and/or the device is off this will now happen
This is where I am currently stuck. Any ideas on how to solve this are more than welcome
Thanks
Here's how I handle this issue for iPhone. When the app starts, I call my server and ask for the current GMT time (you could also call a public NTP server if you preferred). I then compare it to the system time. If it is different by more than X then I popup a message saying, sorry your system time is wrong so you can't use the app until you fix this. I then monitor for the user changing the system time while the app is running and if they do that, then I do the compare again (and popup the error message if the time is off by more than X). This ensures that their system time is always correct (within some reasonable allowance) and you can trust [NSDate date]. However, this solution does require a valid network connection. If this solution works for you, I can post the sample code.
i think i am going to combine Jules and Joel's answers into one solution which will provide for my needs the best solution:
since the user might change the clock when the mobile doed not have GPRS, just detecting the time change event will not help us as we can not validate at that moment the new time is correct.
As Joel recommended i will pull the time from my server when my application is started (at that point i still must have communications with the server or else my application will not start). The time pulled from the server along with the current device upTime will be saved.
when the user wants to make an entry i will calculate the current time using (Server Base Time + Current UpTime - Base UpTime). this way i will have an independent source of time regardless of the current clock of the device
this will defenitly work on android
on iPhone we will try to use something out of http://www.cocoadev.com/index.pl?FindingUptime to get the upTime
Jules & Joel, thanks for your answers!
Look into android.os.SystemClock. Specifically, elapsedRealtime() returns a time since the phone was switched on, which is not affected if the clock is changed by the user.
You can correlate times in event the phone is switched off by having code that runs when it is switched on and checks the realtime clock. As the clock can't be changed when the phone is off, I suspect you could use this to put together a system that will catch any simple attempts at cheating. (If the user roots the phone all bets are off -- they could modify the behaviour of the APIs from under you).
Running code every second will kill the phone's battery life. Most phones would be unlikely to last a day if you did this.

Categories

Resources