Разработка приложений Bluetooth

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

Эта глава сначала представляет обзор различных типов приложений Bluetooth. Тогда это обсуждает общие принципы разработки для рассмотрения при разработке приложения Bluetooth для OS X. Наконец, это описывает некоторые определенные задачи, которые приложение, возможно, должно было бы выполнить.

Обзор типов приложения Bluetooth

Приложения Bluetooth выполняют палитру от игр, которые могут использовать устройство ввода данных Bluetooth к приложениям, продающим службы Bluetooth или поддерживающим новые профили. Для различных приложений нужны разные уровни “осведомленности Bluetooth” для успешного выполнения их функций. Некоторые приложения могут быть в состоянии использовать высокоуровневого менеджера, которого OS X предоставляет, никогда не имея необходимость использовать Bluetooth API. Другие будут использовать Bluetooth API экстенсивно для предоставления специфичных для Bluetooth услуг. Интеграция поддержки Bluetooth на OS X поддерживает приложения всюду по этому диапазону.

Чтобы помочь Вам решить в том, что уровень Ваше приложение должен передать с bluetooth-устройством, этот раздел рассматривает некоторые типичные меры, которые могло бы принять приложение Bluetooth. После чтения этого раздела у Вас будет лучшая идея того, какие части OS X Bluetooth API (если таковые имеются) необходимо использовать.

Доступ к устройству класса HID

Если Вы пишете игру или другое приложение, принимающее ввод от устройства класса HID, можно задаваться вопросом, необходимо ли сделать что-то специальное для поддержки устройств с поддержкой Bluetooth. Также при обеспечении устройства класса HID с поддержкой Bluetooth Вы могли бы задаться вопросом, как реализовать специальные опции в Вашем драйвере. К счастью, Apple выполнил большую часть работы для Вас. В версии 10.2.5 OS X и позже, Apple обеспечивает полностью совместимый драйвер класса HID, поддерживающий Bluetooth. Это означает, что с поддержкой Bluetooth, устройства класса HID работают прозрачно над версией 10.2.5 OS X и позже: Ваша игра или другое приложение, принимающее ввод от устройства класса HID, не должны касаться транспорта устройства. Одинаково важный, это также означает, что Вы не должны использовать Bluetooth Apple API для доступа к таким устройствам.

При конфигурировании устройства класса HID предоставленный Apple драйвер класса HID загружается и заботится обо всех протоколах и профилях, говорящих с модулем Bluetooth на устройстве. Вы не должны писать резидентный ядром драйвер для получения доступа к устройству. Вместо этого Ваше приложение может получить доступ и даже настроить Apple использования устройства класса HID менеджер по HID клиент API. OS X менеджер по HID клиент API обеспечивает доступ к устройству класса HID через интерфейс устройства, экспортируемый в пространство пользователя семьей HID. Например, с помощью менеджера по HID клиент API Вы можете:

  • Откройте или закройте устройство

  • Получите новое значение элемента

  • Установите значение элемента

Для получения дополнительной информации об использовании менеджера по HID клиент API для доступа к устройству класса HID посмотрите Руководство по Интерфейсу Устройства Класса HID. Для примера кода, иллюстрирующего, как использовать менеджера по HID клиент API, посмотрите Игровой Пример кода Обратной связи Устройства и Силы Интерфейса пользователя.

Несмотря на то, что Вы не должны использовать Bluetooth API для доступа к устройству класса HID, можно принять решение использовать функции или методы от платформы Bluetooth для улучшения опыта пользователя. Например, Ваше приложение может предоставить специфичную для Bluetooth информацию, сообщающую пользователю, если устройство не поддерживает определенную службу. Можно читать о некоторых из этих задач в Наборе Определенных Задач.

Доступ к последовательным портам

