Есть ли способ проверить, заблокировано/разблокировано устройство iOS?
Я использовал обновления местоположения GPS в своем приложении. Я хочу определить, находится ли устройство iOS в спящем режиме, чтобы я мог отключить обновления местоположения GPS и оптимизировать использование батареи. Я уже пробовал pausesLocationupdates в iOS 6, но он не работает по желанию.
Я хочу отключить обновления местоположения GPS, как только устройство перейдет в спящий режим.
Я хочу обнаружить событие блокировки/разблокировки на устройстве.
Есть ли способ достичь этой функциональности?
До сих пор я получал уведомления darwin, приведенные ниже
-(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);
}
Я могу получить уведомления darwin, когда устройство заблокировано/разблокировано, но реальная проблема заключается в том, как определить, произошло ли уведомление из-за блокировки или разблокировки устройства. Журналы консоли:
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 также будет достаточным.
Спасибо заранее.
Ответы
Ответ 1
Я решил это так:
//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", уведомление
Update
порядок двух уведомлений больше не зависит от последних версий iOS
Ответ 2
/* Зарегистрировать приложение для обнаружения состояния блокировки */
-(void)registerAppforDetectLockState {
int notify_token;
notify_register_dispatch("com.apple.springboard.lockstate", ¬ify_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];
});
}
Ответ 3
Здесь лучшее решение
#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;
}
}
Ответ 4
Приложениям не разрешено прослушивать уведомления о блокировке устройства прямо сейчас.
Я получил следующее:
Уважаемый разработчик,
Мы обнаружили одну или несколько проблем с вашим недавним представлением для "xxxx". Чтобы обработать ваше сообщение, необходимо устранить следующие проблемы:
Неподдерживаемая операция. Приложениям запрещается прослушивать уведомления о блокировке устройства.
Как только эти проблемы были исправлены, используйте Xcode или Application Loader для загрузки нового бинарного файла в iTunes Connect. Выберите новый бинарный файл на странице "Сведения о приложениях" в "Мои приложения" в iTunes Connect и нажмите "Отправить для просмотра".
Привет,
Команда App Store
26 апреля 2017 в 10:56
Ответ 5
Джимми предоставил отличное решение, но безопаснее проходить в (__bridge const void *)(self)
в качестве наблюдателя.
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
(__bridge const void *)(self),
displayStatusChanged,
CFSTR("com.apple.springboard.lockcomplete"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
Это позволяет правильно удалить наблюдателя.