Detect device time change ONLY WHEN it is changed manually - iphone

Problem: I know about the method applicationSignificantTimeChange to detect manual time change. But the method documentation says:
Examples of significant time changes include the arrival of midnight, an update of the time by a carrier, and the change to daylight savings time. The delegate can implement this method to adjust any object of the application that displays time or is sensitive to time changes.
So it detects not only a manual time change, but arrival of midnight as well. In my application, that will create a problem as the user will see an alertbox:
You have change the time. Please revert back to actual time.
even when he resumes the app after midnight (or may be he minimized the app and went to sleep. Next day he wakes up, resumes the app and surprisingly gets the time change notification).
Question:
How to show the alert only on manual time change and not on arrival of midnight ?

Just use NSSystemClockDidChangeNotification
Apple doc link

I have used a variant of the remote server time check for one or a few years now. It works pretty well, on iOS.
Fetch remote time.
In your time checking class, store the offset between remote time and device time, store that in a simple NSTimeInterval variable.
Now you can get "real time" at any time from your time checking class, because it can take the current device time and just add the stored offset and you will have the real time, all the time.
Whenever the app backgrounds, you will need to delete the stored offset, because the user can be fiddling with the time settings.
For every app foreground event, you will have to perform 3. again. Go get remote time again. Deny any calls to get real time until you have that offset again. Any calls depending on the real time existing will have to fail gracefully in those events where real time has not yet been fetched.
Now the offset you get should/can be compared with the offset you got last time. Decide a threshold, like 15 seconds. If the offset change from last time exceeds that threshold, the user likely changed time manually. This is a useful event for me. Of course even though the user can change the device time I will always have real time handy (most of the time).
Afaik, I always work with UTC time stamps to avoid any locale troubles.

Always its better to check such things with server time.
Follow below steps.
Fetch the server time and convert to current locale.
Check mobile time using current locale.
If they are not same, that means user has changed the time.
Let me know if this is clear or not.

Related

Restrict user to use only network provided time

I made an attendance app in Flutter in which I want to restrict employees to use only network provided time so that employees won't be able to temper the date and time.
Is there any option or solution to implement this in android and iOS as well?
Using this package datetime_settings we will get the settings of Automatic date & time of mobile so when automatic date & time is on mobile will give us an accurate network time otherwise we will show an error to turn on the automatic date & time in settings. That's how I used to restrict users to use only network-provided time.
I'll tell you what worked for me. Hope this can help you. I don't know if it's the most optimized way to do it, but it worked very well for me:
You need to create an internal clock for your app, and from this, use it instead of the DateTime.now() function. For this, you must take the server time when opening the app, and keep it updated with a timer that runs every 1 second.
Please note that the app goes to sleep (or closes) when the device is locked or the app is minimized for a certain amount of time (this depends on the operating system and battery saver settings), thereby stopping the internal clock, and consequently, it is delayed when the app is activated again. In my case, I got around this problem by using a foreground service that I designated to perform this task (I used flutter_foreground_task). Another advantage of using a foreground service, is that the user can close the app and the clock keeps running (and in my case, I also perform other simple tasks periodically).
If the user does not manipulate the system time, the difference should never reach 1 second.
Optionally, you could check when retrieving the server time, the difference with the device time, and if it is greater than a certain gap that you determine, warn the user, so that he can correct it if he prefers, so that he does not see a discrepancy with the time recorded and displayed by the application.
Regards.

Is it possible to call past date UILocal Notification?

I have to added a local notification for next 30 days(June-01-2013 t0 June-30-2013).
For Example:
I have to change the date on the "settings" to June-15-2013, and then I have to change the date to June-05-2013. The local notification not called for the (June-01 to June-15). After June-16 is working fine.
My question is
1) Any restrictions for the UILocalNotification to fire the past dates?
2) Is it possible to fire the local notification for past dates?
Please help me. Thanks in advance.
Apple docs states that
If the specified value is nil or is a date in the past, the
notification is delivered immediately.
So if you are setting the fireDate of a local notification in the past the notification will be fired immediately.
Also your case I think is a special one because you are manually change the device date settings. The date settings may be changed when the time zone is changed but your case is different, you are not changing the time zone, you just change the date and I think the local notifications before (in the past) your new date are ignored.
Well, this is one of the situation i had faced when cam testing of robustness of the app. My app was also issuing notification for future dates. All goes well, if user does not change the date. But as part of testing, changing date to future and then past makes disables some notification which were suppose to appear.
The way i workaround this situation was responding to following call back in application Delegate
-(void)applicationSignificantTimeChange:(UIApplication *)application
Here i re-issued all the notifications as per required from the current date. That did the trick in my case. It's a heavy solution as all notifications has to be deleted and re-issued, but did the required for me.
There is one more case where you may required to re-Sync the notification. User may had also changed the date, when app is closed. For this, i made the application to reSync the notification everytime it launches. You can optimize this approach, by checking if there is significant change in date or not.

