How can I locally detect iPhone clock advancement by a user between app runs? - iphone

A common exploit in casual games is to artificially advance the system clock to jump ahead in gameplay. How can such user clock advancement be detected by an app on an iOS device?
Must not involve network communication
Must not assume app is open (running or suspended) while clock is advanced
Must detect clock advancement, detecting clock rollback is not sufficient
Ideally, the solution would be robust against reboots, but that is not a requirement.

CACurrentMediaTime & mach_absolute_time
Take a look at this questions:
iOS: How to measure passed time, independent of clock and time zone changes?
Calculating number of seconds between two points in time, in Cocoa, even when system clock has changed mid-way
CACurrentMediaTime uses mach_absolute_time:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreAnimation_functions/Reference/reference.html
Here you have an example on how to use CACurrentMediaTime:
http://www.informit.com/blogs/blog.aspx?b=02b4e309-308c-468a-bab1-cebb1404be6a
Here you have a more information on mach_absolute_time:
http://developer.apple.com/library/mac/#qa/qa1398/_index.html
http://shiftedbits.org/2008/10/01/mach_absolute_time-on-the-iphone/

I was thinking about the fact that the CoreLocation stuff could do this if that part of the GPS data was exposed to you. However that got me thinking.
My only (far fetched) suggestion is to put something into background processing - which has to be for one of a small specific set of reasons, for example to track location in the background. As a side effect of that, try to detect a clock change on a regular timer. Apple might reject it as it may be clear that its not using the location information and its just a reason to exploit background processing.
Any solution not involving networking is so much harder to implement, I wonder why you're not using it.

Whilst I don't think it's possible to reliably determine whether or not a user has manually turned their clock forward without network access, you can of course reliably determine if they've travelled back in time. And since we know this to be physically impossible it can therefore be assumed they have manipulated their clock to cheat.
What I mean by this is, isn't the usual process to trigger some action in-app that requires a period of waiting, exit the app and turn the clock forward, re-launch the app to gain whatever they were waiting for and then reset the clock back to the actual time?
If this is indeed the case, then to build on the suggestion by #smgambel, you could store the physical time and current time-zone on each launch and compare with the previously stored time and time-zone. If the time is behind the previously stored time, and the time-zone of the device hasn't changed then you can safely assume the user has manipulated the clock.

Related

CLLocationManager geo-fencing/startMonitoringForRegion: vs. startMonitoringForSignificantLocationChanges: vs. 10-minute startUpdating calls

