I need to do something in applicationDidEnterBackground
. But I need to differentiate which user action causes the "enter background": screen lock or home button press.
I was using this code, which is from this post - How to differentiate between screen lock and home button press on iOS5?:
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateInactive) {
NSLog(@"Sent to background by locking screen");
} else if (state == UIApplicationStateBackground) {
NSLog(@"Sent to background by home button/switching to other app");
}
It works fine on iOS6. but on iOS7 (both device and simulator), I always get UIApplicationStateBackground
, whether the user clicks the home or the lock button.
Does someone have an idea about what could cause this? iOS 7 updates to multi-task background handling? Or some setting of my app (my app's background mode is off)?
And is there an alternative solution?
This can help you both on iOS6 & iOS7 :).
When user press lock button you will get a com.apple.springboard.lockcomplete
notification.
//new way
//put this in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
NULL,
displayStatusChanged,
CFSTR("com.apple.springboard.lockcomplete"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
//put this function in AppDelegate
static void displayStatusChanged(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo) {
if (name == CFSTR("com.apple.springboard.lockcomplete")) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"kDisplayStatusLocked"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
//put this in onAppEnterBackground
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateInactive) {
NSLog(@"Sent to background by locking screen");
} else if (state == UIApplicationStateBackground) {
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"kDisplayStatusLocked"]) {
NSLog(@"Sent to background by home button/switching to other app");
} else {
NSLog(@"Sent to background by locking screen");
}
}
//put this in - (void)applicationWillEnterForeground:(UIApplication *)application
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"kDisplayStatusLocked"];
[[NSUserDefaults standardUserDefaults] synchronize];
CGFloat screenBrightness = [[UIScreen mainScreen] brightness];
NSLog(@"Screen brightness: %f", screenBrightness);
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateInactive) {
NSLog(@"Sent to background by locking screen");
} else if (state == UIApplicationStateBackground) {
if (screenBrightness > 0.0) {
NSLog(@"Sent to background by home button/switching to other app");
} else {
NSLog(@"Sent to background by locking screen");
}
}
This solution was taken from this answer and worked for me. It is a bit hacky but it makes it easier to be accepted on the appstore because it doesn't use com.apple.springboard.lockcomplete or com.apple.springboard.lockstate.
The following code goes into your AppDelegate:
func applicationDidEnterBackground(_ application: UIApplication) {
if (DidUserPressLockButton()) {
print("User pressed lock button")
} else {
print("user pressed home button")
}
}
private func DidUserPressLockButton() -> Bool {
let oldBrightness = UIScreen.main.brightness
UIScreen.main.brightness = oldBrightness + (oldBrightness <= 0.01 ? (0.01) : (-0.01))
return oldBrightness != UIScreen.main.brightness
}
The idea is to try changing the brightness of the screen after the application went to background and to check if this change was successful.
Disclaimer: it doesn't work on the simulator and you will have to test it on a real device.
It doesn't work in Swift, you need to do some modification to make it work in Swift as follow
1.create a objectiveC file named LockNotifierCallback.m as follow:
static void displayStatusChanged(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo) {
if ([(__bridge NSString *)name isEqual: @"com.apple.springboard.lockcomplete"]) {
NSLog(@"Screen Locked");
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"kDisplayStatusLocked"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
@implementation LockNotifierCallback
+ (void(*)(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo))notifierProc {
return displayStatusChanged;
}
@end
create a head as well:
#import
@interface LockNotifierCallback : NSObject
+ (void(*)(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo))notifierProc;
@end
2.bridge this file to swift
3.add function to APPdelegate.swift:
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), nil, LockNotifierCallback.notifierProc(), "com.apple.springboard.lockcomplete", nil, CFNotificationSuspensionBehavior.DeliverImmediately)
PS:UIApplicationState doesn't work perfectly in here