I have an app that needs to do something when it’s sent to background using the Home button and something else when the device is locked using the top hardware button. The standard way of solving these requirements are the notifications and delegate methods sent out by UIApplication
. On iOS 4 they look like this:
// Pressing the home button Will resign active. Did enter background. // Tapping app icon on Springboard Will enter foreground. Did become active. // Pressing the lock button Will resign active. // Unlocking the device Did become active.
In other words, it’s quite easy to tell between locking and backgrounding. On iOS 5 the behaviour changed:
// Pressing the home button Will resign active. Did enter background. // Tapping app icon on Springboard Will enter foreground. Did become active. // Pressing the lock button Will resign active. Did enter background. // Unlocking the device Will enter foreground. Did become active.
Notice that the didEnterBackground
and willEnterForeground
notifications are now sent out even when (un)locking the device, making it impossible to tell between locking and backgrounding. Is this change documented somewhere? Is it a regression? Do you know another way to distinguish the two cases?
Apparently, you first have to enable the respective lock screen widgets on your device, and it's quite easy. Get to the Settings and tap the Security option. Next, under the 'Screen security' option, tap and enable the Widget box.
When chosen, the Lock screen displays notices, not message previews or content.</p>\n<p class=\"Tip\">To make the Lock screen notifications useful, double-tap one. The app that generated the notification starts, and you can see more details.
In my preliminary testing via the simulator, checking the application state with
[[UIApplication sharedApplication] applicationState]
in either
- (void)applicationWillEnterForeground:(UIApplication *)application - (void)applicationDidEnterBackground:(UIApplication *)application
allows you to differentiate between a call to lock the device and just switching back to the homescreen. A lock screen will return 1 (UIApplicationStateInactive), whereas a home button press will register as a 2 (UIApplicationStateBackground).
It seems consistent and should work on an iOS device just as reliably as it does in the simulator.
The iOS 6 method no longer works in iOS 7. In order to do this now, you have to utilize CFNotificationCenter and listen for a darwin notification (labeled: com.apple.springboard.lockcomplete). You can find the github repo with the sample project here: https://github.com/binarydev/ios-home-vs-lock-button
Credit for the iOS 7 fix goes out to wqq
I have looked into this quite a bit so I would love to be wrong here if someone knows something I don't, but technically, there is no documented way to tell the difference between locking the device, and sending to background.
One thing you can check however, is the UIApplicationState
during the transition from foreground to background. Locking a device will give UIApplicationStateInactive
and moving the App to the background will give UIApplicationStateBackground
. But, since this behaviour is not officially documented it may change in the future.
A basic example:
- (void)applicationDidEnterBackground:(UIApplication *)application { UIApplicationState state = [[UIApplication sharedApplication] applicationState]; NSLog(@"Device state: %@", state); switch (state) { case UIApplicationStateActive: /* ... */ break; case UIApplicationStateInactive: /* Device was/is locked */ break; case UIApplicationStateBackground: /* User pressed home button or opened another App (from an alert/email/etc) */ break; } }
UIApplicationState
- The running states of an applicationtypedef enum { UIApplicationStateActive, UIApplicationStateInactive, UIApplicationStateBackground }
UIApplicationState
Constants
UIApplicationStateActive
- The application is running in the foreground and currently receiving events. Available in iOS 4.0 and later.
UIApplicationStateInactive
- The application is running in the foreground but is not receiving events. This might happen as a result of an interruption or because the application is transitioning to or from the background.
UIApplicationStateBackground
- The application is running in the background.
According to the UIApplicationDelegate Protocol Reference:
applicationWillResignActive: didEnterBackground: // ... willEnterForeground: applicationDidBecomeActive:
are the only methods that ever get called in both situations.
According to the iOS 4.3 to iOS 5.0 API Diff, these are the ONLY changes regarding UIApplication
or UIApplicationDelegate
, so I couldn't find where they documented any of these notification changes:
UIApplication.h Added -[UIApplication setNewsstandIconImage:] Added UIApplication.userInterfaceLayoutDirection Added UIApplicationDelegate.window Added UIApplication(UINewsstand) Added UIApplicationLaunchOptionsNewsstandDownloadsKey Added UIRemoteNotificationTypeNewsstandContentAvailability Added UIUserInterfaceLayoutDirection Added UIUserInterfaceLayoutDirectionLeftToRight Added UIUserInterfaceLayoutDirectionRightToLeft
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With