Do all android tablets have bluetooth

Bluetooth Low Energy

In this document

Key classes

See Also

Video

DevBytes: Bluetooth Low Energy API

Android 4.3 (API Level 18) introduces built-in platform support for Bluetooth Low Energy in the central role and provides APIs that apps can use to discover devices, query for services, and read/write characteristics. In contrast to Classic Bluetooth, Bluetooth Low Energy (BLE) is designed to provide significantly lower power consumption. This allows Android apps to communicate with BLE devices that have low power requirements, such as proximity sensors, heart rate monitors, fitness devices, and so on.

Key Terms and Concepts

Here is a summary of key BLE terms and concepts:

  • Generic Attribute Profile (GATT)—The GATT profile is a general specification for sending and receiving short pieces of data known as «attributes» over a BLE link. All current Low Energy application profiles are based on GATT.
    • The Bluetooth SIG defines many profiles for Low Energy devices. A profile is a specification for how a device works in a particular application. Note that a device can implement more than one profile. For example, a device could contain a heart rate monitor and a battery level detector.
  • Attribute Protocol (ATT)—GATT is built on top of the Attribute Protocol (ATT). This is also referred to as GATT/ATT. ATT is optimized to run on BLE devices. To this end, it uses as few bytes as possible. Each attribute is uniquely identified by a Universally Unique Identifier (UUID), which is a standardized 128-bit format for a string ID used to uniquely identify information. The attributes transported by ATT are formatted as characteristics and services.
  • Characteristic—A characteristic contains a single value and 0-n descriptors that describe the characteristic’s value. A characteristic can be thought of as a type, analogous to a class.
  • Descriptor—Descriptors are defined attributes that describe a characteristic value. For example, a descriptor might specify a human-readable description, an acceptable range for a characteristic’s value, or a unit of measure that is specific to a characteristic’s value.
  • Service—A service is a collection of characteristics. For example, you could have a service called «Heart Rate Monitor» that includes characteristics such as «heart rate measurement.» You can find a list of existing GATT-based profiles and services on bluetooth.org.

Roles and Responsibilities

Here are the roles and responsibilities that apply when an Android device interacts with a BLE device:

  • Central vs. peripheral. This applies to the BLE connection itself. The device in the central role scans, looking for advertisement, and the device in the peripheral role makes the advertisement.
  • GATT server vs. GATT client. This determines how two devices talk to each other once they’ve established the connection.

To understand the distinction, imagine that you have an Android phone and an activity tracker that is a BLE device. The phone supports the central role; the activity tracker supports the peripheral role (to establish a BLE connection you need one of each—two things that only support peripheral couldn’t talk to each other, nor could two things that only support central).

Once the phone and the activity tracker have established a connection, they start transferring GATT metadata to one another. Depending on the kind of data they transfer, one or the other might act as the server. For example, if the activity tracker wants to report sensor data to the phone, it might make sense for the activity tracker to act as the server. If the activity tracker wants to receive updates from the phone, then it might make sense for the phone to act as the server.

In the example used in this document, the Android app (running on an Android device) is the GATT client. The app gets data from the GATT server, which is a BLE heart rate monitor that supports the Heart Rate Profile. But you could alternatively design your Android app to play the GATT server role. See BluetoothGattServer for more information.

BLE Permissions

In order to use Bluetooth features in your application, you must declare the Bluetooth permission BLUETOOTH . You need this permission to perform any Bluetooth communication, such as requesting a connection, accepting a connection, and transferring data.

If you want your app to initiate device discovery or manipulate Bluetooth settings, you must also declare the BLUETOOTH_ADMIN permission. Note: If you use the BLUETOOTH_ADMIN permission, then you must also have the BLUETOOTH permission.

Declare the Bluetooth permission(s) in your application manifest file. For example:

If you want to declare that your app is available to BLE-capable devices only, include the following in your app’s manifest:

However, if you want to make your app available to devices that don’t support BLE, you should still include this element in your app’s manifest, but set required=»false» . Then at run-time you can determine BLE availability by using PackageManager.hasSystemFeature() :

Setting Up BLE

Before your application can communicate over BLE, you need to verify that BLE is supported on the device, and if so, ensure that it is enabled. Note that this check is only necessary if is set to false.

If BLE is not supported, then you should gracefully disable any BLE features. If BLE is supported, but disabled, then you can request that the user enable Bluetooth without leaving your application. This setup is accomplished in two steps, using the BluetoothAdapter .

Читайте также:  Управление андроидом кнопками громкости

The BluetoothAdapter is required for any and all Bluetooth activity. The BluetoothAdapter represents the device’s own Bluetooth adapter (the Bluetooth radio). There’s one Bluetooth adapter for the entire system, and your application can interact with it using this object. The snippet below shows how to get the adapter. Note that this approach uses )»>getSystemService() to return an instance of BluetoothManager , which is then used to get the adapter. Android 4.3 (API Level 18) introduces BluetoothManager :

Next, you need to ensure that Bluetooth is enabled. Call isEnabled() to check whether Bluetooth is currently enabled. If this method returns false, then Bluetooth is disabled. The following snippet checks whether Bluetooth is enabled. If it isn’t, the snippet displays an error prompting the user to go to Settings to enable Bluetooth:

If you want to scan for only specific types of peripherals, you can instead call startLeScan(UUID[], BluetoothAdapter.LeScanCallback) , providing an array of UUID objects that specify the GATT services your app supports.

Here is an implementation of the BluetoothAdapter.LeScanCallback , which is the interface used to deliver BLE scan results:

Note: You can only scan for Bluetooth LE devices or scan for Classic Bluetooth devices, as described in Bluetooth. You cannot scan for both Bluetooth LE and classic devices at the same time.

Connecting to a GATT Server

The first step in interacting with a BLE device is connecting to it— more specifically, connecting to the GATT server on the device. To connect to a GATT server on a BLE device, you use the connectGatt() method. This method takes three parameters: a Context object, autoConnect (boolean indicating whether to automatically connect to the BLE device as soon as it becomes available), and a reference to a BluetoothGattCallback :

This connects to the GATT server hosted by the BLE device, and returns a BluetoothGatt instance, which you can then use to conduct GATT client operations. The caller (the Android app) is the GATT client. The BluetoothGattCallback is used to deliver results to the client, such as connection status, as well as any further GATT client operations.

In this example, the BLE app provides an activity ( DeviceControlActivity ) to connect, display data, and display GATT services and characteristics supported by the device. Based on user input, this activity communicates with a Service called BluetoothLeService , which interacts with the BLE device via the Android BLE API:

When a particular callback is triggered, it calls the appropriate broadcastUpdate() helper method and passes it an action. Note that the data parsing in this section is performed in accordance with the Bluetooth Heart Rate Measurement profile specifications:

Back in DeviceControlActivity , these events are handled by a BroadcastReceiver :

Reading BLE Attributes

Once your Android app has connected to a GATT server and discovered services, it can read and write attributes, where supported. For example, this snippet iterates through the server’s services and characteristics and displays them in the UI:

Receiving GATT Notifications

It’s common for BLE apps to ask to be notified when a particular characteristic changes on the device. This snippet shows how to set a notification for a characteristic, using the setCharacteristicNotification() method:

Once notifications are enabled for a characteristic, an onCharacteristicChanged() callback is triggered if the characteristic changes on the remote device:

Closing the Client App

Once your app has finished using a BLE device, it should call close() so the system can release resources appropriately:

Источник

Использование Bluetooth в Android

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

Работа с Bluetooth состоит из четырех этапов: установка настроек bluetooth адаптера, поиск доступных для соединения устройств, установка соединения, передача данных.

Обзор Android Bluetooth API

