8

I need to ensure that my app gets the correct time, not the time set by the user in settings.

So for instance, once the user starts the app, I'd want to get a timestamp. The user would see the elapsed time on a timer on screen updated every second. When the user exits the app, and after some time restarts the app , the timer would just get the current time and compare it with the original timestamp it kept. So basically, just like the stopwatch in the Clock.App on iPhone.

Now the problem with the clock.app is that if the user goes and advances the time in Settings by one hour, this will influence the timer. Obviously I don't want that, because in my app, that would be cheating.

I'd need to get a more trustworthy time source to compare to.

I could get the time from the internet. But the problem is that I'd need internet connection , so only works on if there is an internet connection. My app needs to work offline preferably.

Is there some kind of internal clock I can access?

Is there a way of checking whether the user has changed the date time in Settings?

Any other ideas?

Thanks

Maxm007
  • 1,190
  • 2
  • 13
  • 21
  • I accidentally the real time ... is that bad? – Kamil Szot Sep 18 '09 at 10:26
  • Would it be possible to get time from the GPS ? – Maxm007 Sep 18 '09 at 13:03
  • 1
    You will need to get the time from some external source (NIST, GPS, the cell phone system, maybe even by packet sniffing for other peoples traffic that has the right data) as any internal clock can be messed with. OTOH, if you don't trust the user, you shouldn't even be doing this on the client's system. – BCS Sep 18 '09 at 16:18
  • Because my app might be used in very remote areas, I cannot depend on external source except GPS. Unfortunately GPS API doesn't expose atomic clock timestamp. I have a solution with the mach timer. – Maxm007 Sep 19 '09 at 21:42
  • @Maxm007 Have you got the solution for this ?? – Karthik Mandava Jan 12 '17 at 13:30
  • @BCS I know this is an old post, but most time-based rewards in games don't trust the user to set the time :-) They could fast forward to the future to receive rewards ahead of schedule. – mogelbuster Mar 15 '17 at 12:45

4 Answers4

1

Get the time from NIST with the Daytime Protocol:

UDP Based Daytime Service A server listens for UDP datagrams on UDP port 13. When a datagram is received, an answering datagram is sent containing the current date and time as a ASCII character string (the data in the received datagram is ignored).

NIST Format of response: JJJJJ YR-MO-DA HH:MM:SS TT L H msADV UTC(NIST) OTM

http://tf.nist.gov/service/its.htm

http://tf.nist.gov/tf-cgi/servers.cgi

zaph
  • 111,848
  • 21
  • 189
  • 228
1

The best solution I've come up with is using the mach timer which counts time units since last iphone boot.

This works great. The only restriction is that the user cannot be allowed to reboot or it would invalidate his time.

I detect a reboot by initially storing the iphone timestamp associated with the mach timer and then checking every time the app starts, so it hasn't changed. This has as a side effect that if the user changes iPhone DateTime while he's being timed , that will also invalidate the score, but that is ok.

How can I detect whether the iphone has been rebooted since last time app started

I can easily warn my users about this: rebooting or changing iphone time while you're on the clock will invalidate your scored time.

Community
  • 1
  • 1
Maxm007
  • 1,190
  • 2
  • 13
  • 21
0

I just posted the following here:

This works to get the GPS time:

#import <CoreLocation/CoreLocation.h>

CLLocation* gps = [[CLLocation alloc]
                       initWithLatitude:(CLLocationDegrees) 0.0
                       longitude:(CLLocationDegrees) 0.0];
NSDate* now = gps.timestamp;

It doesn't seem to be tamper-proof though.

I tried this code on an iPhone 4 in airplane mode (iOS 6.1), and even then it gives a time all right. But unfortunately this time seems to change with the system clock. Ugh.

Funny thing that I found (still in airplane mode) is that if you tamper with the system clock (after turning to off Time & Date's Set Automatically), and then turn Set Automatically back to on, the machine restores the real (original) time without a hitch. this works even after cycling the phone's power. So it seems that there is something like a tamper-proof time the device maintains internally. But how to access this?

Community
  • 1
  • 1
JohnK
  • 6,865
  • 8
  • 49
  • 75
0

This method will find the actual current time, found in google.com's response header:

NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
                                initWithURL:[NSURL URLWithString:@"http://google.com"]];

[request setHTTPMethod:@"GET"];

NSHTTPURLResponse *httpResponse = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&httpResponse error:nil];
NSString *dateString = [[httpResponse allHeaderFields] objectForKey:@"Date"];
NSDate *currentDate = [NSDate dateWithNaturalLanguageString:dateString locale:NSLocale.currentLocale];
stevel
  • 1,612
  • 1
  • 14
  • 13