iOS auto logout of application - objective-c

I am wanting to create a timer or something of sorts to auto logout the user after x minutes of inactivity. I would like to do it the same way the Bank of America application does it. The way the BofA app does it is even when the application is put into the background it still keeps track of the time. When the time limit is reached a notification will popup stating you are being logged out.
How can this be done without the timer being suspended when the application goes into the background?

I think maybe the simplest thing you can do is register your AppDelegate with the NSNotificationCenter to listen for all events from all (or maybe specific) senders.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(resetTimer) name:nil object:nil];
You need to take care with passing nil to the name and object parameters as you will get a ton of notifications (even some not originating from the application, i.e., memory warnings). If you know of or have the list of specific event names and/or objects I would observe on those instead.
In your resetTimer method, you will simply invalidate the previous timer and create a new one that will call some logout method AND set an iVar to the current date/time (i.e., timerStart = [NSDate now];)
The above steps will take care of your app while it is in the foreground.
When the app is backgrounded, the timers will quit working. However, when the app returns to the foreground, you can calculate the delta between [NSDate now] and your timerStart iVar. If the delta is greater than some interval, you invoke your logout method. If not, you can just call resetTimer to start your timers again.
EDIT
If you want the backgrounded app to alert that the user is about to be logged out, you can use a UILocalNotification. You can schedule one to alert when the application enters the background. When the application enters the foreground, you can cancel that notification (and perform the steps I mention above).

Related

Detect user activity in Cocoa app (taps, clicks, ...)

For a Mac application, I want to detect user activity in the app, so I can periodically let a web service know that the user is still active on the endpoint.
In Cocoa Touch, I would override sendEvent of UIApplication, but the sendEvent in NSApplication equivalent in Cocoa, doesn't do the same.
Which APIs should I use instead for a Mac application, to detect user activity? Can I perhaps somehow have a global responder hookup from where I can send the pings to my service?
Preferably, I want to listen for actions the user can be expected to perform every 15-30 second, ie. clicks, tabs, typing, switching windows or applications.
You most likely want to create a global event monitor using +[NSEvent addGlobalMonitorForEventsMatchingMask:handler:]. This calls your handler whenever an event whose type matches the passed mask (you should use NSAnyEventMask) is sent to another application. You can observe, but not change, the event here, which suits your usage perfectly. There is one thing to watch out for: the documentation says that you won't receive key events unless your app is trusted for Accessibility.
You can do similarly for events that are routed to your own application with +[NSEvent addLocalMonitorForEventsMatchingMask:handler:].
It's not a notification, but you can query the time since user activity using CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType).
This worked for me:
-(void) addMyApplicationEventsMonitor {
self.localEventsMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskAny handler:^NSEvent * (NSEvent * event) {
// do your stuff here
return event;
}];
}
-(void)dealloc{
//remember add this to remove your monitor
[NSEvent removeMonitor:self.localEventsMonitor];
}
reference here

UIApplication fixed background fetch interval (private API welcome)

I'm working on an internal app that requires to check the server every 10 mins or so when the application enters background. Normally, I can use APNS when new record arrives.
However, this app will completely skip Apple's garden, so no APN and yes private API.
So the question, is there any way for me to set the background fetch interval directly instead of calling the normal application setMinimumBackgroundFetchInterval:
I also welcome other ideas for the same result.
I recommend implement VOIP background mode, because is simply and provide app wakeup every few minutes. Just set Voice over IP in Background Modes and register handler;
Example:
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
NSLog(#"Here I do something every 600 seconds");
}];
This method more preferable because can work on old iOS, and timeout is fixed vs background fetch where timeout is calculated by user activity and app usage.

Cancel all local notifications when app is closed by the user

