当前位置: 动力学知识库 > 问答 > 编程问答 >

gps - Is there a way to check if the iOS device is locked/unlocked?

问题描述:

I have used GPS location updates in my application. I want to detect if the iOS device is in sleep mode so that I can turn off the GPS location updates and optimize the battery use. I have already tried pausesLocationupdates in iOS 6, but it does not work as desired.

I want to turn off the GPS location updates as soon as the device goes to sleep mode.

I want to detect the lock/unlock event in the device.

Is there any way to achieve this functionality ?

so far I got the darwin notifications as given below

-(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);

}

I am able to get the darwin notifications when device is locked/unlocked, but the real problem is how identify between if the notification has come from locking or the unlocking of the device. Console logs are:

 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

Any private API would also suffice.

Thanks in advance.

网友答案:

I solved it like this:

//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);
}

Note: the "com.apple.springboard.lockcomplete" notification will always come after the "com.apple.springboard.lockstate" notification

Update

The order of the two notifications can no longer be relied upon, as of recent versions of iOS

网友答案:

/* Register app for detecting lock state */

 -(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];

  });

 }
网友答案:

Here's a better solution

#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;
    }
}
网友答案:

Jimmy provided a great solution but it's safer to pass in (__bridge const void *)(self) as an observer.

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

This allows you to properly remove the observer.

分享给朋友:
您可能感兴趣的文章:
随机阅读: