Интеграция Bluetooth Low Energy (BLE) в мобильное приложение

BLE-интеграция: стабильная работа с устройствами Мы часто видим проекты, где BLE-подключение реализовано как «включил сканирование — подключился — радуемся». В реальности это конечный автомат с дюжиной состояний, каждое из которых может завершиться ошибкой: адаптер выключен, устройство вне зоны,

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

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

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Интеграция Bluetooth Low Energy (BLE) в мобильное приложение
Сложный
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

BLE-интеграция: стабильная работа с устройствами

Мы часто видим проекты, где BLE-подключение реализовано как «включил сканирование — подключился — радуемся». В реальности это конечный автомат с дюжиной состояний, каждое из которых может завершиться ошибкой: адаптер выключен, устройство вне зоны, сервис не найден, характеристика не поддерживает запись. Наша команда — специалисты с 5+ летним опытом разработки BLE-решений для iOS и Android. Мы гарантируем, что ваше приложение стабильно обрабатывает все краевые случаи.

Почему BLE-интеграция требует профессионального подхода?

BLE работает по модели GATT (Generic Attribute Profile). Периферийное устройство предоставляет Services — логические группы функций. Каждый Service содержит Characteristics — конкретные значения для чтения, записи или подписки (notify/indicate). Ошибка на любом из этих уровней — и приложение не получит данные. Мы видели проекты, где разработчики забывали подписываться на дескриптор CCCD — в результате характеристика не отправляла уведомления.

Конечный автомат подключения

Минимальный набор состояний, который нужно обрабатывать явно:

IDLE → SCANNING → DISCOVERED → CONNECTING → CONNECTED → DISCOVERING_SERVICES → SERVICES_READY → SUBSCRIBING → READY 

И ошибки на каждом переходе: таймаут сканирования, разрыв соединения в CONNECTING, gattStatus != GATT_SUCCESS при discovery, потеря соединения в READY. Тестируем все сценарии с помощью симуляторов и реальных устройств.

Состояние iOS (CoreBluetooth) Android (BluetoothGatt)
IDLE .poweredOn BluetoothAdapter.state_on
SCANNING scanForPeripherals startScan
DISCOVERED didDiscover onScanResult
CONNECTING connect connectGatt
CONNECTED didConnect onConnectionStateChange (STATE_CONNECTED)
DISCOVERING_SERVICES discoverServices discoverServices
SERVICES_READY didDiscoverServices onServicesDiscovered
SUBSCRIBING setNotifyValue writeDescriptor (CCCD)
READY didUpdateValue onCharacteristicChanged

Что делать, если соединение разорвалось?

Самая частая ошибка — игнорирование didDisconnectPeripheral (iOS) или onConnectionStateChange с не-GATT_SUCCESS (Android). Без автоматического реконнекта пользователь вынужден перезапускать приложение. Мы реализуем логику с экспоненциальным backoff: при разрыве ждём 1 с, 2 с, 4 с, 8 с, затем сбрасываем. На iOS для работы в фоне используем CBCentralManagerOptionRestoreIdentifierKey — system wakes up the app when device reappears.

iOS: CoreBluetooth

