Базовая Фоновая обработка Bluetooth для приложений для iOS

Для приложений для iOS крайне важно знать, работает ли Ваше приложение на переднем плане или фоне. Приложение должно вести себя по-другому в фоновом режиме, чем на переднем плане, потому что системные ресурсы более ограничены на устройствах на iOS. Для полного обсуждения многозадачности на iOS посмотрите состояния Приложения и Многозадачность в Руководстве по программированию приложения для iOS.

По умолчанию, многие из общего Ядра, задачи Bluetooth — и на центральной и на периферийной стороне — отключены, в то время как Ваше приложение в фоновом режиме или в состоянии ожидания. Однако можно объявить, что приложение поддерживает Ядро фоновые режимы выполнения Bluetooth, чтобы позволить приложению быть разбуженным от состояния ожидания для обработки определенных связанных с Bluetooth событий. Даже если для Вашего приложения не нужен полный спектр поддержки фоновой обработки, это может все еще попросить быть предупрежденным системой, когда важные события имеют место.

Даже если Ваши поддержки приложений один или оба из Ядра фоновые режимы выполнения Bluetooth, это не может работать навсегда. В некоторый момент система, возможно, должна завершить Ваше приложение для высвобождения памяти для текущего приоритетного приложения — то, чтобы заставлять любые активные или незаконченные соединения быть потерянной, например. С iOS 7 Ядро поддержки Bluetooth, сохраняющие информацию состояния для центрального и периферийного менеджера, возражает и восстанавливающий то состояние во время запуска приложения. Можно использовать эту функцию для поддержки долгосрочных действий, включающих bluetooth-устройства.

Приложения только для переднего плана

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

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

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

Используйте в своих интересах периферийные опции соединения

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

Можно использовать в своих интересах эти предупреждения включением одной из следующих периферийных опций соединения при вызове connectPeripheral:options: метод CBCentralManager класс для соединения с удаленным периферийным устройством:

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

  • CBConnectPeripheralOptionNotifyOnDisconnectionKey— Включайте этот ключ, если Вы хотите, чтобы система вывела на экран предупреждение разъединения для данного периферийного устройства, если приложение приостановлено во время разъединения.

  • CBConnectPeripheralOptionNotifyOnNotificationKey— Включайте этот ключ, если Вы хотите, чтобы система вывела на экран предупреждение для всех уведомлений, полученных от данного периферийного устройства, если приложение приостановлено в то время.

Для получения дополнительной информации о периферийных опциях соединения, посмотрите Peripheral Connection Options константы, детализированные в Ссылке класса CBCentralManager.

Базовые фоновые режимы выполнения Bluetooth

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

Существует два Ядра фоновые режимы выполнения Bluetooth, которые приложение может объявить — один для приложений, реализовав центральную роль и другого для приложений, реализовав периферийную роль. Если Ваше приложение реализует обе роли, оно может объявить, что поддерживает оба фоновых режима выполнения. Ядро фоновые режимы выполнения Bluetooth объявляется путем добавления UIBackgroundModes ключ к Вашему Info.plist файл и установка значения ключа к массиву, содержащему одну из следующих строк:

Для получения информации о том, как сконфигурировать содержание Вашего Info.plist файл, посмотрите редактора Списка свойств Хелпа.

Центральный Bluetooth Фоновый Режим Выполнения

Когда приложение, реализующее центральную роль включает UIBackgroundModes ключ с bluetooth-central значение в Info.plist файл, Ядро платформа Bluetooth позволяет Вашему приложению работать в фоновом режиме для выполнения определенных связанных с Bluetooth задач. В то время как Ваше приложение в фоновом режиме, можно все еще обнаружить и соединиться с периферийными устройствами, и исследовать и взаимодействовать с периферийными данными. Кроме того, система будит Ваше приложение когда любой из CBCentralManagerDelegate или CBPeripheralDelegate методы делегата вызываются, позволяя Вашему приложению обработать важные центральные ролевые события, такой как тогда, когда соединение установлено или разъединено, когда периферийное устройство отправляет обновленные характеристические значения, и когда изменения состояния центрального менеджера.