Профиль последовательного порта Bluetooth формирует основание многих других профилей, таких как коммутируемые сети, обмен родового объекта и объектное нажатие. Кроме того, профиль последовательного порта обеспечивает уровень эмуляции последовательного порта, поддерживающий приложения, требующие доступа прямого последовательного порта. С профилем последовательного порта Bluetooth эти приложения могут обработать ссылку Bluetooth как ссылку последовательного кабеля с помощью стандартного POSIX ttys.

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

  • Обо всех специфичных для Bluetooth ошибках сообщают как отказ открыть последовательный порт.

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

  • Пользователь должен установить последовательный порт.

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

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

  • Беспрепятственный доступ к последовательным портам

  • Полный контроль над созданием, поведением и уничтожением каналов RFCOMM

  • Тонкозернистое сообщение об ошибке, включая создание отчетов специфичных для Bluetooth ошибок и сообщений о состоянии

  • Чистый и всесторонний пользовательский интерфейс, обладающий, интегрировал панели Bluetooth UI для выбора устройства

Продажа службы Bluetooth

Поддержка Bluetooth на версии 10.2 OS X и позже позволяет Вам создавать новые службы в программном обеспечении и делать их доступными для удаленных клиентов. Используя APIs в платформах Bluetooth, Вы определяете службу, гарантируете, что это видимо другим, и служите ему удаленным клиентам.

Конечно, который Bluetooth APIs, который Вы используете, зависит от природы услуги, которую Вы планируете предложить. Одной задачей, которая характерна для всех таких приложений, однако, является добавление службы к локальной базе данных SDP. Служба должна присутствовать в базе данных SDP, таким образом, удаленные клиенты могут найти его во время запроса SDP. Apple оптимизировал эту задачу путем определения:

  • Объем службы

  • Формат атрибутов службы

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

Как описано в Объектах в подключениях Bluetooth, система Bluetooth использует формат словаря для определения службы Bluetooth. В словаре службы каждая запись соответствует атрибуту службы. Эта схема делает новую службу простой определить, потому что можно описать ее в списке свойств. Это также упрощает добавлять словарь к базе данных SDP. Используя платформу Bluetooth API можно создать служебную книжку SDP из словаря, добавить его к базе данных SDP и удалить его из базы данных.

Для определенной детализации в качестве примера, как работать со словарями атрибута службы, посмотрите Предоставление Новой Услуги.

Другая задача, определенная для создания новой службы для продажи, заставляет UUID идентифицировать его. Спецификация Bluetooth определяет UUIDs для различных профилей и служб. Кроме того, SDP описывает метод генерации UUIDs, гарантирующего чрезвычайно маленький шанс дублирования. Для получения дополнительной информации об основании этого метода посмотрите http://www .opengroup.org/publications/catalog/c706.htm. Apple использует Базовые функции Основы для генерации UUIDs. Для получения дополнительной информации о том, как сделать это, посмотрите Генерацию UUID.

Общие конструктивные соображения

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

Запрос и разбивка на страницы

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

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

  • Приложение, постоянно выполняющее запросы, разрушает 802.11b трафик в близости.

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

  • Выполнение частых страниц не приводит к положительному пользовательскому опыту.

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

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

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

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

В версии 10.4 OS X Apple представил класс IOBluetoothDeviceInquiry. Используя объект IOBluetoothDeviceInquiry, который инстанцируют от этого класса, Ваше приложение может выполнить запросы устройства не-GUI.

Ограничения пропускной способности

Bluetooth был разработан как низкая пропускная способность, решение для беспроводного подключения. Важно помнить ограничение пропускной способности при разработке приложения. Общий бюджет на ссылку для пропускной способности и пропускной способности составляет 720 Кбит/с. Это означает, что существует 720 Кбит/с, доступных, чтобы быть совместно использованными среди всех соединений на ссылке. Когда приложение предполагает, что все 720 Кбит/с доступны единственному соединению, существует два негативных последствия:

  • Производительность на других соединениях ухудшается

  • Если пользователь выбрал для использования мыши Bluetooth или клавиатуры, приложение, вероятно, испытает намного более низкий уровень пропускной способности, особенно. Ограничения качества обслуживания требуют, чтобы OS X посвятил пропускную способность этим устройствам, также.

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

SCO

