Можно ли отличить блокировку устройства от отправки приложения в фоновый режим? - PullRequest
38 голосов
/ 13 октября 2011

У меня есть приложение, которое должно что-то делать, когда оно отправляется в фоновый режим с помощью кнопки «Домой», и что-то еще, когда устройство заблокировано с помощью верхней аппаратной кнопки.Стандартным способом решения этих требований являются уведомления и методы делегирования, отправляемые UIApplication.На iOS 4 они выглядят так:

// Pressing the home button
Will resign active.
Did enter background.
// Tapping app icon on Springboard
Will enter foreground.
Did become active.

// Pressing the lock button
Will resign active.
// Unlocking the device
Did become active.

Другими словами, довольно легко отличить блокировку от фонового.На iOS 5 изменилось поведение:

// Pressing the home button
Will resign active.
Did enter background.
// Tapping app icon on Springboard
Will enter foreground.
Did become active.

// Pressing the lock button
Will resign active.
Did enter background.
// Unlocking the device
Will enter foreground.
Did become active.

Обратите внимание, что уведомления didEnterBackground и willEnterForeground теперь отправляются даже при (не) блокировке устройства, что делает невозможным выбор между блокировкой и фоновым режимом.Это изменение где-то задокументировано?Это регрессия?Вы знаете другой способ различить два случая?

Ответы [ 5 ]

28 голосов
/ 30 января 2012

iOS 6

В моем предварительном тестировании с помощью симулятора проверка состояния приложения с помощью

[[UIApplication sharedApplication] applicationState]

в любом из

- (void)applicationWillEnterForeground:(UIApplication *)application

- (void)applicationDidEnterBackground:(UIApplication *)application

позволяет различатьпозвоните, чтобы заблокировать устройство и просто переключиться обратно на домашний экран.Экран блокировки вернет 1 (UIApplicationStateInactive), в то время как нажатие кнопки «Домой» будет зарегистрировано как 2 (UIApplicationStateBackground).

Кажется согласованным и должно работать на устройстве iOS так же надежно, как в симуляторе.

iOS 7

Метод iOS 6 больше не работает в iOS 7. Чтобы сделать это сейчас, вы должны использовать CFNotificationCenter и прослушивать уведомление Дарвина (помечено: com.apple.springboard.lockcomplete).Вы можете найти репозиторий github с примером проекта здесь: https://github.com/binarydev/ios-home-vs-lock-button

Кредит на исправление iOS 7 выходит на wqq

7 голосов
/ 17 октября 2011

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

Одна вещь, которую вы можете проверить, однако, это UIApplicationState при переходе от переднего плана к фону.Блокировка устройства даст UIApplicationStateInactive, а перемещение приложения на задний план - UIApplicationStateBackground.Но, поскольку это поведение официально не задокументировано, оно может измениться в будущем.

Базовый пример:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    UIApplicationState state = [[UIApplication sharedApplication] applicationState];
    NSLog(@"Device state: %@", state);
    switch (state) {
        case UIApplicationStateActive:
            /* ... */
            break;
        case UIApplicationStateInactive:
            /* Device was/is locked  */
            break;
        case UIApplicationStateBackground:
            /* User pressed home button or opened another App (from an alert/email/etc) */
            break;
    }
}

UIApplicationState - рабочие состояния приложения

typedef enum {
    UIApplicationStateActive,   
    UIApplicationStateInactive,
    UIApplicationStateBackground
}

UIApplicationState

Константы UIApplicationStateActive - Приложение работает на переднем плане и в данный момент получает события.Доступно в iOS 4.0 и более поздних версиях.

UIApplicationStateInactive - Приложение работает на переднем плане, но не получает события.Это может произойти в результате прерывания или из-за перехода приложения в фоновый режим или из него.

UIApplicationStateBackground - Приложение работает в фоновом режиме.


Согласно Справочнику по протоколу UIApplicationDelegate :

applicationWillResignActive:
didEnterBackground:
// ...
willEnterForeground:
applicationDidBecomeActive:

- единственные методы, которые когда-либо вызывались в обеих ситуациях.


Согласно API от iOS 4.3 до iOS 5.0 Diff , это ЕДИНСТВЕННЫЕ изменения, касающиеся UIApplication или UIApplicationDelegate, поэтому я не смог найти, где они документировали какие-либо из этих изменений уведомлений:

UIApplication.h
Added -[UIApplication setNewsstandIconImage:]
Added UIApplication.userInterfaceLayoutDirection
Added UIApplicationDelegate.window
Added UIApplication(UINewsstand)
Added UIApplicationLaunchOptionsNewsstandDownloadsKey
Added UIRemoteNotificationTypeNewsstandContentAvailability
Added UIUserInterfaceLayoutDirection
Added UIUserInterfaceLayoutDirectionLeftToRight
Added UIUserInterfaceLayoutDirectionRightToLeft
3 голосов
/ 22 августа 2012

Это скорее обходной путь / хак, но, по моему опыту, это очень надежно. Когда устройство заблокировано экраном (а не просто нажатием кнопки домой, если это слово :)) - bound сетевые (UDP) сокеты повреждены. Я использовал GCDAsyncUDPSocket (ранее также был AsyncUDPSocket), и они оба надежно генерировали ошибку сети / обрыва канала при выключении устройства. В любом случае, в любом случае мне нужен сокет UDP, для других приложений это может быть немного вонючим, однако просто связывание / прослушивание сокета UDP без каких-либо действий не так уж страшно, если вам действительно нужно провести различие.

Эта записка [самоуничтожится]; 5 минут (поэтому Apple не узнает).

2 голосов
/ 01 августа 2013

Вот что говорится в руководстве Apple по программированию для iOS:

Нажатие кнопки «Режим сна / Пробуждение» - это еще один тип прерывания, вызывает временное отключение вашего приложения. Когда пользователь нажимает эта кнопка, система отключает сенсорные события, перемещает приложение в фон, но задает значение свойства applicationState приложения в UIApplicationStateInactive (в отличие от UIApplicationStateBackground) и, наконец, блокирует экран.

http://developer.apple.com/library/ios/#DOCUMENTATION/iPhone/conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

Итак, вы должны проверить UIApplication 'applicationState свойство в applicationDidEnterBackground:. Если это UIApplicationStateBackground, пользователь нажал кнопку «Домой». Но если это UIApplicationStateInactive, пользователь заблокировал устройство.

1 голос
/ 18 октября 2011

На форуме разработчиков Apple существует тема (только зарегистрированные разработчики, извините). Суть в том, что новое поведение - это дизайн. Есть запросы на новую функцию API, чтобы различать два варианта использования, но пока ничего не работает.

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