Несмотря на то, что можно выполнить много связанных с Bluetooth задач, в то время как приложение в фоновом режиме, имейте в виду, что сканирование для периферийных устройств, в то время как приложение в фоновом режиме, работает по-другому чем тогда, когда приложение находится на переднем плане. В частности когда Ваше приложение сканирует для устройства в то время как в фоновом режиме:

  • CBCentralManagerScanOptionAllowDuplicatesKey функциональная клавиша сканирования проигнорирована, и многократные открытия рекламного периферийного устройства объединяются в единственное событие открытия.

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

Эти изменения помогают минимизировать радио-использование и улучшить время работы от батареи относительно Вашего устройства на iOS.

Периферийный для Bluetooth Фоновый Режим Выполнения

Выполнять определенные периферийные ролевые задачи, в то время как в фоновом режиме, необходимо включать UIBackgroundModes ключ с bluetooth-peripheral оцените в своем приложении Info.plist файл. Когда эта пара ключ/значение включена в приложение Info.plist файл, система будит Ваше приложение, чтобы обработать чтение, записать, и события подписки.

В дополнение к разрешению Вашего приложения быть разбуженными для обработки чтения запишите, и запросы подписки от связанного centrals, Ядро, которое платформа Bluetooth позволяет приложению распространять, в то время как в фоновом режиме утверждают. Однако необходимо знать, что распространение, в то время как приложение в фоновом режиме, работает по-другому чем тогда, когда приложение находится на переднем плане. В частности когда Ваше приложение распространяется в то время как в фоновом режиме:

  • CBAdvertisementDataLocalNameKey ключ рекламы проигнорирован, и локальное имя периферийного устройства не распространено.

  • Вся служба UUIDs, содержавшаяся в значении CBAdvertisementDataServiceUUIDsKey ключ рекламы помещается в специальную область «переполнения»; они могут быть обнаружены только устройством на iOS, явно сканирующим для них.

  • Если все распространяющиеся приложения в фоновом режиме, частота, в которой Ваше периферийное устройство отправляет рекламные пакеты, может уменьшиться.

Используйте фоновые режимы выполнения мудро

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

Любое приложение, объявляющее поддержку любого из Ядра фоновые режимы выполнения Bluetooth, должно следовать нескольким основным инструкциям:

Для больше-общей-информации о том, как Ваше приложение должно быть, ведите себя в фоновом режиме состояние, смотрите Быть Ответственным Фоновым приложением в Руководстве по программированию приложения для iOS.

Выполнение долгосрочных действий в фоновом режиме

Некоторые приложения, возможно, должны использовать Ядро платформа Bluetooth для выполнения долгосрочных действий в фоновом режиме. Как пример, предположите разработку домашнего приложения защиты для устройства на iOS, связывающегося с дверной блокировкой (оборудованный низкоэнергетической технологией Bluetooth). Приложение и блокировка взаимодействуют для автоматической блокировки двери, когда пользователь уезжает из дома, и разблокируйте дверь, когда пользователь возвращается — все, в то время как приложение в фоновом режиме. Когда пользователь уезжает из дома, устройство на iOS может в конечном счете стать из диапазона блокировки, заставив соединение с блокировкой быть потерянным. В этой точке приложение может просто вызвать connectPeripheral:options: метод CBCentralManager класс, и потому что запросы на установление соединения убирают не время, устройство на iOS, повторно соединится, когда пользователь возвратится домой.

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

Сохранение состояния и восстановление

Поскольку сохранение состояния и восстановление встроены к Ядру Bluetooth, Ваше приложение может решить в к этой функции попросить, чтобы система сохранила состояние центральных и периферийных менеджеров Вашего приложения и продолжала выполнять определенные связанные с Bluetooth задачи от их имени, даже когда больше не работает Ваше приложение. Когда одна из этих задач завершается, система повторно запускает Ваше приложение в фон и дает Вашему приложению возможность восстановить ее состояние и обработать событие соответственно. В случае домашнего приложения защиты, описанного выше, система контролировала бы запрос на установление соединения и переповторно запустила бы приложение для обработки centralManager:didConnectPeripheral: обратный вызов делегата, когда пользователь возвратился домой и завершенный запрос на установление соединения.

Базовый Bluetooth поддерживает сохранение состояния и восстановление для приложений, реализующих центральную роль, периферийную роль или обоих. Когда Ваше приложение реализует центральную роль и добавляет поддержку сохранения состояния и восстановления, система сохраняет состояние Вашего центрального объекта менеджера, когда система собирается завершить Ваше приложение для высвобождения памяти (если приложение имеет многократных центральных менеджеров, можно выбрать, которые Вы хотите, чтобы система отслеживала). В частности для данного CBCentralManager объект, система отслеживает:

  • Службы, для которых сканировал центральный менеджер (и любые опции сканирования указал, когда сканирование запустилось),

  • Периферийные устройства центральный менеджер пытался соединиться с или уже соединился с

  • Характеристики центральный менеджер были подписаны на

Приложения, реализующие периферийную роль, могут аналогично использовать в своих интересах сохранение состояния и восстановление. Для CBPeripheralManager объекты, система отслеживает:

  • Данные периферийный менеджер распространялись

  • Службы и характеристики периферийный менеджер опубликовали к базе данных устройства

  • centrals, подписанные на значения Ваших характеристик

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

Добавление поддержки сохранения состояния и восстановления

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

  1. Когда Вы выделяете и инициализируете центральный или периферийный объект менеджера, (Требуемый) Выбирают в утвердить сохранение и восстановление. Этот шаг описан в, Выбирают В к Сохранению состояния и Восстановлению.

  2. (Требуемый) Повторно инстанцируют любых центральных или периферийных объектов менеджера после того, как Ваше приложение будет повторно запущено системой. Этот шаг описан в, Повторно инстанцируют Ваших Центральных и Периферийных менеджеров.

  3. (Требуемая) Реализация надлежащий метод делегата восстановления. Этот шаг описан в Реализации Надлежащий Метод делегата Восстановления.

  4. (Необязательно) Обновление процесс инициализации Ваших центральных и периферийных менеджеров. Этот шаг описан в Обновлении Ваш Процесс Инициализации.

Выберите в к сохранению состояния и восстановлению

Для выбора в к функции сохранения и восстановления состояния просто обеспечьте уникальный идентификатор восстановления, когда Вы выделите и инициализируете центрального или периферийного менеджера. Идентификатор восстановления является строкой, идентифицирующей центрального или периферийного менеджера для Ядра Bluetooth и для Вашего приложения. Значение строки является значительным только к Вашему коду, но присутствие этой строки говорит Ядру Bluetooth, что это должно сохранить состояние маркированного объекта. Базовый Bluetooth сохраняет состояние только тех объектов, имеющих идентификатор восстановления.

Например, для выбора в утвердить сохранение и восстановление в приложении, использующем только один экземпляр a CBCentralManager возразите, чтобы реализовать центральную роль, указать CBCentralManagerOptionRestoreIdentifierKey опция инициализации и предоставляет идентификатор восстановления центральному менеджеру, когда Вы выделяете и инициализируете ее.

    myCentralManager =
        [[CBCentralManager alloc] initWithDelegate:self queue:nil
         options:@{ CBCentralManagerOptionRestoreIdentifierKey:
         @"myCentralManagerIdentifier" }];

Несмотря на то, что вышеупомянутый пример не демонстрирует это, Вы выбираете в утвердить сохранение и восстановление в приложении, использующем периферийные объекты менеджера аналогичным способом: Укажите CBPeripheralManagerOptionRestoreIdentifierKey когда Вы выделяете и инициализируете каждый периферийный объект менеджера, опция инициализации, и обеспечивает идентификатор восстановления.

