Додаток для обліку активності без інтеграції фітнес-платформи — втрата половини сценаріїв. Користувачі очікують автоматичний збір кроків, калорій, пульсу, але без Google Fit або Health Connect дані доводиться вводити вручну. Ми пропонуємо вбудувати Google Fit (і Health Connect як fallback) у ваш Android-додаток за 4–14 робочих днів — під ключ, з повною обробкою OAuth, дедуплікацією та підтримкою Wear OS. Наша команда має 5+ років досвіду в Android-розробці та понад 40 успішних проєктів з фітнес-інтеграцією.
Google Fit API існує з 2014 року і сьогодні перебуває в стані «працює, але краще мігрувати на Health Connect». Google офіційно рекомендує переходити на Health Connect для нових проєктів. Тим не менш, Google Fit залишається актуальним для пристроїв на Android 8–13 без підтримки Health Connect, для Wear OS-додатків та для проєктів з існуючою базою користувачів.
Google Fit REST API vs Fitness API
Дві принципово різні точки входу:
Android Fitness API (com.google.android.gms:play-services-fitness) — нативний Java/Kotlin SDK, працює через Google Play Services, потребує OAuth 2.0-акаунт Google.
Google Fit REST API — HTTP API, підходить для серверної сторони та Flutter/React Native, але потребує власного управління OAuth токенами.
Для нативного Android — завжди Fitness API. REST має сенс лише якщо дані потрібні на бекенді без участі мобільного пристрою.
Як ми інтегруємо Google Fit?
Ми використовуємо стек: Kotlin, Jetpack Compose, Hilt для DI, Google Sign-In для OAuth. На першому етапі аналізуємо вимоги до даних: які типи (кроки, пульс, калорії), чи потрібна агрегація за часом, чи потрібна підписка на живі дані. Потім проєктуємо архітектуру з урахуванням дедуплікації та обробки помилок. Реалізуємо читання історичних даних через HistoryClient і підписку через SensorsClient (для переднього плану) або RecordingClient (фоновий трекінг). Всі запити обгорнуті в suspend функції з корутинами для асинхронності.
Чому варто обирати Health Connect для нових проєктів?
Health Connect — це переосмислена платформа Google для обміну даними здоров'я між додатками. На відміну від Google Fit, вона не прив'язана до облікового запису Google, працює локально на пристрої та дає користувачеві більше контролю над тим, які додатки читають конкретні типи даних. Для Android 14+ вона доступна за замовчуванням, для старіших версій — через встановлення окремого APK.
| Характеристика |
Google Fit |
Health Connect |
| Залежність від акаунта Google |
Так |
Ні |
| Мінімальна версія Android |
8.0 |
8.0 (з APK) / 14+ (вбудований) |
| Дедуплікація |
Часткова |
Вбудована |
| Підтримка Wear OS |
Так |
Так |
| Рекомендація Google |
Fallback |
Основний стек |
Ми гарантуємо сумісність з обома підходами та допомагаємо клієнтам обрати стратегію міграції, оптимальну під їхню аудиторію.
Дозволи та OAuth: головне джерело проблем
Google Fit потребує двох рівнів дозволів:
- Android-дозвіл:
android.permission.ACTIVITY_RECOGNITION (з Android 10)
- OAuth scope:
FITNESS_ACTIVITY_READ, FITNESS_BODY_READ, FITNESS_LOCATION_READ тощо.
Якщо запросити Android-дозвіл, але не отримати OAuth scope — Fitness API поверне порожні дані без помилки. Це мовчазний збій, який важко відловити.
val fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_READ)
.build()
val account = GoogleSignIn.getAccountForExtension(this, fitnessOptions)
if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) {
GoogleSignIn.requestPermissions(
this,
GOOGLE_FIT_REQUEST_CODE,
account,
fitnessOptions
)
}
Якщо користувач відкликає дозвіл через налаштування Google-акаунта (не через Android Settings), hasPermissions() поверне false при наступному запуску. Це потрібно обробляти — без retry-логіки додаток просто перестане отримувати дані.
Читання даних: HistoryClient та SensorsClient
Історичні дані (кроки, калорії)
val readRequest = DataReadRequest.Builder()
.read(DataType.TYPE_STEP_COUNT_DELTA)
.aggregate(DataType.AGGREGATE_STEP_COUNT_DELTA)
.bucketByTime(1, TimeUnit.DAYS)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build()
Fitness.getHistoryClient(context, account)
.readData(readRequest)
.addOnSuccessListener { response ->
response.buckets.forEach { bucket ->
val steps = bucket.dataSets
.flatMap { it.dataPoints }
.sumOf { it.getValue(Field.FIELD_STEPS).asInt() }
}
}
bucketByTime — ключовий метод для агрегації. Без нього запит поверне кожен окремий крок від кожного джерела (телефон + годинник + браслет), що може бути кілька тисяч записів за день.
Дані в реальному часі
SensorsClient для підписки на живі дані:
Fitness.getSensorsClient(context, account)
.add(SensorRequest.Builder()
.setDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.setSamplingRate(10, TimeUnit.SECONDS)
.build(),
onDataPointListener
)
Цей підписник активний лише поки додаток на передньому плані. Для фонового трекінгу — RecordingClient.subscribe(), який Google Fit акумулює сам.
Дедуплікація даних з кількох джерел
Це реальна біль: у користувача Apple Watch (через Health) + Google Fit на Android телефоні + Samsung Health — кроки подвоюються і потроюються. Google Fit частково вирішує це через DataSet.getDataSources() — у кожної точки даних є джерело (DataSource). Фільтрація за DataSource.DEVICE дозволяє брати дані лише від конкретного пристрою.
Повністю надійної дедуплікації немає — це відома проблема екосистеми. Документуємо клієнту очікувані розбіжності та будуємо UI так, щоб користувач міг обрати пріоритетне джерело.
Міграція на Health Connect
Для нових пристроїв (Android 14+) Google Fit deprecated на рівні рекомендацій. Стратегія: перевіряємо доступність Health Connect, якщо доступний — використовуємо його, fallback на Google Fit для старих пристроїв:
val healthConnectAvailable = HealthConnectClient.getSdkStatus(context) ==
HealthConnectClient.SDK_AVAILABLE
Що входить в роботу
- Архітектурне проєктування: вибір підходу (Fitness API / REST / Health Connect)
- Реалізація OAuth-аутентифікації та обробка відкликання дозволів
- Розробка коду читання/запису даних (кроки, калорії, пульс тощо)
- Підтримка Wear OS за потреби
- Дедуплікація даних з кількох джерел
- Тестування на реальних пристроях з різними версіями Android
- Документація API та налаштувань OAuth
- Супровід при публікації в сторах (App Store Review Guidelines, Google Play Console)
Терміни
Базова інтеграція Google Fit (кроки, дистанція, калорії) — 4–7 робочих днів. З підтримкою Health Connect, дедуплікацією та Wear OS — 2–4 тижні. Зв'яжіться з нами для оцінки вашого проєкту — ми підберемо оптимальний підхід.
Google Fit API reference
Інтеграція з залізом: BLE, NFC, IoT та HomeKit у мобільних додатках
Коли задача — зв’язати смартфон з фізичним пристроєм, половина проблем знаходиться не в коді, а в прошивці заліза, характеристиках BLE-сервісів та затримках протоколу. Ми, як мобільні розробники, працюємо на стику з firmware-командою, і без розуміння стеку знизу вгору результат непередбачуваний. Ось чому ми завжди починаємо з HCI-логу та специфікації GATT — Apple Developer: Core Bluetooth Framework — це єдиний спосіб уникнути реверс-інжинірингу в польових умовах.
Чому BLE-інтеграція — найчастіша точка відмови?
Bluetooth Low Energy — основний протокол для носимих, медичних пристроїв, розумних замків та промислових датчиків. Core Bluetooth на iOS та BluetoothGatt на Android реалізують одну специфікацію, але поводяться по-різному в крайніх випадках. Статистика наших проектів: більше 70% звернень у підтримку по BLE пов’язані саме з низькорівневими помилками GATT, а не з логікою додатку.
| Сценарій |
iOS (Core Bluetooth) |
Android (BluetoothGatt) |
| Управління підключенням |
CBCentralManager потребує сильного посилання протягом всієї сесії; втрата об’єкта → розрив з’єднання |
disconnect() та close() викликаються окремо; close() без disconnect() → пристрій позначається зайнятим |
| Типова помилка |
Немає попередження при втраті посилання — з’єднання мовчки розривається |
Помилка 133 (GATT_ERROR) — виникає при переповненні черги GATT або некоректному закритті попередньої сесії |
| Сканування |
NSBluetoothAlwaysUsageDescription обов’язковий у Info.plist (з iOS 13); без нього сканування не стартує |
BLUETOOTH_SCAN потребує neverForLocation (Android 12+), інакше користувач бачить запит геолокації |
Що робити з помилкою 133 в Android?
Помилка 133 — найчастіша в Android BLE-розробці. Це не «щось пішло не так», а конкретний індикатор переповнення черги GATT або некоректного закриття попереднього з’єднання. Ми лікуємо її двома прийомами: використовуємо чергу операцій над GATT (write, read, notification subscribe строго послідовно через операційну чергу) та завжди викликаємо disconnect() перед close(). Наша черга GATT-операцій у 3 рази знижує кількість помилок ATT_INSUFFICIENT_RESOURCES порівняно з конкурентними запитами. MTU за замовчуванням — 23 байти. Запит на збільшення (MTU exchange) обов’язковий для передачі даних об’ємом понад 20 байт. На iOS MTU запитується автоматично при підключенні, на Android потрібно явно викликати requestMtu(). Без цього ви не зможете передати, наприклад, зображення або лог через характеристику.
NFC: CoreNFC та Android NFC API
iOS підтримує NFC-читання через CoreNFC з версії iOS 11, запис — з iOS 13. Важливе обмеження: сесія сканування активна лише поки живий об’єкт NFCNDEFReaderSession і показує системний UI. Фонове сканування доступне лише для додатків з entitlement com.apple.developer.nfc.readersession.formats і лише для ISO 14443 (банківські картки, паспорти) — і цей entitlement видається не всім. На Android все простіше: NfcAdapter.enableForegroundDispatch() ловить теги у foreground без системного UI. Фоновий запуск додатку по NFC-тегу реалізується через intent-filter з ACTION_NDEF_DISCOVERED. Порівняння платформ по NFC:
| Функція |
iOS (CoreNFC) |
Android (NfcAdapter) |
| Фонове читання |
Тільки з entitlement та ISO 14443 |
Через intent-filter ACTION_NDEF_DISCOVERED |
| Запис |
З iOS 13 (NDEF) |
З коробки (API 10+) |
| Сесія |
Триває до 5 хвилин з системним UI |
Необмежено у foreground, background по тегу |
| Запуск додатку |
Тільки foreground |
Автоматично при виявленні тегу |
HomeKit та Matter
HomeKit — екосистема Apple для розумного дому. Для інтеграції пристрій повинен мати MFi-сертифікацію (або працювати через Software Authentication для Matter). Мобільний додаток використовує HomeKit framework: HMHomeManager → HMHome → HMRoom → HMAccessory → HMService → HMCharacteristic. Matter (раніше CHIP) — крос-платформний стандарт, який підтримують Apple, Google, Amazon та Samsung. На iOS Matter-пристрої додаються через MTRDeviceController, на Android — через Google Home SDK або Matter SDK безпосередньо. Перевага Matter: один пристрій працює з HomeKit, Google Home та Alexa без перепрошивки, а конфігурація налаштовується в 4 рази швидше порівняно з власним HAP-протоколом.
| Параметр |
HomeKit |
Matter |
| Сертифікація |
MFi — апаратний чіп |
Software Authentication (ключі) |
| Підтримка платформ |
Тільки Apple |
Apple, Google, Amazon, Samsung |
| Додавання пристрою |
HMHomeManager |
MTRDeviceController / Google Home SDK |
| Протокол |
HAP (IP, BLE) |
IP-based (Wi-Fi, Thread) |
Для Flutter та React Native використовуємо flutter_blue_plus та react-native-ble-plx відповідно — обидва активно підтримуються і покривають 90% сценаріїв, але для роботи з GATT-нотифікаціями у background на Android все одно потрібен foreground service. Переконайтеся, що deep linking (Universal Links на iOS, App Links на Android) налаштовані для коректного пробудження додатку при скануванні NFC-тегу або отриманні push-повідомлення від IoT-пристрою. Вимоги ATT (App Tracking Transparency) для інтеграції з залізом зазвичай не застосовуються, але якщо додаток збирає анонімну аналітику — додайте запит. Отримайте консультацію нашого інженера — він розбере вашу специфікацію за 2 дні.
Як ми інтегруємо BLE та NFC?
-
Аналітика — отримуємо від firmware-команди повну специфікацію BLE GATT (список сервісів, характеристик, формати даних) або HCI-лог. Без цього розробка перетворюється на реверс-інжиніринг через nRF Connect або Wireshark over HCI.
-
Проектування — визначаємо архітектуру підключень: чергу GATT-операцій, фонові сервіси для Android, перепідключення при втраті зв’язку. Враховуємо MTU-узгодження та обробку помилок ATT_INSUFFICIENT_RESOURCES.
-
Реалізація — кодимо на Swift/Kotlin з урахуванням особливостей платформ (Universal Links, App Links, push-повідомлення через APNs/FCM для тригерів). Для захисту Android-коду використовуємо ProGuard / R8 (shrink).
-
Тестування — на реальних пристроях з першого дня. Емулятор BLE в симуляторах не відтворює edge cases перепідключення, втрати сигналу, зміни MTU. Використовуємо автоматизацію на базі XCTest та Espresso.
-
Деплой — завантаження в App Store Connect / Google Play Console з правильним code signing та provisioning profile. Для iOS — TestFlight, для Android — Firebase App Distribution.
Що входить в роботу (deliverables)
- Вихідний код мобільного додатку з інтеграцією BLE, NFC або IoT (Swift / Kotlin / Flutter / React Native)
- Документація по протоколу GATT (карта сервісів та характеристик)
- Навантажувальне тестування на 10+ реальних пристроях (помилка 133, перепідключення, MTU-узгодження)
- Аналіз та усунення edge cases (помилка ATT_INSUFFICIENT_RESOURCES, втрата з’єднання на фоні, конфлікт з background fetch)
- Інструкція зі збірки та деплою (code signing, TestFlight, Firebase App Distribution)
- Місяць підтримки після релізу
Строки та орієнтовна вартість
Проста інтеграція з одним BLE-периферійним пристроєм (показання + команди керування) — від 2 до 4 тижнів. Типова вартість такої задачі розраховується індивідуально, включаючи налагодження GATT-профілю та обробку edge cases. Повноцінний IoT-додаток з декількома типами пристроїв, firmware OTA-оновленнями та HomeKit-підтримкою — від 2 місяців. Вартість розраховується індивідуально під ваш проект.
Ми займаємося мобільною розробкою кілька років — досвід 45+ проектів з BLE/NFC/HomeKit. Наші інженери сертифіковані Apple та Google, а кожен етап роботи фіксується в issue tracker з прив’язкою до комітів. Ми гарантуємо прозорість процесу та дотримання строків. Використовуємо підхід «інженер клієнту»: без маркетингових пауз, з прямим доступом до розробника.
Закажіть оцінку — отримайте консультацію інженера з розбором вашої специфікації. Замовте інтеграцію під ключ: ми проаналізуємо HCI-лог, перевіримо GATT-характеристики та запропонуємо архітектуру за 2 дні.