I am developing an application for a client and I would like a usage timeout. For example, the user installs the app and after 3 hours it can no longer use. What would be the best way to do this?
I could do it in the most basic way, recording a time flag to check every time the app loads, but how do I prevent the user from uninstalling and reinstalling the app and can use it again?
Can I record a global variable on Android?
After user first time installs the app you can get unique UUID for that device using for example Ionic Native Device plugin and send it to your database along with timestamp.
import { Device } from '#ionic-native/device';
constructor(private device: Device) { }
...
console.log('Device UUID is: ' + this.device.uuid);
After that, it's enough at some time intervals or every time an API is called, compare that time in the database with current time and if more than three hours have passed prohibit calling all APIs from device with that UUID. The application will, in that case, become unusable.
Of course, you can always allow a particular user (UUID) to use it for a long time.
Related
The way I've currently set it up,
Each device makes an API call to my server with a unique ID it generates on first launch as POST data.
The API call renews the timestamp of that ID.
The devices make this call every 20 minutes. Hence every 20 minutes, they update the server for with the current time as way of indicating when last they were active on the device.
Then to view the active devices, I've got a web page, which shows me how many devices have had the app running within the last 21 minutes.
But I feel this is a bit primitive, there has to be a more efficient way, even for a hybrid cordova app. I don't think Whatsapp literally checks the network state of devices every millisecond.
If you know any cordova plugin that can help me acheive this, I would be more than grateful that you shared.
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.
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.
In my app I want to allow user to be able to use it for 7 days offline usage for free, but want him to connect online once 7 days are done and buy a subscription after that. So basically, I want to lock him out after 7 days from install. The problem is user can very well change system time and trick the app. Also, I cannot use server as the authority as the app is supposed to also work completely offline, except for the time of purchasing subscription.
I can run a background service to keep track of any system time change but I want to avoid doing that.
Is there a straight forward solution which can work even if the device is totally offline for 7 days.
You can save the current time in shared preference and compare it every time you sample it. If you get an older sample the user changed the time backward.
Use remote clock , for even simple read the time of server from mobile in desired time gap and use those number for your app's clock
So this is how I am planning to solve this, though this is not unbreakable but will work for majority of users.
So while signing for trial I get network time and store it as start_time in preferences. Next on each app start and app resume I read the current_time and write to prefs. Once current_time of pref is greater than time of device, we lock the app. Once preferences are not there we ask user to come online as suggested by #Zach
To make preferences editing a little inconvenient to the rooted device guys I am storing data in encrypted form in prefs.
This is still no way unbreakable as one can decompile the apk and read the obfuscated code to guess the algorithm and the key but I guess the value of content in the app is not that high for someone to go through that much pain.
can add syscall and track the time offline, get it from here
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.