import CoreBluetooth class BLEManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate { var centralManager: CBCentralManager! var targetPeripheral: CBPeripheral? override init() { super.init() centralManager = CBCentralManager(delegate: self, queue: DispatchQueue(label: "ble.queue")) } func centralManagerDidUpdateState(_ central: CBCentralManager) { guard central.state == .poweredOn else { // обрабатываем .poweredOff, .unauthorized, .unsupported return } startScanning() } func startScanning() { let serviceUUID = CBUUID(string: "180D") centralManager.scanForPeripherals(withServices: [serviceUUID], options: [ CBCentralManagerScanOptionAllowDuplicatesKey: false ]) } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) { guard RSSI.intValue > -80 else { return } // фильтр по сигналу centralManager.stopScan() targetPeripheral = peripheral centralManager.connect(peripheral, options: nil) } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { peripheral.delegate = self peripheral.discoverServices([CBUUID(string: "180D")]) } func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { guard error == nil, let services = peripheral.services else { return } for service in services { peripheral.discoverCharacteristics([CBUUID(string: "2A37")], for: service) } } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { guard let characteristics = service.characteristics else { return } for char in characteristics where char.properties.contains(.notify) { peripheral.setNotifyValue(true, for: char) } } func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { guard let data = characteristic.value else { return } // парсим data согласно GATT-спецификации характеристики } } 

Android: BluetoothGatt

val gattCallback = object : BluetoothGattCallback() { override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { if (status != BluetoothGatt.GATT_SUCCESS) { // status содержит код ошибки, например 133 (GATT_ERROR) - нужен реконнект gatt.close() return } if (newState == BluetoothProfile.STATE_CONNECTED) { gatt.discoverServices() } } override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { val characteristic = gatt .getService(UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb")) ?.getCharacteristic(UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb")) ?: return gatt.setCharacteristicNotification(characteristic, true) val descriptor = characteristic.getDescriptor( UUID.fromString("00002902-0000-1000-8000-00805f9b34fb") // Client Characteristic Configuration ) descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE gatt.writeDescriptor(descriptor) } override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { val data = characteristic.value // парсим } } device.connectGatt(context, false, gattCallback, BluetoothDevice.TRANSPORT_LE) 

Проблемы, которые мы решаем в каждом проекте

Проблема Решение
didDisconnectPeripheral без предупреждения Автореконнект с backoff, restoration identifier (iOS)
Статус 133 GATT_ERROR на Android gatt.close(), refresh() через рефлексию, повтор через 2 с
Сканирование убивает батарею allowDuplicates: false — включаем только при измерении RSSI
State restoration не работает Настраиваем CBCentralManagerOptionRestoreIdentifierKey в схеме
Android 12+ разрешения Запрашиваем BLUETOOTH_SCAN и BLUETOOTH_CONNECT динамически

Что входит в работу по интеграции BLE

  • Документация по GATT-схеме устройства (сервисы, характеристики, форматы данных)
  • Реализация сканирования, подключения, подписки, реконнекта
  • Обработка всех штатных и аварийных состояний
  • Оптимизация MTU: запрос 512 байт вместо 23 для ускорения передачи
  • Интеграция с тестовым устройством (предоставленным заказчиком или нашим)
  • Unit-тесты и сценарии нагрузочного тестирования (до 10 одновременных BLE-периферий)
  • Поддержка после сдачи: гарантия 3 месяца на стабильность соединения

Как мы работаем: от анализа до деплоя

  1. Аналитика — изучаем документацию устройства, согласуем GATT-схему и формат данных.
  2. Проектирование — создаём конечный автомат, определяем политику реконнекта.
  3. Реализация — пишем код на Swift/Kotlin с использованием современных фреймворков.
  4. Тестирование — проверяем на симуляторах, реальных устройствах, с эмуляцией помех.
  5. Деплой — публикуем в TestFlight / Firebase Distribution, помогаем с App Review (проверка раздела 4.2 и 5.1 App Store Review Guidelines).

Производительность и батарея

MTU по умолчанию — 23 байта. Запрашиваем через gatt.requestMtu(512) / peripheral.maximumWriteValueLength(for: .withResponse). На больших передачах (прошивка OTA, данные датчиков) это разница между 30 секундами и 3 минутами. Экономия времени при использовании нашей библиотеки достигает 40%. Финансовая эффективность интеграции BLE под ключ очевидна — вы получаете готовое решение без необходимости вникать в тонкости GATT.

Подробнее о MTU

По умолчанию BLE использует MTU 23 байта, из которых 3 — служебные. Мы запрашиваем 512 байт, что в 22 раза больше. Для передачи данных объёмом 1 Кбайт это сокращает количество пакетов с 50 до 3. На устройствах с ограниченным каналом (например, фитнес-браслеты) это экономит до 60% энергии.

Сроки и условия

Базовая интеграция (один notify-сервис) — 3-5 дней. Сложные сценарии (OTA, мультиперифери, background mode) — 1-2 недели. Стоимость рассчитывается индивидуально после анализа вашего устройства. Свяжитесь с нами для бесплатной оценки вашего проекта. Закажите интеграцию BLE сегодня — мы предложим варианты реализации.

Рекомендуем прочитать официальную документацию CoreBluetooth и Android BluetoothGatt для более детального понимания API. Подробнее о GATT читайте в Wikipedia.