6

In my app, I want to allow users to be able to use it for 7 days offline usage for free but want them to connect online once the 7 days are done and buy a subscription after that. So basically, I want to lock him out after 7 days from installation. The problem is users can very well change system time and trick the app. Also, I cannot use the server as the authority as the app is supposed to also work entirely offline, except for the time of purchasing a 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 straightforward solution that can work even if the device is offline for 7 days?

Abhishek Sinha
  • 435
  • 4
  • 12
  • 1
    Possible duplicate of [Is there a way to detect when the user has changed the clock time on their device?](http://stackoverflow.com/questions/15544996/is-there-a-way-to-detect-when-the-user-has-changed-the-clock-time-on-their-devic) – F43nd1r Apr 07 '16 at 11:32
  • That solution will work but basically I do not want to keep track of all time changes that happen in device. Also intent may not be received if device is rooted and user changes from command line or user changes the system time in safe mode. Correct me if I am wrong – Abhishek Sinha Apr 07 '16 at 12:59
  • There is no safety on a rooted device. period. Look at xposed if you don't believe me. – F43nd1r Apr 07 '16 at 13:16

4 Answers4

9

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.

Zach Bublil
  • 857
  • 10
  • 28
  • 5
    This is so bad solution. User can clear applications data and get another free 7 days... – vilpe89 Apr 07 '16 at 11:50
  • 2
    @vilpe89 If the user clears application data he'll have to get online (and get the start date from server) in order to continue using the application. It seems a good idea to me. – Sevle Apr 07 '16 at 11:56
  • I'm not saying that it's unbrekable, SharedPreferences are not safe and can be manipulated. Nevertheless it's an easy workaround that will work for the average user with an unrooted device. – Sevle Apr 07 '16 at 12:01
  • But the user can START using the app offline so where to get the start date then, so that's not going to work either. And the program can't check if user has cleared the data. – vilpe89 Apr 07 '16 at 12:09
  • @vilpe89 I was under the impression that the user has to be online the very first time that he uses the app. If that's not the case, indeed that can't work. The program can check if the data exists in SharedPreferences with `SharedPreferences.contains(String key)`. If there isn't, lock the app and prompt the user to get online in order to continue the trial period. – Sevle Apr 07 '16 at 12:15
  • Yes but user still can clear the apps cache (even without the all mighty root privileges) and get the new start date from the server (assuming that server does NOT store the first start date per user). But in case of dumbass user, that would work just fine... – vilpe89 Apr 07 '16 at 12:24
  • I already mentioned that this only works if the user is online the very first time the trial period starts. I got your point ;) – Sevle Apr 07 '16 at 12:29
  • User will be connected at the first time they use your app , give them auth token and save their email and device ID in your DBMS , so if a person deletes file he will try to get the token again and if the initial token time and now is more than 1 month , or you can even create a content that won't be deleted when your app is uninstalled and you read that file when the app first starts . – erluxman Apr 07 '16 at 12:36
  • 1
    This is a good solution.Obviously in offline case there is no 100% secuirty guarantee. So, setting a signup for trial of 7 days is needed, wherein he needs to be online, and it is needed to store the account information on server so same user does not install after uninstall. Once we get the signup success we store the start time in preferences in some encrypted form(for rooted device), and on each onResume of app we update the last checkpoint time, and once current time becomes less than checkpoint time, we lock the app.We even ask him to connect if he clears the cache. – Abhishek Sinha Apr 07 '16 at 12:45
  • It's not the perfect solution..checking the time every second is bad habit. Go with other solution out there. It's a perfect one! Check this out - [Perfect one!](https://stackoverflow.com/a/17175444/10357086) – Dev4Life Nov 25 '21 at 06:17
2

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

erluxman
  • 18,155
  • 20
  • 92
  • 126
  • Yes, thats a good solution, and that is the first thing one can do for such use case. The issue, here though the app needs to work offline and only time user is needed to come online is when he needs to buy subscription. So, user not connecting to internet is an allowed scenario – Abhishek Sinha Apr 07 '16 at 12:30
2

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.

Abhishek Sinha
  • 435
  • 4
  • 12
0

can add syscall and track the time offline, get it from here

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 27 '21 at 13:49