有没有办法检查iOS设备是否locking/解锁?

我在我的应用程序中使用了GPS位置更新。 我想检测iOS设备是否处于睡眠模式,以便closuresGPS位置更新并优化电池使用。 我已经尝试在iOS 6暂停位置更新,但它不能按需要工作。 一旦设备进入睡眠模式,我想closuresGPS位置更新。 我想检测设备中的locking/解锁事件。

有什么办法可以实现这个function吗?

到目前为止,我得到了下面给出的达尔文通知

-(void)registerForall { //Screen lock notifications CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.iokit.hid.displayStatus"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.lockstate"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.hasBlankedScreen"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.lockcomplete"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); } //call back static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { NSLog(@"IN Display status changed"); NSLog(@"Darwin notification NAME = %@",name); } 

当设备被locking/解锁时,我能够获得达尔文通知,但真正的问题是如果通知来自locking或设备的解锁,如何识别。 控制台日志是:

  LockDetectDemo[2086] <Warning>: IN Display status changed LockDetectDemo[2086] <Warning>: Darwin notification NAME = com.apple.springboard.lockcomplete LockDetectDemo[2086] <Warning>: IN Display status changed LockDetectDemo[2086] <Warning>: Darwin notification NAME = com.apple.springboard.lockstate LockDetectDemo[2086] <Warning>: IN Display status changed LockDetectDemo[2086] <Warning>: Darwin notification NAME = com.apple.springboard.hasBlankedScreen LockDetectDemo[2086] <Warning>: IN Display status changed LockDetectDemo[2086] <Warning>: Darwin notification NAME = com.apple.iokit.hid.displayStatus 

任何私人API也足够了。 提前致谢。

我解决了这个问题:

 //call back static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { // the "com.apple.springboard.lockcomplete" notification will always come after the "com.apple.springboard.lockstate" notification CFStringRef nameCFString = (CFStringRef)name; NSString *lockState = (NSString*)nameCFString; NSLog(@"Darwin notification NAME = %@",name); if([lockState isEqualToString:@"com.apple.springboard.lockcomplete"]) { NSLog(@"DEVICE LOCKED"); //Logic to disable the GPS } else { NSLog(@"LOCK STATUS CHANGED"); //Logic to enable the GPS } } -(void)registerforDeviceLockNotif { //Screen lock notifications CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.lockcomplete"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center NULL, // observer displayStatusChanged, // callback CFSTR("com.apple.springboard.lockstate"), // event name NULL, // object CFNotificationSuspensionBehaviorDeliverImmediately); } 

注意:“ com.apple.springboard.lockcomplete ”通知将始终在“com.apple.springboard.lockstate”通知之后

更新

截至最近的iOS版本,不能再依赖这两个通知的顺序

/ *注册应用程序检测locking状态* /

  -(void)registerAppforDetectLockState { int notify_token; notify_register_dispatch("com.apple.springboard.lockstate", &notify_token,dispatch_get_main_queue(), ^(int token) { uint64_t state = UINT64_MAX; notify_get_state(token, &state); if(state == 0) { NSLog(@"unlock device"); } else { NSLog(@"lock device"); } NSLog(@"com.apple.springboard.lockstate = %llu", state); UILocalNotification *notification = [[UILocalNotification alloc]init]; notification.repeatInterval = NSDayCalendarUnit; [notification setAlertBody:@"Hello world!! I come becoz you lock/unlock your device :)"]; notification.alertAction = @"View"; notification.alertAction = @"Yes"; [notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:1]]; notification.soundName = UILocalNotificationDefaultSoundName; [notification setTimeZone:[NSTimeZone defaultTimeZone]]; [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; }); } 

这是一个更好的解决scheme

 #import <notify.h> #define kNotificationNameDidChangeDisplayStatus @"com.apple.iokit.hid.displayStatus" @interface YourClass () { int _notifyTokenForDidChangeDisplayStatus; } @property (nonatomic, assign, getter = isDisplayOn) BOOL displayOn; @property (nonatomic, assign, getter = isRegisteredForDarwinNotifications) BOOL registeredForDarwinNotifications; @end - (void)registerForSomeNotifications { // // Display notifications // __weak YourClass *weakSelf = self; uint32_t result = notify_register_dispatch(kNotificationNameDidChangeDisplayStatus.UTF8String, &_notifyTokenForDidChangeDisplayStatus, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0l), ^(int info) { __strong YourClass *strongSelf = weakSelf; if (strongSelf) { uint64_t state; notify_get_state(_notifyTokenForDidChangeDisplayStatus, &state); strongSelf.displayOn = (BOOL)state; } }); if (result != NOTIFY_STATUS_OK) { self.registeredForDarwinNotifications = NO; return; } self.registeredForDarwinNotifications = YES; } - (void)unregisterFromSomeNotifications { // // Display notifications // uint32_t result = notify_cancel(_notifyTokenForDidChangeDisplayStatus); if (result == NOTIFY_STATUS_OK) { self.registeredForDarwinNotifications = NO; } } 

应用程序现在不允许聆听设备locking通知!

我收到了这个:

亲爱的开发者

我们发现您最近提交的“xxxx”有一个或多个问题。 要处理您的提交,必须纠正以下问题:

不受支持的操作 – 应用程序不允许收听设备locking通知。

一旦这些问题得到纠正,请使用Xcode或Application Loader将新的二进制file upload到iTunes Connect。 在iTunes Connect上的我的应用程序中的应用程序“详情”页面上select新的二进制文件,然后单击提交以供查看。

问候,

App Store团队
2017年4月26日10:56

Jimmy提供了一个很好的解决scheme,但作为观察者传递(__bridge const void *)(self)更安全。

 CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), displayStatusChanged, CFSTR("com.apple.springboard.lockcomplete"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); 

这使您可以正确删除观察者。