Подтвердить что ты не робот

Блокировка разблокировки событий iphone

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

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

4b9b3361

Ответ 1

Вы можете использовать уведомления Darwin, чтобы прослушивать события. Из моего тестирования на jailbroken 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(). Вы получите другое значение для блокировки и разблокировки как описано здесь.

Ответ 2

Круглый ответ:

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

Однако, похоже, 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;
}

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

Ответ 3

Существует более красивый способ рассказать о переключении задач и инициировании блокировки экрана 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: происходит из-за активного состояния > неактивного состояния (как при блокировке экрана), но мы щедро позволяем системе доказать обратное в течение таймаута (в этом случае a одиночный цикл runloop), задерживая вызов screenLockActivated. В случае блокировки экрана система завершает текущий цикл runloop, не касаясь других методов делегата. Если, однако, это активный переход > состояние фона, он также вызывает applicationDidEnterBackground: до конца цикла, что позволяет нам просто отменить ранее запланированный запрос оттуда, тем самым предотвращая его вызов, когда он не предполагается к.

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

Ответ 4

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


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

Включив разрешение " Защита данных", ваше приложение может подписаться на applicationProtectedDataWillBecomeUnavailable: и applicationProtectedDataDidBecomeAvailable: уведомления, с высокой вероятностью определяющие, когда устройство, использующее аутентификацию с помощью пароля или TouchID, заблокировано/разблокировано. Чтобы определить, использует ли устройство пароль / LAContext можно запросить 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 с) задержку между двумя событиями:

15:22:59.236 willResignActive
15:22:59.267 didEnterBackground
15:22:59.267 difference: 0.031404

Ответ 5

Просто импортируйте #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];

    });
}

Ответ 6

в 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 для получения текущего состояния в любом месте, это полезно, когда вы хотите знать состояние и состояние экрана не меняются.

Ответ 7

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

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

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

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

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

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

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

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