Как описано в Стеке протоколов Bluetooth, SCO обозначает синхронные, ссылки с установлением соединения. Эти ссылки используются прежде всего для голосовой связи. С Bluetooth 1.5 (который работает в версии 10.3.2 OS X и позже), Apple представил поддержку профиля гарнитуры, основывающегося на ссылке SCO. Используя компьютер, оборудованный внутренним Apple модуль Bluetooth (или D-Link версия DBT-120. B или позже), выполнение последнего встроенного микропрограммного обеспечения, можно использовать гарнитуру с поддержкой Bluetooth для передачи беты общественности iChat AV 2.1 использования или позже.

Важно понять, что в его текущей реализации SCO не достаточен для распознавания речи в OS X. Несмотря на то, что операционная система могла поддерживать его, большинство основанных на SCO гарнитур не будет в состоянии поставить 22 кГц, 16-разрядное разрешение, требуемое для распознавания речи.

Интерфейсы устройства

Если Вы знакомы с Набором I/O, объектно-ориентированной платформой Apple для разработки драйверов устройств, можно также быть знакомы с понятием интерфейса устройства. Интерфейс устройства является конструкцией Набора I/O, позволяющей Вам аппаратным средствам доступа из приложений. Используя интерфейс устройства, можно разработать основанный на приложении драйвер устройства, обладающий тем же уровнем управления, доступного в драйверах ядра.

Вы не должны использовать интерфейс устройства для доступа к bluetooth-устройству из приложения. APIs платформы Bluetooth, доступный в версии 10.2 OS X и позже, обеспечивает все, что необходимо получить доступ и к bluetooth-устройствам и к объектам в стеке протоколов Bluetooth. Используя платформу Bluetooth APIs, Вы можете:

  • Создайте и уничтожьте соединения

  • Получите уведомления о появлении устройства и исчезновении

  • Данные передачи к и от устройства

Набор определенных задач

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

Предоставление новой услуги

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

Существует пять шагов в предоставлении услуги:

  1. Определите службу.

  2. Генерируйте UUID для службы (или, если Вы предоставляете предопределенную услугу, используйте UUID, определенный в профиле).

  3. Добавьте определение службы базе данных SDP.

  4. Регистр для уведомления об открытии входящего канала присвоился к службе.

  5. Закончено предоставляя услугу, удалите определение службы из базы данных SDP.

Следующие разделы описывают эти пять шагов подробно.

Определение службы

Как описано в Объектах в подключениях Bluetooth, Вы определяете службу путем создания словаря, в котором каждая пара ключ/значение или свойство, соответствует атрибуту службы. Apple упрощает добавлять новые службы к системе путем поддержки импорта a plist файл, содержащий словарь. Таким образом, вместо того, чтобы создать потенциально сложный словарь в коде, можно использовать Редактора Списка свойств приложение для создания его. Затем Вы используете Bluetooth API для загрузки словаря в приложение. Рисунок 3-1 показывает часть словаря, описывающего Серверную службу Чата RFCOMM.

Рисунок 3-1  Частичное перечисление словаря Серверной службы Чата RFCOMM
Partial listing of RFCOMM Chat Server service dictionary

Каждое свойство в словаре соответствует одному из многих атрибутов службы, определенных спецификацией Bluetooth (или к одному из атрибутов, определенных в профиле службы). Ключ свойства является атрибутом ID, и значение является значением данных атрибута. Например, первое свойство в словаре на рисунке 3-1 описывает дескриптор служебной книжки, 32-разрядное число, однозначно определяющее службу в сервере. Третья пара ключ/значение описывает протоколы Bluetooth потребности службы.

Каждый ключ атрибута является строкой, которая должна начаться с шестнадцатеричного числа, представляющего ID атрибута. Этот IDs определяется в файле BluetoothAssignedNumbers.h, доступный в платформе Bluetooth. Если Вы выбираете, можно добавить другие символы к строке ключа, но только после пространства после шестнадцатеричного Идентификационного номера. Например, каждый ключ в словаре выше выводит на экран имя атрибута после Идентификационного номера и пространства.