Bluetooth API располагается в пакетеandroid.bluetooth. В его состав входит несколько классов:

  • BluetoothAdapter— отвечает за работу с установленным в телефоне Bluetooth модулем. Экземпляр этого класса есть в любой программе, использующей bluetooth. В состав этого класса входят методы, позволяющие производить поиск доступных устройств, запрашивать список подключенных устройств, создавать экземпляр класса BluetoothDevice на основании известного MAC адреса и создавать BluetoothServerSocket для ожидания запроса на соединение от других устройств.
  • BluetoothDevice— класс, ассоциирующийся с удаленным Bluetooth устройством. Экземпляр этого класса используется для соединения через BluetoothSocket или для запроса информации об удаленном устройстве (имя, адресс, класс, состояние).
  • BluetoothSocket— интерфейс для Bluetooth socket, аналогичный TCP сокетам. Это точка соединения, позволяющая обмениваться данными с удаленным устройством через InputStream и OutputStream.
  • BluetoothServerSocket— представляет открытый сокет сервера, готовый к обработке входящего запроса. Для того чтобы соединить два Android устройства, одно из них должно открыть сокет с помощью этого класса. Когда удаленное устройство пошлет запрос на соединение, BluetoothServerSocket вернет объект BluetoothSocket.
  • BluetoothClass— описывает основные параметры Bluetooth модуля. Объект этого класса доступен только в режиме чтения и может быть полезен при определении типа устройства.
  • BluetoothProfile— интерфейс, представляющий Bluetooth профиль (спецификацию беспроводного интерфейса для соединения устройств через Bluetooth). Примером профиля может служить Hands-Free profile, определяющий порядок работы с беспроводной гарнитурой.
  • BluetoothHeadset— обеспечивает поддержку bluetooth гарнитур. Включает в себя профили Bluetooth Headset и Hands-Free (v1.5).
  • BluetoothA2dp— Описывает Advanced Audio Distribution Profile, определяющий передачу потока высококачественных аудиоданных через bluetooth.
  • BluetoothHealth— определяет proxy для Health Device Profile.
  • BluetoothHealthCallback— абстрактный класс, который можно использовать для реализации обратных вызовов от BluetoothHealth. Для того чтобы регистрировать изменение состояния Bluetooth устройства нужно на основе этого класса создать собственный и переопределить в нем callback методы.
  • BluetoothHealthAppConfiguration— конфигурация, которая используется для соединения с различными медицинскими bluetooth устройствами.
  • BluetoothProfile.ServiceListener— интерфейс, который посылает уведомление BluetoothProfile IPC клиентам при их подключении и отключении от сервиса.
Читайте также:  Мобильные модемы для андроид

В рамках этой статьи мы не будем углубляться в суть работы с медицинскими bluetooth устройствами и сосредоточимся на первых четырех классах.

Установка настроек Bluetooth адаптера из Android

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

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

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

При использовании разрешения BLUETOOTH_ADMIN, необходимо также указывать и BLUETOOTH.

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

Если ваш телефон не поддерживает bluetooth, будет возвращено значение «null». На практике нужно всегда проверять это условие, чтобы избежать ошибок.

Даже если ваш аппарат оснащен Bluetooth модулем, он может быть недоступен, поскольку пользователь просто отключил его. Для проверки доступности Bluetooth служит метод isEnabled(). В случае, если модуль отключен, можно предложить пользователю включить его.

Если пользователь согласился на включение адаптера, в переменную enableBtIntent будет записано значение RESULT_OK. В противном случае — RESULT_CANCELED.

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

Если приложение имеет разрешение BLUETOOTH_ADMIN, вы можете изменить имя Bluetooth устройства с помощью метода

для отображения состояния адаптера служит метод BluetoothAdapter.getState(). Этот метод может возвращать одно из следующих значений:

STATE_TURNING_ON
STATE_ON
STATE_TURNING_OFF
STATE_OFF

Часто в целях экономии заряда батареи Bluetooth выключен по умолчанию. Следующих код создает сообщение, в котором информирует пользователя о состоянии адаптера:

Организация поиска доступных bluetooth устройств