Avoiding Local Push notification to fire after changing time

In my app, I want to send a Local Push notification every 30 minutes. One way is to just configure local push notification and fire it. However there is a possibility that user can change his time and move forward 30 minutes. In this way a cheat can be done.
I want to configure my app so that notification only occur after 30 minutes. How can I do that. My app does communicate with server and can get its timestamp but I want to do things which don't use much server resources.
The only way I can think of to detect a user altering the system clock is as follows:
When app launches, ask your server the time and note the difference between that and [NSDate date]. Persist that as [NSNumber numberWithFloat:serverOffset];
Implement a method like - (BOOL)deviceClockChanged that asks the server again and compares to the persisted value. If the difference is greater than some small tolerance for clock drift + latency on the synch request, then you can conclude that the clock was changed. Do all this in UTC so it works independent of user travels between time zones.
Consider this: if the user wants badly enough to fool your app about the time in order to delay a notification, messing up the rest of his phone, maybe you ought to just let him edit the notification schedule.
I can supply code examples for points 1 and 2 if you want, and if you want I can supply some #"alert text" for point 3 that will make the user feel really guilty about editing his notifications.
My original answer here. If you choose to let user edit notifications, these methods will be key... UIApplication has a property:
NSArray *scheduledLocalNotifications;
and implements:
- (void)cancelLocalNotification:(UILocalNotification *)notification
So to change one, cancel it, then reschedule it.

Determine if day change has occurred

I would like to create a notifciation that occurs every time a new day has occurred locally (either while using the app, or if it occurs in between launches). I was wondering what might be the best way to go about observing this change.
While your app is running, you can listen for the UIApplicationSignificantTimeChangeNotification notification and test the current day when you receive that. When your app quits, you can save the current day to your preferences, and when the app launches again, you can test the saved day against the current day.
You can get information about the current day using NSDateComponents.
As mentioned in the other thread, as of iOS8, you can also directly listen to NSCalendarDayChangedNotification.
Check out :
Erica Sadun Time Utililties
There are some useful methods there for checking dates.
Alternatively you can look at UILocalNotifcations
You could schedule a local notification with a repeatInterval of one day.
It all depends on what you want to do but those are some options.
I'd probably do two things:
While the app is running, have an NSTimer set to poll the current date [NSDate date] at a given interval. Store the value of the last date someplace (even in the user defaults) and then compare the new time to the stored time to check for a new day.
When closing/quitting the app, store the current date and time in the same manner above. Then, when launching the app or bringing it to the foreground, check the current date against the stored date.
NSDateComponents, NSCalendar and NSDate will come in handy for this.

Is there a replication delay in Salesforce.com via the APEX API?

I have been using SOAP to deal with Salesforce.com and have been using the getUpdated() call, using the timestamp I retrieve from the getServertimestamp() call.
I have watched my process check, (it polls every minute) and a few seconds after I save the change in the Sandbox environment, I see it poll, get no <ids> in the getUpdated call, and then on the next poll, the modified id shows up.
Is there a backend replication delay in SFDC? I suspect there is, but have had no luck in identifying the magnitude of it. Anyone else experienced this?
Additionally, I realize I should mention, this is all in a Sandbox copy of the environment, which may confuse matters even further.
Update: I just tested, and I made a change, and my poll ran 48 seconds later, and did not see the updated object. But 1 minute 48 seconds later it did see it. So that is one data point. (I know my SOAP endpoint and Web interface are both running on the same server at SFDC, tapp0).
There's no delay in the recording of the change, but the getUpdate/getDeleted calls round down the specified time to the nearest minute, so a finish time of now, gets rounded down, and the just made change falls outside of the range.
Also, if you're doing near realtime replication via these calls, then make sure to pay attention to the inflight transaction timestamp returned, otherwise you can miss changes (as the change timestamp can't be the actual transaction commit time)