Блокировка разблокировать события iphone - PullRequest
34 голосов
/ 01 апреля 2009

Как я могу обнаружить события блокировки / разблокировки на iPhone? Предполагая, что это возможно только для взломанных устройств, можете ли вы указать мне правильный API?

Под событиями блокировки я имею в виду отображение или скрытие экрана блокировки (для разблокировки которого может потребоваться пароль).

Ответы [ 10 ]

21 голосов
/ 08 января 2013

Вы можете использовать Дарвинские уведомления , чтобы прослушивать события. Из моего тестирования на взломанном iOS 5.0.1 iPhone 4 я думаю, что одним из этих событий может быть то, что вам нужно:

com.apple.springboard.lockstate
com.apple.springboard.lockcomplete

Примечание: в соответствии с комментариями автора к аналогичному вопросу, на который я ответил здесь , это также должно работать на не взломанном телефоне.

Чтобы использовать это, зарегистрируйтесь для участия в таком событии (это относится только к первому событию, указанному выше, но вы также можете добавить наблюдателя и для lockcomplete):

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                (void*)self, // observer (can be NULL)
                                lockStateChanged, // callback
                                CFSTR("com.apple.springboard.lockstate"), // event name
                                NULL, // object
                                CFNotificationSuspensionBehaviorDeliverImmediately);

, где lockStateChanged - обратный вызов вашего события:

static void lockStateChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
    NSLog(@"event received!");
    if (observer != NULL) {
        MyClass *this = (MyClass*)observer;
    }

    // you might try inspecting the `userInfo` dictionary, to see 
    //  if it contains any useful info
    if (userInfo != nil) {
        CFShow(userInfo);
    }
}

Событие lockstate наступает, когда устройство заблокировано и разблокировано, но событие lockcomplete запускается только при блокировке устройства. Другой способ определить, относится ли это событие к событию блокировки или разблокировки, - использовать notify_get_state(). Вы получите другое значение для блокировки против разблокировки, , как описано здесь .

14 голосов
/ 20 сентября 2011

Об ответе:

Приложение будет подавать в отставку, активным вызывается во всех сценариях ... и из всех моих тестов, даже если ваше приложение не дремлет, пока оно находится в фоновом режиме, нет способов определить, заблокирован ли экран (скорость процессора не отображается , Скорость шины остаётся неизменной, число_члена / число не изменяется) ...

Однако, похоже, Apple отключает акселерометр, когда устройство заблокировано ... Включить акселерометр iPhone, когда экран заблокирован (протестированное iOS4.2 на iPhone 4 имеет такое поведение)

Таким образом ...

В вашей заявке делегат:

- (void)applicationWillResignActive:(UIApplication *)application
{
    NSLog(@"STATUS - Application will Resign Active");
    // Start checking the accelerometer (while we are in the background)
    [[UIAccelerometer sharedAccelerometer] setDelegate:self];
    [[UIAccelerometer sharedAccelerometer] setUpdateInterval:1]; // Ping every second
    _notActiveTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(deviceDidLock) userInfo:nil repeats:NO]; // 2 seconds for wiggle

}
//Deprecated in iOS5
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
    NSLog(@"STATUS - Update from accelerometer");
    [_notActiveTimer invalidate];
    _notActiveTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(deviceDidLock) userInfo:nil repeats:NO];
}

- (void)deviceDidLock
{
    NSLog(@"STATUS - Device locked!");
    [[UIAccelerometer sharedAccelerometer] setDelegate:nil];
    _notActiveTimer = nil;
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    NSLog(@"STATUS - Application did become active");
    [[UIAccelerometer sharedAccelerometer] setDelegate:nil];
    [_notActiveTimer invalidate];
    _notActiveTimer = nil;
}

Я знаю ... Это что-то вроде хака, но до сих пор это работало для меня как шарм. Пожалуйста, обновите, если вы видите какие-либо проблемы, которые мешают этому работать.

7 голосов
/ 23 января 2012

Существует более симпатичный способ отличить переключение задач от обратных вызовов, вызванных блокировкой экрана applicationWillResignActive:, которые даже не содержат недокументированных функций, таких как состояние акселерометра.

