Поведение при значительном изменении местоположения API при прекращении / приостановке?

108

Это раздел документации CLLocationManager, описывающий поведение приложения с помощью startMonitoringSignificantLocationChanges :

Если вы запускаете эту службу, а ваше приложение впоследствии прекращает работу, система автоматически перезапускает приложение в фоновом режиме при появлении нового события. В таком случае словарь параметров, переданный приложению: didFinishLaunchingWithOptions: метод делегата вашего приложения, содержит ключ UIApplicationLaunchOptionsLocationKey, чтобы указать, что ваше приложение было запущено из-за события местоположения. После перезапуска вы все равно должны настроить объект диспетчера местоположения и вызвать этот метод, чтобы продолжить получение событий местоположения. Когда вы перезапускаете службы определения местоположения, текущее событие немедленно доставляется вашему делегату. Кроме того, свойство местоположения вашего объекта диспетчера местоположения заполняется самым последним объектом местоположения даже до того, как вы запустите службы определения местоположения.

Итак, я понимаю, что если ваше приложение завершается (и я предполагаю, что если вы не вызываете stopMonitoringSignificantLocationChanges из applicationWillTerminate ), вы проснетесь с параметром UIApplicationLaunchOptionsLocationKey для application: didFinishLaunchingWithOptions . На этом этапе вы создаете свой CLLocationManager , вызываете startMonitoringSignificantLocationChanges и выполняете фоновую обработку местоположения в течение ограниченного времени . Так что меня это устраивает.

В предыдущем абзаце говорится только о том, что происходит, когда приложение закрывается, но не предлагается, что вы делаете, когда приложение приостановлено. В документации для didFinishLaunchingWithOptions говорится:

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

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

Однако в абзаце о службе значительных изменений в Руководстве по программированию с учетом местоположения говорится следующее:

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

Это говорит о том, что вы просыпаетесь с данными о местоположении, если ваше приложение было приостановлено, но не упоминает, как вы проснулись:

  • Получает ли UIApplicationDelegate обратный вызов, сообщающий мне, что я выхожу из приостановленного состояния в фоновое состояние?
  • Начинает ли менеджер местоположения (который был высушен замораживанием, когда приложение было приостановлено) получать обратные вызовы locationManager: didUpdateToLocation: fromLocation ?
  • Нужно ли мне просто реализовать код в моем сообщении didUpdateToLocation, который проверяет состояние приложения и выполняет минимальную обработку в фоновом режиме?

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

RedBlueThing
источник

Ответы:

80

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

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

[UIApplication sharedApplication].applicationState == UIApplicationStateBackground

Я пришел к такому выводу с помощью программы определения местоположения, которую вы можете скачать и опробовать. Это довольно простое приложение, которое позволяет вам включать значительные изменения и API изменения GPS через пользовательский интерфейс и регистрировать все ответы, которые вы получите.

NB Пункт шесть в предыдущем ответе неверен. Мораторий высушенные подвешенные приложения действительно получают CLLocationManagerDelegate обратных вызовов , когда они проснулись от взвешенного состояния.