There is a small bug in my App.
My App displays notifications at specific times when the App is running and cancel all of them whenever a button is switched.
My problem is that whenever a user closes the App using the multitasking feature of iOS the notifications are still showing up.
I tried to add the following code which doesn't work:
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
[[UIApplication sharedApplication] cancelAllLocalNotifications];
}
The problem is that my App should show notifications when the App is running but shouldn't show notifications when the App is terminated.
Why does the above code not work?
The correct answer is that this cannot currently be done by a multitasking app. One solution is to set a flag in our info.plist declaring your app wants to be killed when the user switches to another app - then you will get the willTerminate message (but get killed then).
There are huge numbers of threads on this topic, one which quotes an Apple doc that tells you backgrounded apps that are terminated do NOT get the willTerminate message is here.
For me, this just means I can now close an open bugreport out with a 'cannot fix' resolution :-)
Just because your app is visible in the app-changer, it doesn't mean it is still running.. it can get closed at any point. You cannot differentiate between the OS closing your app or the user closing your app.
Perhaps a button would be the solution? A button that cancels all notifications?
Or you run a real background task (which can last for about 5 minutes) and stop all notifications afterwards. Or you just schedule the notifications for the next 5-10 minutes and that's it.
For what are you using them?

Timer that works in the background

For the sake of learning i'm making a timer. Used an NSTimer but it appears this stops
when going to the background.
Thought of using NSDate instead. Does this work in the background?
Do i compare current time to a set time to get the timer running properly?
Some thoughts would be greatly appreciated!
If you are looking for something to handle time based events in the background, have a look at UILocalNotification. With a local notification, the OS will alert the user at the appointed time whether the app that scheduled the notification is running or not.
If you are looking for something to happen when the app starts, you can use NSUserDefaults and store a value containing the current timestamp. Fire this off when in the AppDelegate inside applicationWillResignActive method. You can then check this value in the applicationDidBecomeActive.

Calling a method either the second time a condition occurs OR after a timeout, whichever comes first

After plenty of coding in the past days, I'm finally (um) pretty much stuck.
My application listens for an external NSNotification sent by iTunes. The notification is sent out whenever the current playing status changes, in this case most interestingly when the current stream title changes. When you connect to a new radio station, two notifications are usually sent - one as soon as iTunes connects, with the station name as the title, and one soon thereafter (a second or so) with the actual artist and title of the current song. I'm only interested in the artist/title combo, or the second notification. Or, if there's still only one notification sent after a two second pause, use the first one. (Since there's no way of knowing whether there will be one or two beforehand, the timeout is the only way I can think of.)
In fewer words, I want to call a method only the second time a condition occurs, OR after a two-second timeout if only one notification is sent. It should reset back to do the whole deal again after the two seconds have passed.
Any ideas?
This isn't too complicated. You just need to hang on to the first notification until either the timer fires or the second notification comes in. The comments I put in the code should explain the procedure.
- (void)awakeFromNib {
// Register for the notification you're interested in
[[NSDistributedNotificationCenter defaultCenter] addObserver:self
selector:#selector(iTunesNoteCallback:)
name:NSTheiTunesNotificationImInterestedIn
object:nil]; // #"iTunes"?
}
- (void)iTunesNoteCallback:(NSNotification *)note {
// Check whether there's been a notification already
if( !gotFirstNote ){
// If so, hang on to it,
gotFirstNote = YES;
self.currNote = note; // With currNote declared as a retained property
// and start a timer.
noteTimer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(actOniTunesInfo:)
userInfo:nil repeats:NO];
}
else {
// However, if we got a notification already,
// hang on to the new one,
self.currNote = note;
// stop the timer,
[noteTimer invalidate];
// and call the same method the timer would have
[self actOniTunesInfo:nil];
}
}
- (void)actOniTunesInfo:(NSTimer *)timer {
// Reset the flag
gotFirstNote = NO;
// Use currNote; doesn't matter which one it is,
// it's the best info we've gotten
}
If there are two types of notifications, it's even simpler. You no longer need the flag, you just register two callbacks, and as soon as the second one is called, you can invalidate the timer, release the first notification, and use the info you've just gotten.
You need to create a data model that can store and model the notfications as well as their order and timing.
First you would need a data object to store each notification and data about the notification.
- the notification object
- the time stamp when the notification arrived
- type of notification
Then you would need a container-object that could hold the data-objects in an array as well as start and catch timers. So, when a notification arrives, it is classified, stored in a data object which is then pushed onto the array. If it is the first type of notification the container object starts a two second timer. If another notification of the second type arrives, the container-object kills the timer but if the timer fires, then it returns the data-object of the last first type notification that is more than two seconds old.
Once you've triggered an action, empty the container-object and start over.