Когда приложение перемещается в фоновый режим, делегату приложения сначала отправляется applicationWillResignActive:, а затем applicationDidEnterBackground:. Когда приложение прерывается нажатием кнопки блокировки или входящим телефонным звонком, последний метод не вызывается. Мы можем использовать эту информацию, чтобы различать два сценария.

Скажем, вы хотите, чтобы вам перезвонили в методе screenLockActivated, если экран заблокирован. Вот магия:

- (void)applicationWillResignActive:(UIApplication*)aApplication
{
    [self performSelector:@selector(screenLockActivated)
               withObject:nil
               afterDelay:0];
}

- (void)applicationDidEnterBackground:(UIApplication*)aApplication
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
}

- (void)screenLockActivated
{
    NSLog(@"yaay");
}

Пояснение:

По умолчанию мы предполагаем, что каждый вызов applicationWillResignActive: происходит из-за активного перехода в неактивное состояние (как при блокировке экрана), но мы щедро позволяем системе доказать обратное в течение тайм-аута (в данном случае, один цикл выполнения), задерживая вызов на screenLockActivated. В случае, если экран заблокирован, система завершает текущий цикл цикла выполнения, не затрагивая другие методы делегата. Однако, если это активный переход в фоновое состояние, он также вызывает applicationDidEnterBackground: до конца цикла, что позволяет нам просто отменить ранее запланированный запрос оттуда, тем самым предотвращая его вызов, когда он не предполагается к.

Наслаждайтесь!

5 голосов
/ 08 мая 2017

На момент написания статьи существует два достаточно надежных способа обнаружения блокировки устройства:


Защита данных

Включив право Защита данных , ваше приложение может подписаться на уведомления applicationProtectedDataWillBecomeUnavailable: и applicationProtectedDataDidBecomeAvailable:, чтобы с высокой вероятностью определить, когда устройство, которое использует пароль / TouchID. Аутентификация заблокирована / разблокирована. Чтобы определить, использует ли устройство код доступа / TouchID, можно запросить LAContext.

Предостережения : Этот метод основан на том, что «защищенные данные становятся недоступными», совпадающими с заблокированным телефоном. Когда телефон использует TouchID и нажата кнопка «Режим сна» / «Блокировка», телефон блокируется, защищенные данные становятся недоступными, и для его разблокировки немедленно потребуется пароль. Это означает, что защищенные данные становятся недоступными по существу указывает на то, что телефон был заблокирован. Это не обязательно так, когда кто-то использует просто код доступа , поскольку он может установить время «требуется пароль» в любом месте от немедленно до чего-то вроде 4 часа . В этом случае телефон сообщит о возможности обработки защищенных данных, но блокировка телефона не приведет к тому, что защищенные данные станут недоступными в течение некоторого времени.


Время жизненного цикла

Если ваше приложение находится на переднем плане, будет заметное изменение разницы во времени между двумя событиями жизненного цикла UIApplicationWillResignActiveNotification и UIApplicationDidEnterBackgroundNotification в зависимости от того, что их запускает.

(это было протестировано в iOS 10 и может измениться в будущих выпусках)

Нажатие кнопки «домой» приводит к значительной задержке между ними (даже если включена настройка «Ограниченное движение»):

15:23:42.517 willResignActive
15:23:43.182 didEnterBackground
15:23:43.184 difference: 0.666346

Блокировка устройства при открытом приложении создает более тривиальную (<~ 0,2 с) задержку между двумя событиями: </p>

15:22:59.236 willResignActive
15:22:59.267 didEnterBackground
15:22:59.267 difference: 0.031404
5 голосов
/ 19 мая 2015

в iOS 8 вы блокируете экран или нажимаете кнопку «Домой», все это заставляет приложение работать в фоновом режиме, но вы не знаете, какой оператор приведет к этому. Мое решение то же самое с Nits007ak, используйте notify_register_dispatch, чтобы получить состояние.

#import <notify.h>
        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");
                                 }
                             }
                             );

Пока приложение работает, на переднем плане или в фоновом режиме. не приостановить, вы можете получить это событие.

И вы можете использовать notify_token в качестве параметра notify_get_state, чтобы получить текущее состояние в любом месте, это полезно, когда вы хотите знать состояние и состояние экрана не меняется.

4 голосов
/ 24 сентября 2014

Просто импортируйте #import notify.h перед использованием этого кода. наслаждаться !!

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

    });
}
3 голосов
/ 03 июля 2014

Если установлен пароль, вы можете использовать это событие в AppDelegate

-(void)applicationProtectedDataWillBecomeUnavailable:(UIApplication *)application
{
}

- (void)applicationProtectedDataDidBecomeAvailable:(UIApplication *)application
{
}
1 голос
/ 28 апреля 2016

Из большого количества проб и ошибок обнаруженный мониторинг пустого экрана, блокировка завершена и события состояния блокировки дают постоянный индикатор блокировки экрана. Вам нужно будет следить за переходом между состояниями.

// call back
void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
    // notification comes in order of
    // "com.apple.springboard.hasBlankedScreen" notification
    // "com.apple.springboard.lockcomplete" notification only if locked
    // "com.apple.springboard.lockstate" notification

    AppDelegate *appDelegate = CFBridgingRelease(observer);

    NSString *eventName = (__bridge NSString*)name;
    NSLog(@"Darwin notification NAME = %@",name);

    if([eventName isEqualToString:@"com.apple.springboard.hasBlankedScreen"])
    {
        NSLog(@"SCREEN BLANK");

        appDelegate.bDeviceLocked = false; // clear
    }
    else if([eventName isEqualToString:@"com.apple.springboard.lockcomplete"])
    {
        NSLog(@"DEVICE LOCK");

        appDelegate.bDeviceLocked = true; // set
    }
    else if([eventName isEqualToString:@"com.apple.springboard.lockstate"])
    {
        NSLog(@"LOCK STATUS CHANGE");

        if(appDelegate.bDeviceLocked) // if a lock, is set
        {
            NSLog(@"DEVICE IS LOCKED");
        }
        else
        {
            NSLog(@"DEVICE IS UNLOCKED");
        }
    }
}

-(void)registerforDeviceLockNotif
{
    // screen and lock notifications
    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                    CFBridgingRetain(self), // observer
                                    displayStatusChanged, // callback
                                    CFSTR("com.apple.springboard.hasBlankedScreen"), // event name
                                    NULL, // object
                                    CFNotificationSuspensionBehaviorDeliverImmediately);

    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                    CFBridgingRetain(self), // observer
                                    displayStatusChanged, // callback
                                    CFSTR("com.apple.springboard.lockcomplete"), // event name
                                    NULL, // object
                                    CFNotificationSuspensionBehaviorDeliverImmediately);

    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                    CFBridgingRetain(self), // observer
                                    displayStatusChanged, // callback
                                    CFSTR("com.apple.springboard.lockstate"), // event name
                                    NULL, // object
                                    CFNotificationSuspensionBehaviorDeliverImmediately);
}

Чтобы индикаторы блокировки экрана работали в фоновом режиме, вам необходимо реализовать фоновую обработку, вызывающую следующее при запуске приложения.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.backgroundTaskIdentifier =
    [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
    }];

    [self registerforDeviceLockNotif];
}
1 голос
/ 05 мая 2011

Если ваше приложение работает, и пользователь блокирует устройство, ваш делегат приложения получит вызов «Приложение будет отставать в активном состоянии». Если ваше приложение было запущено, когда оно заблокировано, оно получит вызов «Приложение стало активным:», когда устройство разблокировано. Но вы получаете те же звонки на ваше приложение, если пользователь получает телефонный звонок, а затем решает игнорировать его. Насколько я знаю, вы не можете понять разницу.

И если ваше приложение не было запущено в любой из этих периодов, нет способа получить уведомление, так как ваше приложение не запущено.

0 голосов
/ 07 мая 2015

Самый простой способ получить события блокировки и разблокировки экрана - добавить наблюдателей событий с помощью NSNotificationCenter в ваш viewcontroller. Я добавил следующий наблюдатель в методе viewdidload. Вот что я сделал:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(applicationEnteredForeground:)
                                             name:UIApplicationWillEnterForegroundNotification
                                           object:nil];

Затем я добавил следующий селектор в viewcontroller. Этот селектор будет вызываться, когда экран разблокирован.

 - (void)applicationEnteredForeground:(NSNotification *)notification {
    NSLog(@"Application Entered Foreground");
    }

Если вы хотите обнаружить событие, когда экран заблокирован, вы можете заменить UIApplicationWillEnterForegroundNotification на UIApplicationDidEnterBackgroundNotification .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...