Каждое значение атрибута содержит информацию, описывающую атрибут. Спецификация Bluetooth определяет несколько типов данных, идентифицирующих различные типы данных, которые могут содержать значения атрибута. Например, целое без знака является типом 1, и последовательность элементов данных является типом 6. Apple отобразил эти типы данных на Фундаментальные классы, такие как NSNumber и NSArray. В свою очередь, эти классы соответствуют собственным типам списка свойств, такой как integer и array. Эта цепочка корреспонденции упрощает переводить словарь в a plist файл в объект служебной книжки, представляющий Вашу службу.

Как Вы видите на рисунке 3-1, однако, значения атрибута отличаются значительно от друг друга. Это вызвано тем, что различные типы значения атрибута могут быть описаны по-разному. Формально, значение атрибута описано комбинацией трех компонентов:

  • Размер данных

  • Описание типа данных

  • Сами данные

Этот набор информации аккуратно получен в словаре с тремя свойствами, в котором каждый ключ свойства называет компонент, и каждое соответствующее значение содержит информацию. Пример такого словаря в значении ключа списка дескриптора протокола, показанного на рисунке 3-1:

<dict>
    <key>DataElementSize</key>
    <integer>1</integer>
    <key>DataElementType</key>
    <integer>1</integer>
    <key>DataElementValue</key>
    <integer>3</integer>
</dict>

Однако упростить создавать словарь атрибута в a plist файл, Apple обеспечивает некоторые ярлыки для типов общих данных:

  • Если значение атрибута имеет тип string, data, или array, Вы не должны обеспечивать свойство размера элемента данных. Это вызвано тем, что OS X, система Bluetooth выведет тип данных из словаря, вводит и вычисляет размер от самих данных.

  • Если значение атрибута является строкой или 32-разрядным целым числом без знака, никакой словарь с тремя свойствами не требуется, чтобы описывать его. Значение ключа дескриптора служебной книжки в рисунке 3-1 является примером 32-разрядного целочисленного значения без знака.

  • Если значение имеет nil введите (тип 0), ни свойство размера элемента данных, ни свойство значения элемента данных не требуются.

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

  • Если значение атрибута является UUID, можно использовать data тип списка свойств для содержания его. OS X система Bluetooth выведет тип данных и вычислит размер от значения.

  • Если значение атрибута является списком, таким как атрибут списка дескриптора протокола на рисунке 3-1, Вы используете array тип списка свойств для представления его. Каждый элемент массива описывает элемент списка. Поскольку каждый элемент массива является самостоятельно элементом данных, он должен соответствовать инструкциям для значений атрибута.

В это время существует два свойства атрибута службы, которые Вы не должны помещать в свой словарь службы:

  • Дескриптор служебной книжки

  • Идентификатор канала RFCOMM

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

Атрибуты службы, обсужденные до сих пор, определяются спецификацией Bluetooth. Они сделаны доступными посредством процесса открытия службы, таким образом, потенциальные клиенты могут сделать информированный выбор. В дополнение к этим атрибутам Apple определяет дополнительные локальные атрибуты, управляющие локальным поведением службы. Эти атрибуты не видимы удаленным клиентам. В это время Apple определяет два локальных атрибута:

  • Персистентный

  • Целевое приложение

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

Персистентный атрибут (идентифицированный ключом Persistent) принимает булев тип. Значение TRUE указывает, что служба должна сохраниться вне приложения, инициировавшего его и через системные перезагрузки. При использовании этого атрибута для обозначения службы как персистентную, дескриптор служебной книжки автоматически сохраняется. Это используется для восстановления службы каждый раз, когда присутствуют связанные аппаратные средства Bluetooth. Важно, что Ваше приложение сохраняет свою собственную копию рекордного дескриптора персистентной службы, также. Это вызвано тем, что единственный способ программно удалить персистентную службу состоит в том, чтобы передать рекордный дескриптор IOBluetoothRemoveServiceWithRecordHandle функция. (Для получения информации о том, как вызвать удаление службы, дескриптор которой Вы не знаете, посмотрите Удаление Службы Без Дескриптора.)

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

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

Генерация UUID