RedBlueThing
источник
1
Вычеркнул №6 в моем ответе, чтобы не путать людей.
Аарон
По иронии судьбы, я почувствовал такое же замешательство, когда готовился к значительному изменению. Я все еще сомневаюсь, что произойдет, если приложение будет закрыто. не происходит ли обратного вызова UIApplicationDelegate? это правильный способ запустить приложение. если менеджер местоположения еще не запущен, как он может получать уведомления в фоновом режиме? (время для дополнительных исследований и разработок)
даршансонд
Большое спасибо за образец приложения, оно мне очень пригодилось. У меня вопрос: что, если бы я использовал в фоновом режиме стандартную службу определения местоположения, а не важную, будет ли приложение перезапущено после завершения работы в этом случае? Я задал этот вопрос здесь подробно, был бы рад, если бы вы могли меня облегчить:] stackoverflow.com/questions/12239967/…
aslisabanci
2
Не работает на ios7 stackoverflow.com/questions/18946881/…
Игорь
Вы знаете, сколько времени потребовалось для прекращения работы вашего приложения? А затем получить вместо этого обратный вызов appDelegate? (Это примерно 30 минут? 2 часа? 5 часов?) Я спрашиваю об этом потому, что я настроил регион для мониторинга. Много раз пытался увидеть, как запускается мое приложение, но только однажды мне удалось его перезапустить. В других случаях didExitRegionобратный вызов, но я не мог startLocationUpdatesоттуда, потому что это не было через запуск приложения ...
Дорогая,
25

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

  1. Ваше приложение запускается в первый раз, вы регистрируетесь на startMonitoringSignificantLocationChanges и предоставляете функцию обратного вызова. Пока ваше приложение работает, оно будет вызывать этот обратный вызов всякий раз, когда получает существенное изменение.
  2. Если ваше приложение переведено в фоновый режим, UIApplication получит applicationWillResignActive , а затем applicationDidEnterBackground .
  3. Если ваше приложение будет убито, когда оно приостановлено в фоновом режиме, вы не получите уведомления; однако, если ваше приложение будет убито во время его работы (насколько мне известно, на переднем плане или в фоновом режиме), вы получите момент с applicationWillTerminate . Вы не можете запросить дополнительное фоновое время из этой функции.
  4. Несмотря на то, что ОС была убита в фоновом режиме, она перезапустит ваше приложение. Если ваше приложение просто запускается ОС для изменения, вы получите вызов приложения didFinishLaunchingWithOptions :

    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey])

    поможет вам определить, вернулись ли вы после смены фонового местоположения.

  5. Если вместо этого вы в настоящее время работали в фоновом режиме, а ваше приложение вручную перезапускается пользователем, вы получите applicationWillEnterForeground, за которым следует applicationDidBecomeActive .
  6. Независимо от того, как это произошло, когда ваше приложение перезапускается (если оно все еще не работало в фоновом режиме в результате фоновой задачи и указанная задача начала отслеживать изменения), вам нужно снова явно сообщить ему startMonitoringSignificantLocationChanges, потому что обратный вызов не дольше прикрепляется после «сублимационной сушки». И да, вам просто нужно реализовать код в didUpdateToLocation после того, как вы повторно подключили какой-либо обработчик местоположения после выхода из приостановленного состояния.

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

О, и если по какой-то удаче вы выпустите приложение, которое делает то, что я хочу, чтобы я делал, я могу плакать :)

Удачи!

Аарон
источник
1
@Tegeril +1 Спасибо за ответ. Я начал слышать сверчков на этом. :) Я удивлен, что приложения, запущенные после приостановки, требуют повторного вызова startMonitoringSignificantLocationChanges. У вас есть ссылка на документ, где это описано? Насколько я понимаю, загрузка из приостановленного состояния создаст экземпляры всех ваших объектов, как они были, когда приложение было приостановлено. Поэтому я ожидаю, что запрос на существенное изменение вступит в силу.
RedBlueThing
Вы могли об этом говорить? «После перезапуска вы все равно должны настроить объект диспетчера местоположения и вызвать этот метод, чтобы продолжать получать события местоположения». Но я думаю, что это относится к случаю, когда приложение запускается из завершенного состояния (по событию местоположения). По сути, это корень моего вопроса: «Что происходит с приостановленным делом?».
RedBlueThing
Морган Грейнджер на форумах разработчиков предложил следующее: «Вам нужно создать CLLocationManager, установить делегата и вызвать startMonitoringSignificantLocationChanges при запуске вашего приложения, иначе Core Location будет некуда доставлять обновления». в контексте перезапуска приложения независимо от того, в каком состоянии он находится. От "приложение было перезапущено после startMonitoringSignificantLocationChanges и что теперь?"
Аарон
Я согласен с тем, что это все еще может быть расплывчатым даже в контексте того сообщения на форуме (плакат обсуждал пробуждение из фона, но Морган использовал более общий перезапуск приложения). Я все еще думаю, что вам нужно снова вызвать мониторинг при перезапуске вашего приложения, если вы хотите работать с функцией значительных изменений. Если вы хотите вместо этого запустить фоновую задачу и обновить стандартную службу определения местоположения и функции GPS, это альтернативный вариант. Я не верю, что вам нужно перерегистрироваться при каждом запуске со значительными изменениями, чтобы запускаться снова.
Аарон
1
Я рад, что из этого вышло что-то определенное, должно помочь мне в будущем :)
Аарон
1

Если приложение выходит из приостановленного состояния в результате изменения местоположения, приложение запускается в фоновом режиме.

Все объекты будут активны, и вы получите обновление местоположения в существующем делегате.

Anshu
источник