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

Можно ли различать блокировку устройства и отправку приложения в фоновый режим?

У меня есть приложение, которое нужно что-то сделать, когда его отправили на задний план, используя кнопку "Домой" и что-то еще, когда устройство заблокировано с помощью верхней аппаратной кнопки. Стандартным способом решения этих требований являются уведомления и методы делегирования, отправленные 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 теперь отправляются даже тогда, когда (un) блокирует устройство, что делает невозможным рассказать между блокировкой и фоном. Является ли это изменение документированным где-то? Это регресс? Вы знаете другой способ отличить два случая?

4b9b3361

Ответ 1

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 и прослушивать уведомление darwin (помечено: com.apple.springboard.lockcomplete). Здесь вы можете найти репозиторий github с примером проекта: https://github.com/binarydev/ios-home-vs-lock-button

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

Ответ 2

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

Однако вы можете проверить, есть ли 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:

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


В соответствии с iOS 4.3 для iOS 5.0 API 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

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

Эта записка будет [self destruct]; составляет 5 минут (поэтому Apple не узнает).

Ответ 4

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

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

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

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

Ответ 5

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