Для генерации UUID для службы можно использовать утилиту командной строки uuidgen. Просто введите uuidgen на командной строке для получения уникального 128-разрядного значения в форме акцентированной дефисом строки ASCII, как в этом примере:

% uuidgen
4302FA6D-089B-11D8-96C4-0030656F08FE

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

Перечисление 3-1  , Генерирующее новый UUID в коде

#include <CoreFoundation/CoreFoundation.h>
 
int main()
{
    CFUUIDRef   uuid;
    CFStringRef string;
 
    uuid = CFUUIDCreate( NULL );
    string = CFUUIDCreateString( NULL, uuid );
 
    CFShow( string );
}

Добавление определения службы базе данных SDP

После описания атрибутов службы в a plist файл, Вы готовы использовать его в своем приложении. Следующее является схемой шагов, которые Вы предпринимаете для предоставления доступа к службе доступной:

  1. Создайте словарь и инициализируйте его с содержанием Вашего plist файл.

  2. Создайте служебную книжку SDP, содержащую атрибуты в Вашем словаре.

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

  4. Если необходимо, сохраните RFCOMM или канал L2CAP, который система присваивает Вашей службе.

Код в Перечислении 3-2 показывает, как реализовать эти шаги. Это предполагает, что Вы уже определили словарь атрибута в a plist файл и знает путь файла. Для пользы краткости только показана ограниченная обработка ошибок.

Перечисление 3-2  , Делающее новую доступную службу

- (BOOL)publishService
{
    NSString            *dictionaryPath = nil;
    NSString            *serviceName = nil;
    NSMutableDictionary *sdpEntries = nil;
 
    // Create a string with the new service name.
    serviceName = [NSString stringWithFormat:@"%@ My New Service", [self
                            localDeviceName]];
 
    // Get the path for the dictionary we wish to publish.
    dictionaryPath = [[NSBundle mainBundle]
                pathForResource:@"MyServiceDictionary" ofType:@"plist"];
 
    if ( ( dictionaryPath != nil ) && ( serviceName != nil ) )
    {
        // Initialize sdpEntries with the dictionary from the path.
        sdpEntries = [NSMutableDictionary
                    dictionaryWithContentsOfFile:dictionaryPath];
 
        if ( sdpEntries != nil )
        {
            IOBluetoothSDPServiceRecordRef  serviceRecordRef;
 
            [sdpEntries setObject:serviceName forKey:@"0100 - ServiceName*"];
 
        // Create a new IOBluetoothSDPServiceRecord that includes both
        // the attributes in the dictionary and the attributes the
        // system assigns. Add this service record to the SDP database.
            if (IOBluetoothAddServiceDict( (CFDictionaryRef) sdpEntries,
                        &serviceRecordRef ) == kIOReturnSuccess)
            {
                IOBluetoothSDPServiceRecord *serviceRecord;
 
                serviceRecord = [IOBluetoothSDPServiceRecord
                            withSDPServiceRecordRef:serviceRecordRef];
 
                // Preserve the RFCOMM channel assigned to this service.
                // A header file contains the following declaration:
                // IOBluetoothRFCOMMChannelID mServerChannelID;
                [serviceRecord getRFCOMMChannelID:&mServerChannelID];
 
                // Preserve the service-record handle assigned to this
                // service.
                // A header file contains the following declaration:
                // IOBluetoothSDPServiceRecordHandle mServerHandle;
                [serviceRecord getServiceRecordHandle:&mServerHandle];
 
                // Now that we have an IOBluetoothSDPServiceRecord object,
                // we no longer need the IOBluetoothSDPServiceRecordRef.
                IOBluetoothObjectRelease( serviceRecordRef );
 
            }
        }
    }
}

Получение открытых для канала уведомлений

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

Перечисление 3-3  , Регистрирующееся для открытого для канала уведомления

// Register for a notification so we get notified when a client opens
// the channel assigned to our new service.
// A header file contains the following declaration:
// IOBluetoothUserNotification *mIncomingChannelNotification;
 
