当iOS设备进入睡眠模式时(当屏幕变黑时),有没有可以检测到该事件?

Roh*_*yap 13 iphone-privateapi ios sleep-mode

我想检测两个事件:

  1. 设备被锁定/解锁.
  2. 设备进入睡眠状态,屏幕变黑.

我能够在这里实现的第一个: 有没有办法检查iOS设备是否被锁定/解锁?

现在我想检测第二个事件,有什么方法可以做到吗?

Nat*_*ate 20

你基本上已经有了解决方案,我猜你从我最近的一个答案中找到了:)

使用该com.apple.springboard.hasBlankedScreen活动.

屏幕空白时会发生多个事件,但这个应该足够了:

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                NULL, // observer
                                hasBlankedScreen, // callback
                                CFSTR("com.apple.springboard.hasBlankedScreen"), // event name
                                NULL, // object
                                CFNotificationSuspensionBehaviorDeliverImmediately);
Run Code Online (Sandbox Code Playgroud)

回调是:

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!");
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:正如@VictorRonin在下面的评论中所说,应该很容易跟踪自己屏幕当前是打开还是关闭.这允许您确定hasBlankedScreen在屏幕打开或关闭时是否发生事件.例如,当您的应用启动时,请设置一个变量以指示屏幕已开启.此外,任何时候发生任何UI交互(按下按钮等),您都知道屏幕当前必须处于打开状态.所以,hasBlankedScreen你得到的下一个应该表明屏幕已关闭.

另外,我想确保我们对术语很清楚.当屏幕由于超时或用户手动按下电源按钮而自动变暗时,设备会锁定.无论用户是否配置了密码,都会发生这种情况.那时,你会看到com.apple.springboard.hasBlankedScreencom.apple.springboard.lockcomplete事件.

当屏幕重新打开时,您将com.apple.springboard.hasBlankedScreen再次看到.但是,com.apple.springboard.lockstate在用户实际使用滑动(可能是密码)解锁设备之前,您将看不到.


更新2:

还有另一种方法可以做到这一点.您可以使用一组备用API来侦听此通知,并在通知到来时获取状态变量:

#import <notify.h>

int status = notify_register_dispatch("com.apple.springboard.hasBlankedScreen",
                                      &notifyToken,
                                      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");
}
Run Code Online (Sandbox Code Playgroud)

并且您需要保留一个ivar或其他持久变量来存储通知令牌(不要只是在注册的方法中将其作为局部变量!)

int notifyToken;
Run Code Online (Sandbox Code Playgroud)

你应该看到state通过notify_get_state()在0和1之间切换的变量,它可以让你区分屏幕开启和关闭事件.

虽然此文档非常陈旧,但它会列出哪些通知事件具有可通过其检索的关联状态notify_get_state().

警告: 请参阅此相关问题以了解最后一种技术的一些并发症