I am trying to set up an app that will be able to check people's locations in the background, see if they are at a given location, and send a ping to a server if they are. We do not want to drain the energy of our users, so we are attempting to figure out the best solution.
I've done substantial reading and I have not found very much information on these methods. I'll go through the pros and cons as I understand them right now
startMonitoringForSignificantChanges
Description: Based off of wi-fi and cell tower changes the system wakes up the app.
Docs:
Apps can expect a notification as soon as the device moves 500 meters
or more from its previous notification. It should not expect
notifications more frequently than once every five minutes. If the
device is able to retrieve data from the network, the location manager
is much more likely to deliver notifications in a timely manner.
Pros:
Most battery efficient
Cons:
Dependent on wi-fi/cell tower changes
Can only assume that this will be called every 200m to 2km (if not more in certain areas)
More on accuracy
Thus, inconsistent and imprecise
10-minute start-updating or "n-minute updating":
Description: This basically asks the app for more time, when that extra time is about to expire, it calls [self.locationManager startUpdating], grabs the location and extends the background thread for 10 more minutes.
Pros:
Consistent
Can be as accurate as you want it to be as consistently as you
want it
Cons:
Has to do a call every ten minutes or less to keep the app running in the
background (ie n can't be greater than 10 for the calls)
Questions:
What effect does this have on the battery? Does waking up the GPS and shutting it off hurt the battery more? I couldn't imagine running a brief location check in the background would drain the battery that much... but then again, I don't know what goes into powering up the GPS and getting a usable signal.
startMonitoringForRegion (geo-fencing):
Simply put, your app gets woken up when you enter into a pre-defined region. This is the oddball of them, it is more recent and there is less documentation on it. I can't find a good description on how the "system monitors" the boundary crossing. For all I know it is some really smart algorithm, or they are constantly pinging the GPS which would make it less effective than the other methods for doing this.
Pros:
Simple implementation
Managed by the system so you don't have to invent your own ad hoc geo-fences Only triggers on boundary crossing... no unnecessary data to just throw out in exchange for a battery hit
Thus, should be the best for this sort of thing, accurate, managed by the system
Cons:
People question its effectiveness
Huge conflicts on whether or not it is good for battery life or if it
drains battery life terribly.
How is the system monitoring this!?
Basically, indeterminate behavior.
I guess my question boils down to how does startMonitoringForRegion: compare to these other methods of testing user location in the background when it comes to battery life, consistency, and precision. Has anyone thoroughly tested this? Or used it in their app and gotten at least some feedback? Likely, for my purposes, the trade-off is between geo-fencing and the 10 minute update method. (Also given what Apple has publicly said about iOS7 there will be some background tasks... will this change the calculus for the trade-off between these two methods?) Does anyone have an idea of how these two compare?
Thanks so much! Looking forward to seeing if we can get to the bottom of how to compare these methods.
I've been working on vehicle tracking using GPS for 2 years. Learned a lot the hard way... In my experience startMonitoringForRegion or Geo-fencing depends upon cell change events, didEnter or didExit events doesn't fire up until there is a cell/wifi change event. So it doesn't make any difference w.r.t battery consumption. However it does extra computation which depends on how many regions currently are being monitored. Even Apple's Reminder app doesn't give good results for location based reminders because it uses geo-fencing.
The other approach starting GPS for n minutes after each m-minutes is good option, it should not affect the battery life, if done wisely. What exactly effect the battery is constant GPS activation in high precision mode. Like for instance If you enable GPS with kCLLocationAccuracyBest and distance-filter = 0, you can literally observe battery drainage and soon your device will also start getting hotter.
If I was you, I would go for activating GPS after every 10 minutes for 5 sec with kCLLocationAccuracyBest (or may kCLLocationAccuracyNearestTenMeters to use less battery, if accuracy is not that much important) and distance-filter = 5 (meters). Battery consumption in this case will be unnoticeable. You can play around with similar settings which can address your specific case and finally find out what is best you.
BTW: iPhone uses AGPS, A-GPS additionally uses network resources to locate and use the satellites in poor signal conditions. So, when you do startUpdatingLocation it will also use nearby cell tower information. see http://en.wikipedia.org/wiki/Assisted_GPS

iPhone - Synchronize two iPhones to make them start task on same time

I need to make an application that will start playing same media on two (or more) iPhones simultaneously, the problem is that it has to be perfect, no second delays and such. Is it possible that iPhone has some universal time stamp that is perfectly (or near-perfect) on every device. Or maybe I have some other options?
2 rules:
Find a way to have the same time on each devices
Use a "startAtTime" function using this shared uniform time. No "startNow" function.
the iPhones are supposed to be able to sync their date and time using a remote server, if this is not accurate enough (who knows), a way to achieve this (assuming you iPhone are able to communicate between them already):
The master send its time to a slave 10 (or more) times.
Each time the slave compare it's time with the one received and make a delta
After 10 tries, make a mean of the deltas and use this mean to adjust the slave time accordingly
There's no internal clock that is different to the system clock - so this means that each of the devices could have completely different time settings (in fact, it's highly likely that they will have different time settings even if only by a second or two).
Using a network/internet connection to synchronise against a central time server may be an approach that could be taken, but that would then require the network/internet connection and you would have to set the clocks taking into account lags on the connection to/from the time server.
You could have to have some kind of local synchronising system. If they are in close proximity, one approach may be to create an ad-hoc bluetooth connection between the devices in your app and then use some synchronisation code in you app to get the internal timers the same. You could, for example, have the first app to launch be the "controller" and then all the other apps would seek this controller and synchronise against it. The synchronisation could just be the controller sending out timestamp messages which the other devices can get and set an internal counter to match.
Without knowing much more about the requirements, it's hard to say how best to approach this as there may be limitations regarding time between running the app and it making the sound, or if you have to have a triggering signal, or if it is just at time x they need to make the sound.
If they are in same time zone and same time set ,you can schedule it to start your function in the paticular point of time using NSTimer's
- (id)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep;.
One option you have is to access the time from a common server and then start a timer on both devices accordingly (calculating depending on the time you got from the service)so you have exact time on both the devices and then play it ...
Even this has a catch as internet speed may vary and there might be a slight in delay on one of the two devices in getting the response from the server as compared to the other device and looking at your requirement they might go out of sync by a milisecond or so which will be visible.. :/ any other ideas anyone.. ?