С помощью класса BluetoothAdapter, Вы можете найти удаленное bluetooth устройство, запустив сканирование или запросив список спаренных устройств.

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

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

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

Запрос на соединение со спаренным устройством

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

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

Поиск устройств

Для того, чтобы начать сканирование радиодиапазона на предмет наличия доступных устройств просто вызовите метод startDiscovery(). Сканирование происходит в отдельном асинхронном потоке. Метод возвращает true, если запуск сканирования прошел успешно. Обычно процесс сканирования занимает порядка 10-15 секунд. Чтобы получить информацию о найденных устройствах Ваше приложение должно зарегистрировать BroadcastReceiver для интента ACTION_FOUND. Этот интент вызывается для каждого найденного устройства. Интент содержит дополнительные поля EXTRA_DEVICE и EXTRA_CLASS, которые содержат объекты BluetoothDevice и BluetoothClass соответственно.

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

Включение Bluetooth из приложения

Современные Android смартфоны не могут похвастаться долгим временем работы, поэтому все нормальные люди отключают Bluetooth модуль. Если Вы припрограммровании для Android хотите дать своим пользователям возможность сделать телефон видимым для других телефонов, вызовите с помощью метода startActivityForResult(Intent, int) интент ACTION_REQUEST_DISCOVERABLE. В результате пользователю будет показано системное окно с запросом на перевод телефона в режим bluetooth видимости. По умолчанию этот режим включается на 120 секунд. Это время можно изменить с передав интенту дополнительный параметр EXTRA_DISCOVERABLE_DURATION. Максимально доступное время составляет 3600 секунд. Значение 0 переводит bluetooth модуль вашего телефона в режим постоянной видимости. Для примера создадим интент с запросом на переход в режим видимости на 300 секунд

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

Читайте также:  Android studio выравнивание кода горячие клавиши

Если вы хотите получить уведомления, при изменении режима видимости Вашего устройства, зарегистрируйте BroadcastReceiver для интента ACTION_SCAN_MODE_CHANGED. Дополнительные поля EXTRA_SCAN_MODE и EXTRA_PREVIOUS_SCAN_MODE позволяют получить информацию о новом и старом состоянии соответственно. Они могут принимать значения SCAN_MODE_CONNECTABLE_DISCOVERABLE, SCAN_MODE_CONNECTABLE или SCAN_MODE_NONE. Первое значение указывает на то, что устройство доступно для поиска. Второе — устройство не доступно для поиска, но способно принимать соединения. Третье — не доступно для поиска и не может принимать соединения.

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

Соединение устройств

Чтобы соединить два устройства, вы должны написать серверную и клиентскую часть кода. Одно из устройств должно открыть серверный сокет, а второе — инициализировать соединение, используя MAC адрес сервера. Сервер и клиент считаются соединенными, когда они оба имеют активный BluetoothSocket на одном и том же RFCOMM канале. После этого они могут поучать и отправлять потоки данных. Сервер и клиент по-разному получают требуемый BluetoothSocket. Сервер получает его, когда входящее соединение принято. Клиент — когда открывает RFCOMM для сервера.

Сервер

При соединении устройств одно из них должно вести себя как сервер, то есть удерживать открытый BluetoothServerSocket. Цель сервера — ждать запроса на входящее соединение, и когда оно подтверждено, создать BluetoothSocket. После этого BluetoothServerSocket можно закрыть. Рассмотрим поэтапно процедуру соединения с точки зрения сервера:

  1. Получить BluetoothServerSocket вызвав метод listenUsingRfcommWithServiceRecord(String, UUID). Первый параметр метода представляет собой идентификационное имя вашего сервиса. Система автоматически добавит его в базу Service Discovery Protocol (SDP). Обычно в качестве этого параметра просто указывают название приложения. Второй параметр также идентифицирует сервис. Этот параметр используется клиентом при подтверждении соединения.
  2. Начинаем прослушивать запрос на соединения через метод accept(). Это блокирующий метод, который возвращает результат либо когда соединение подтверждено, либо когда произошло исключение. Соединение считается подтвержденным, когда удаленное устройство пошлет запрос на соединение с UUID, указанным при регистрации серверного сокета. В случае успеха, accept() возвращает настроенный на соединение BluetoothSocket.
  3. Если Вы хотите принять дополнительное соединение, вызовите метод close(). Это приведет к освобождению сокета и всех его ресурсов, но не закроет соединенный BluetoothSocket. В отличие от TCP/IP, RFCOMM позволяет работать только с одним клиентом на канале, поэтому в большинстве случаев имеет смысл вызывать метод close() срезу же после установки принятия сокета.

