I wanted to detect two events :
First one I have been able to achieve here: Is there a way to check if the iOS device is locked/unlocked?
Now I want to detect the second event, is there any way to do it ?
You basically already have the solution, which I'm guessing you found from one of my recent answers :)
Use the com.apple.springboard.hasBlankedScreen
event.
There are multiple events that occur when the screen blanks, but this one should suffice:
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
NULL, // observer
hasBlankedScreen, // callback
CFSTR("com.apple.springboard.hasBlankedScreen"), // event name
NULL, // object
CFNotificationSuspensionBehaviorDeliverImmediately);
where the callback is:
static void hasBlankedScreen(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
NSString* notifyName = (__bridge NSString*)name;
// this check should really only be necessary if you reuse this one callback method
// for multiple Darwin notification events
if ([notifyName isEqualToString:@"com.apple.springboard.hasBlankedScreen"]) {
NSLog(@"screen has either gone dark, or been turned back on!");
}
}
Update: as @VictorRonin said in his comment below, it should be easy to keep track yourself whether the screen is currently on or off. That allows you to determine whether the hasBlankedScreen
event is occurring when the screen goes on or off. For example, when your app starts, set a variable to indicate that the screen is on. Also, any time any UI interaction occurs (button pressed, etc.), you know the screen must currently be on. So, the next hasBlankedScreen
you get should indicate that the screen is off.
Also, I want to make sure we're clear on the terminology. The device locks when the screen automatically darkens due to a timeout, or when the user manually presses the power button. This happens regardless of whether the user has a Passcode configured. At that time, you will see the com.apple.springboard.hasBlankedScreen
and the com.apple.springboard.lockcomplete
events.
When the screen turns back on, you will see com.apple.springboard.hasBlankedScreen
once again. But, you will not see com.apple.springboard.lockstate
until the user has actually unlocked the device with a swipe (and maybe a passcode).
Update 2:
There's yet another way to do this. You can use an alternate set of APIs to listen for this notification, and also get a state variable when the notification comes:
#import <notify.h>
int status = notify_register_dispatch("com.apple.springboard.hasBlankedScreen",
¬ifyToken,
dispatch_get_main_queue(), ^(int t) {
uint64_t state;
int result = notify_get_state(notifyToken, &state);
NSLog(@"lock state change = %llu", state);
if (result != NOTIFY_STATUS_OK) {
NSLog(@"notify_get_state() not returning NOTIFY_STATUS_OK");
}
});
if (status != NOTIFY_STATUS_OK) {
NSLog(@"notify_register_dispatch() not returning NOTIFY_STATUS_OK");
}
and you will need to keep an ivar, or some other persistent variable, to store the notification token (do not just make this a local variable in the method that registers!)
int notifyToken;
You should see the state
variable, obtained via notify_get_state()
, toggle between 0 and 1, which will let you distinguish between screen on and off events.
Although this document is very old, it does list which notification events have an associated state that can be retrieved via notify_get_state()
.
Warning: see this related question for some complications with this last technique