mIncomingChannelNotification = [IOBluetoothRFCOMMChannel
        registerForChannelOpenNotifications:self
        selector:@selector(newRFCOMMChannelOpened:channel:)
        withChannelID:mServerChannelID
        direction:kIOBluetoothUserNotificationChannelDirectionIncoming];

Снятие службы

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

Перечисление 3-4  , Подготавливающее прекратить предоставлять услугу

- (void)stopProvidingService
{
    if ( mServerHandle != 0 )
    {
        // Remove the service.
        IOBluetoothRemoveServiceWithRecordHandle( mServerHandle );
    }
 
    // Unregister the notification.
    if ( mIncomingChannelNotification != nil )
    {
        [mIncomingChannelNotification unregister];
        mIncomingChannelNotification = nil;
    }
 
    mServerChannelID = 0;
}

Удаление службы без дескриптора

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

  1. Включите пользователю root.

    Чтобы сделать это, откройте Directory Utility (расположенный в /Applications/Utilities), щелкните по блокировке, чтобы внести изменения и выбрать Edit> Enable Root User. (Обратите внимание на то, что необходимо отключить пользователя root, когда Вы не используете его, для обеспечения безопасности и устойчивости системы.)

  2. Откройте Терминальное приложение и войдите в систему как корень.

  3. Каталог изменения к /var/root/Library/Preferences.

  4. Удалите blued.plist файл.

Используя делегатов для получения асинхронных сообщений

Начиная в версии 10.2.5 OS X, можно использовать делегатов в приложении Objective C для получения асинхронных сообщений, отправленных каналами RFCOMM и L2CAP. Эти сообщения включают уведомления о входящих данных и изменениях состояния канала. Когда канал L2CAP или RFCOMM открыт, клиент канала использует setDelegate: метод для обозначения делегата. Часто удобно для клиента сделать себя делегатом, как в этом примере:

[newRFCOMMChannel setDelegate:self]

Если Вы принимаете решение нанять делегата для получения асинхронных сообщений, необходимо реализовать, по крайней мере, входящий метод делегата данных. Другие методы делегата, такие как те, которые получают сообщения состояния канала, являются дополнительными. Заголовочные файлы IOBluetoothL2CAPChannel.h и IOBluetoothRFCOMMChannel.h (оба расположились в платформе Bluetooth), определяют неофициальные протоколы, описывающие доступные методы делегата. Например, как клиент канала RFCOMM, в дополнение к rfcommChannelData:data:length: метод, можно реализовать любой из следующих методов делегата:

  • rfcommChannelOpenComplete:status:

  • rfcommChannelClose:

  • rfcommChannelControlSignalChanged:

  • rfcommChannelFlowControlChanged:

  • rfcommChannelWriteComplete:refcon:status:

  • rfcommChannelQueueSpaceAvailable:

Выполнение запросов устройства

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

Ваше приложение, также, должно нести часть ответственности за бесперебойную работу процесса запроса устройства. В частности:

  • Вы не должны пытаться обойти ограничение запросов путем вызова start на IOBluetoothDeviceInquiry возражают многократно в быстрой преемственности. После вызова start, запрос может занять несколько секунд для начала и вызов start много раз подряд не изменяет это. Поэтому необходимо вызвать start только один раз для начала процесса запроса, распознавая, что запрос может не начаться, как только Вы ожидаете его к. Если Вы реализуете deviceInquiryStarted когда процесс запроса начнет искать устройства, метод делегата, Вы будете в состоянии сказать.

  • Можно сократить отрезок времени, который объект IOBluetoothDeviceInquiry проводит на процесс запроса, но Вы все еще не должны инициировать многократные запросы в течение того отрезка времени.

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

    Если необходимо выполнить запросы собственного имени на удаленных устройствах, сделайте так только после остановки объекта IOBluetoothDeviceInquiry.

Можно сказать объекту IOBluetoothDeviceInquiry выполнить запросы имени на удаленных устройствах, которые он находит путем вызова setUpdateNewDeviceNames метод. Можно тогда получить информацию после Вашего deviceInquiryDeviceFound метод делегата вызывается.

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