Поскольку метод accept() является блокирующим, его не стоит вызывать из потока главной деятельности, поскольку это приведет к подвисанию интерфейса. Обычна вся работа с BluetoothServerSocket и BluetoothSocket выполняется в отдельном потоке. Чтобы прекратить выполнение метода accept(), вызовите метод close() для BluetoothServerSocket (или BluetoothSocket) из любого другого потока вашего приложения.

Ниже приведен пример потока, реализующий описанный выше механизм работы

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

Обратите внимание, когда accept() возвращает BluetoothSocket, сокет уже соединен, поэтому не требуется вызывать метод connect().

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

Вы должны закрыть BluetoothServerSocket сразу же после завершения прослушивания эфира на предмет наличия входящего соединения. В приведенном примере метод close() вызывается сразу после получения объекта BluetoothSocket. Также Вам может понадобиться public метод для остановки приватного BluetoothSocket.

Клиент

Для инициализации соединения с удаленным устройствам (устройством, которое держит открытым серверный сокет) вам необходимо получить объект BluetoothDevice, содержащий информацию о нем. Этот объект используется для получения BluetoothSocket и инициализации соединения.

Опишем процедуру соединения:

  1. Получим BluetoothSocket вызвав метод BluetoothDevice.createRfcommSocketToServiceRecord(UUID). Значение параметра UUID должно совпадать с значением, указанным при вызове listenUsingRfcommWithServiceRecord сервера.
  2. Инициализируем соединение, вызвав метод connect(). После вызова этого метода система будет выполнять SDP поиск на удаленном устройстве, чтобы сопоставить UUID. В случае успеха при условии подтверждения запроса со стороны сервера будет открыт RFCOMM канал. Это блокирующий вызов. Если по каким-то причинам соединение сорвется или выйдет timeout (около 12 секунд), будет сгенерировано исключение.

Как и в случае с accept, метод connect() следует выполнять в отдельном потоке, в противном случае может произойти подвисание интерфейса.

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

Приведем пример клиентского приложения, инициализирующего соединение

Для остановки сканирования эфира вызывается метод cancelDiscovery(). Перед вызовом этого метода можно проверить идет ли сканирование с помощью isDiscovering().

После завершения работы с BluetoothSocket всегда вызывайте метод close(). Это поможет сэкономить ресурсы телефона.

Передача данных

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

  1. С помощью методов getInputStream() и getOutputStream() полуить объекты InputStream и OutputStream, управляющие передачей через сокет.
  2. Читать и писать данные в поток с помощью методов read(byte[]) и write(byte[]).

Вы должны использовать отдельный поток для чтения и записи данных. Это важно, поскольку методы read(byte[]) и write(byte[]) являются блокирующими и их вызов в основном потоке может парализовать вашу программу. Главный цикл в этом отдельном потоке должен считывать данные из InputStream. Для записи в OutputStream имеет смысл создать отдельный public метод.

В конструкторе создаются объекты для работы с потоками данных, после чего поток оживает входящие данные. После того как прочитан очередной блок данных из входящего потока он посылается в главную деятельность посредствам вызова метода Handler родительского класса. Для отправки данных из главной деятельности просто вызывается метод write(). Внутри этого публичного метода происходит вызов write(byte[]). Метод close() также можно вызвать из главной деятельности. Он разрывает соединение.

Источник

Оцените статью