Internal clock in iPhone background mode

In my application i want to run an internal clock in background mode [while application is not running in foreground].
The whole functionality will be like this:
The objective is to get the server time to use in the application, because using device time may sometimes cause issues. The issues may be in situations like somebody has changed the user's iPhone time etc. So i am following the below method.
-Running an internal clock in my application background even if the application is not running.
-Communicate with server every 15 minutes to get the real time and run a timer.
-If net is disconnected in between,timer will continue and take the timer time.
My application is heavily depended on this time factor as this is a ticket booking system.Kindly help me to implement this or please confirm whether this is possible or not?
I am developing an iPhone application which involves Ticket Booking System. I registered my application as location based beacuse it is using user's location taken in background for a purpose.
My problem is that i need to run an internal clock in my application in background mode. I need to write the codes for internal clock in core location delegate methods, so that internal clock will also run along with the location bsed services. Will my app get rejected? Is anything wrong in doing like this?
I need to get the correct time to use in my app, so that i am running this internal clock. I can use NSDate, but that will return the device time. Anyone can change the device time. So once somebody chaged, wrong time will affect the smooth functioning of the app. Kindly some body suggest to get the correct time with out running the internal clock ?
Update: Sorry to say my original answer isn't correct. When the device goes to sleep (can happen sometime after it's locked) the internal CPU clock stops ticking, and mach_absolute_time won't update either. Theoretically it will return the exact same value if you call it right before the device went to sleep, and after it awakes.
The best available way I know of to check for date changes is kern.boottime, it holds the boot time, and is modified whenever the system time changes. Among other things, kern.boottime will be updated if the user changes the time, or if the OS changes the time itself according to info from cell towers.
So, in your case, you can take the original time you calculated and modify it according to the modifications in kern.boottime. If you see kern.boottime changed significantly, it may mean that the device was turned off, and in this case you will need to contact the server to ask it for the time until the flight.
Relevant code:
time_t getBootTimeSecs(void)
{
struct timeval boottime;
size_t size = sizeof(boottime);
int ret = sysctlbyname("kern.boottime", &boottime, &size, NULL, 0);
assert(ret == 0);
return boottime.tv_sec;
}
Original (incorrect) answer: You can use mach_absolute_time which isn't affected by date changes made by the user.
When you book the ticket, get the correct date from the server and record mach_absolute_time. Now you will always be able to call mach_absolute_time whenever you want, calculate the difference from the one you recorded initially, and display the correct date.
This will only work as long as the device wasn't shut down, in that case it makes sense for the app to re-connect to the server to get the correct date.
You can also either Local or Push Notifications to alert the user when the target date is getting closer, even if the app isn't running.
apple is support small task for background mode which will work for approximate 10 sec only.
so you can do one thing when app is active then get time form server and update your local time according that.
I think that you can only detect that the date of the iOs device has been changed (using NSSystemClockDidChangeNotification).
I guess you to use this notification and force reload the real date of your application from your server (With a WebService).
EDIT: You can use the systemUptime in NSProcessInfo:
NSLog(#"ProcessInfo System uptime: %f",[NSProcessInfo processInfo].systemUptime);
but it will not solve your problem if the Device is restarted.
I think there are 2 ways you can go about solving your problem.
Never use system time. In other words, never call [NSDate date] in your code. When you need the current time, call an NTP server. This will of course cause latency in your app, but will guarantee accuracy.
When the app launches, or enters foreground, verify that the system time is reasonably accurate against an NTP server. If the system time is off by more than your tolerance level, then do not let them continue running the app until they address it. If the system time is okay, then start monitoring to ensure they don't change the system time while running the app (NSSystemClockDidChangeNotification). If they pass the initial check, but the move the clock forward, you can catch that and disable the app til they change it back to being accurate.
Here is an iOS NTP implementation which could be helpful in implementing either solution above. http://code.google.com/p/ios-ntp/
EDIT: The Ticketmaster app uses technique #2, so this seems like a reasonable solution for a ticketing app that requires your system time to be correct.
timezone settings should not affect time as in UTC
your app cannot run in the background. Abusing the location requirement for this will cause your app to be rejected by Apple
so my suggestion: do the logic server side with push notification

Time based GPS location in background (iphone)

I want to create an (game based) iPhone application which sends your GPS location on a specific time (like 3-5 times a day) to a server. I found an apple page explaining some functionality to run in the background like location, music and VOIP.
I need the GPS to be accurate on the meter.
Can someone help me with a small example?
It really depends on your usage of the location. If you monitor actively, kiss the battery of your user goodbye. Very detailed accuracy, even bigger hit to battery. The backgrounding of location is all or nothing as far as accuracy goes.
Less hit, less accuracy is -startMonitoringForSignificantLocationChange. May not be accurate enough for you.
Better depending on usage, region monitoring. Triggers event on entry or exit of defined region.
You don't have the benefit of accuracy and timed location based events. You can do it, but is going to require a lot more effort on your end.
While this is untested, I am planning an app with a similar need. My solution is that on a significant location change, the app will determine what interval exists between the update timestamp, and when I care to know the users location (5pm for instance). If that's below some threshold, it will go into startUpdatingLocation mode (full power, battery draining, which is why that threshold is important) and then, on each location update, check if that target time has passed. if SO, send the update to your server, and go back to monitoring for significant changes. The catch is that if it still requires some movement to trigger the significant change update...so it isn't a perfectly reliable solution, but it may work depending on how you're using the data
You can't "schedule background work". iOS doesn't allow it.
The solution is to set yourself up for notification on significant change (which is some hit to the battery, but it's not horrible), and then only DO anything with that at occasional intervals.

iPhone running periodical process in the background - battery optimized way

I want to run a specific task in the background. This task takes few seconds to complete (it writes some GPS location data to a file). This task should run once every 1 hour.
As I understand from the SDK, I do not have a way to INITIATE something in the background unless I run Location Services forever. When this service runs, it gives me an event from time to time, and I'm able to run my code during these calls. I tried it, and even with the minimal precision possible, my battery goes down very quickly.
So, I'm looking for a way to run Location Services for few seconds every hour. All the rest of the time I do NOT want to run Location Services and I do NOT want to use the battery.
Can you help here please?
Thanks,
Gena
What do you actually want to know every hour? Are you trying to determine the location accurately, or just determine if the phone has moved significantly? startMonitoringSignificantLocationChanges will notify you when the phone moves "significantly" (which generally means changing cell towers). In cities this can happen quite often. startMonitoringForRegion:desiredAccuracy: will only notify you when you move outside of a given radius.
startMonitoringSignificantLocationChanges is pretty cheap. It mostly relies on the cell antenna, which is generally on anyway. If it fires more than once an hour, you could always just skip processing and return. But there's no guarantee that you'll be called once an hour, particularly in rural areas.
If you are a VoIP app, then you may register a periodic "checkin" interval when you may run code. But you cannot do this for location apps.
Have you profiled your code using the Energy Diagnostics instrument? What's actually eating time and power? Are you chewing on the radio, the CPU, the disk?
EDIT
When the app dies, Significant Changes still continue to run and leave a small direction arrow icon next to the percentage on the top toolbar of the iPhone. My users complain that the icons remains after killing the app
After the app dies, if you were registered for significant changes, you would expect to be relaunched in response to them. If you want to unregister in cases where you are terminated, you can add stopMonitoring... to your applicationWillTerminate: method. This isn't guaranteed to be called, but it is a good thing to do, and I believe it will be called if the user terminates you directly and you were not suspended (haven't tested that).
Again, significant location changes should be extremely cheap in terms of battery life as long as there is cell coverage. They should not force the GPS to stay on.
Your best bet is to use significant location changes ... here are some links you can get help from -
http://developer.apple.com/library/ios/#documentation/CoreLocation/Reference/CLLocationManager_Class/CLLocationManager/CLLocationManager.html
http://www.switchonthecode.com/tutorials/getting-your-location-in-an-iphone-application
http://longweekendmobile.com/2010/07/22/iphone-background-gps-accurate-to-500-meters-not-enough-for-foot-traffic/#more-480