Повторно инстанцируйте своих центральных и периферийных менеджеров

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

Если Ваше приложение использует больше чем одного центрального или периферийного менеджера или если оно использует менеджера, который не является вокруг для времени жизни Вашего приложения, Ваше приложение должно знать, каких менеджеров повторно инстанцировать, когда оно повторно запускается системой. Можно получить доступ к списку всех идентификаторов восстановления для объектов менеджера, которые система сохраняла для приложения, когда это было завершено, при помощи надлежащих функциональных клавиш запуска (UIApplicationLaunchOptionsBluetoothCentralsKey или UIApplicationLaunchOptionsBluetoothPeripheralsKey) при реализации делегата приложения application:didFinishLaunchingWithOptions: метод.

Например, когда Ваше приложение повторно запускается системой, можно получить все идентификаторы восстановления для центральных объектов менеджера, которые что система сохраняла для приложения, как это:

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 
    NSArray *centralManagerIdentifiers =
        launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey];
    ...

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

Реализуйте надлежащий метод делегата восстановления

После того, как Вы повторно инстанцируете соответствующих центральных и периферийных менеджеров в своем приложении, восстановите их путем синхронизации их состояния с состоянием системы Bluetooth. Чтобы принести Вашему приложению до скорости с тем, что система делала от своего лица (в то время как это не работало), необходимо реализовать надлежащий метод делегата восстановления. Для центральных менеджеров реализуйте centralManager:willRestoreState: метод делегата; для периферийных менеджеров реализуйте peripheralManager:willRestoreState: метод делегата.

В обоих из вышеупомянутых методов делегата последний параметр является словарем, содержащим информацию о менеджерах, сохраненных в то время, когда приложение было завершено. Для списка доступных ключей словаря посмотрите Central Manager State Restoration Options константы в Ссылке на протокол CBCentralManagerDelegate и Peripheral_Manager_State_Restoration_Options константы в Ссылке на протокол CBPeripheralManagerDelegate.

Восстановить состояние a CBCentralManager объект, используйте ключи для словаря, который предоставлен в centralManager:willRestoreState: метод делегата. Как пример, если Ваш центральный объект менеджера имел какие-либо активные или незаконченные соединения в то время, когда было завершено Ваше приложение, система продолжала контролировать их от имени Вашего приложения. Поскольку следующее показывает, можно использовать CBCentralManagerRestoredStatePeripheralsKey ключ словаря для получения списка всех периферийных устройств (представленным CBPeripheral объекты) центральный менеджер был подключен с или пытался соединиться с:

- (void)centralManager:(CBCentralManager *)central
      willRestoreState:(NSDictionary *)state {
 
    NSArray *peripherals =
        state[CBCentralManagerRestoredStatePeripheralsKey];
    ...

То, что Вы делаете со списком восстановленных периферийных устройств в вышеупомянутом примере, зависит от варианта использования. Например, если Ваше приложение сохраняет список периферийных устройств, центральный менеджер обнаруживает, можно хотеть добавить восстановленные периферийные устройства к тому списку для хранения ссылок на них. Как описано в Соединении с Периферийным устройством после Обнаружения Его, убедиться установить делегата периферийного устройства, чтобы гарантировать, что это получает надлежащие обратные вызовы.

Можно восстановить состояние a CBPeripheralManager объект похожим способом при помощи ключей к словарю, который предоставлен в peripheralManager:willRestoreState: метод делегата.

Обновите свой процесс инициализации

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

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

    NSUInteger serviceUUIDIndex =
        [peripheral.services indexOfObjectPassingTest:^BOOL(CBService *obj,
        NSUInteger index, BOOL *stop) {
            return [obj.UUID isEqual:myServiceUUIDString];
        }];
 
    if (serviceUUIDIndex == NSNotFound) {
        [peripheral discoverServices:@[myServiceUUIDString]];
        ...

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