Зауважимо: коли база продуктів містить неточні дані, а формули КБЖУ дають помилку в 20%, користувачі швидко втрачають довіру. Ми стикалися з проектами, де через невірну інтерпретацію штрихкодів продукти потрапляли не в ті категорії, а синхронізація з HealthKit призводила до дублювання записів. Щоб цього уникнути, ми комбінуємо перевірені API (Open Food Facts, USDA), реалізуємо швидкий сканер штрихкодів за допомогою ML Kit та Vision, та інтегруємо розрахунки з системним HealthKit/Health Connect на рівні нативних фреймворків. Наш досвід — понад 10 проєктів з гарантією точності та стабільності.
На етапі проектування ми обираємо оптимальну базу продуктів. Open Food Facts обробляє запити в 2 рази швидше за USDA завдяки георозподіленим серверам, що економить бюджет на початковому етапі. Порівняємо основні джерела:
| Джерело |
Доступ |
Якість |
Особливості |
| Open Food Facts |
Безкоштовний REST |
Добра для глобальних брендів, пропуски для локальних |
3+ млн продуктів, відкрита ліцензія |
| USDA FoodData Central |
Безкоштовний API з ключем |
Детальна нутрієнтна інформація |
Орієнтований на США |
| Локальні бази (власні) |
Платний / краудсорсинг |
Контрольоване |
Підходить для регіональних продуктів |
Локальне кешування популярних продуктів (топ-1000) прискорює пошук. Промах — запит до API. Використовуємо Room/CoreData.
Як працює сканування штрихкоду?
Найшвидший спосіб додати продукт. На iOS — DataScannerViewController (iOS 16+, Vision framework) або AVCaptureMetadataOutput для старих версій. На Android — CameraX + ML Kit BarcodeScanning:
Приклад коду для Android
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_EAN_13, Barcode.FORMAT_EAN_8, Barcode.FORMAT_QR_CODE)
.build()
val scanner = BarcodeScanning.getClient(options)
val imageAnalysis = ImageAnalysis.Builder()
.setTargetResolution(Size(1280, 720))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
imageAnalysis.setAnalyzer(executor) { imageProxy ->
val mediaImage = imageProxy.image ?: return@setAnalyzer imageProxy.close()
val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
scanner.process(image)
.addOnSuccessListener { barcodes ->
barcodes.firstOrNull()?.rawValue?.let { barcode ->
onBarcodeDetected(barcode)
}
}
.addOnCompleteListener { imageProxy.close() }
}
Чому важлива інтеграція з HealthKit/Health Connect?
Дані про харчування, збережені в системних сховищах, доступні іншим додаткам і покращують користувацький досвід. На iOS записуємо dietaryEnergyConsumed, dietaryProtein тощо. На Android використовуємо NutritionRecord.
let calorieType = HKQuantityType(.dietaryEnergyConsumed)
let calorieSample = HKQuantitySample(
type: calorieType,
quantity: HKQuantity(unit: .kilocalorie(), doubleValue: 450),
start: mealTime,
end: mealTime
)
healthStore.save(calorieSample) { _, _ in }
val nutritionRecord = NutritionRecord(
startTime = mealTime,
startZoneOffset = ZoneOffset.systemDefault().getRules().getOffset(mealTime),
endTime = mealTime.plusMinutes(30),
endZoneOffset = ZoneOffset.systemDefault().getRules().getOffset(mealTime),
energy = Energy.kilocalories(450.0),
protein = Mass.grams(35.0),
totalCarbohydrate = Mass.grams(60.0),
totalFat = Mass.grams(15.0),
mealType = NutritionRecord.MEAL_TYPE_LUNCH
)
healthConnectClient.insertRecords(listOf(nutritionRecord))
Інтеграція потребує уваги до дозволів та правил App Store Review Guidelines (розділ 5.1.1).
Розрахунок КБЖУ: формули та точність
Базові формули:
- BMR (Mifflin-St Jeor): чоловіки:
10 × вага(кг) + 6.25 × зріст(см) − 5 × вік + 5; жінки: 10 × вага(кг) + 6.25 × зріст(см) − 5 × вік − 161. Mifflin-St Jeor equation.
- TDEE = BMR × коефіцієнт активності (1.2–1.9). Дефіцит/профіцит — цільові калорії мінус TDEE.
- Добова норма БЖУ: білок 1.6–2.2 г/кг, жири 0.8–1.2 г/кг, вуглеводи — решта від загального КБЖУ.
Перевіряйте коректність на тестових даних. Помилки в розрахунках — одна з частих проблем при самостійній реалізації.
Обробка відсутніх продуктів
Якщо продукт не знайдено в базі, можна додати його вручну або через краудсорсинг. Ми реалізуємо механізм зворотного зв'язку: користувач надсилає фото та дані, модератор перевіряє та доповнює базу. Автоматичне розпізнавання по фото за допомогою ML Kit ImageLabeling або Logmeal API допомагає прискорити процес, але точність залежить від якості зображення.
Що входить в роботу
Після підписання договору ми:
- Складаємо технічне завдання з описом усіх сутностей (продукти, прийоми їжі, користувачі) та потоку даних.
- Проектуємо архітектуру модулів (мережа, кеш, UI, Health інтеграція).
- Реалізуємо сканер штрихкодів, ручне введення, розрахунок КБЖУ та синхронізацію.
- Готуємо документацію для API та App Store/Google Play (політика конфіденційності, розділи інструкції).
- Надаємо доступ до репозиторію, CI/CD пайплайну та TestFlight/Google Play Console.
- Проводимо навчання команди замовника роботі з бекендом та метриками.
- Надаємо підтримку протягом 3 місяців після релізу (виправлення критичних багів, доопрацювання під нові ОС).
Розпізнавання їжі по фото (опціонально)
Для визначення продукту по знімку використовуємо ML Kit ImageLabeling (MobileNetV2) або спеціалізовані API. Порівняємо підходи:
| Метод |
Точність на стравах |
Швидкість |
Вартість |
Складність інтеграції |
| ML Kit ImageLabeling |
45–55% (загальні об'єкти) |
до 200 мс |
Безкоштовно |
Низька |
| Logmeal API |
92% на 1000+ страв |
800 мс |
$0.01/запит |
Середня |
| Власна модель (CoreML/TFLite) |
>95% при 50+ тис. зображень |
100–300 мс |
Витрати на навчання |
Висока |
Співставлення результату з базою продуктів — нечіткий пошук по імені категорії.
Етапи розробки трекера калорій
- Аналіз вимог — обираємо API бази продуктів, стек сканера, формули розрахунку.
- Проектування архітектури — модулі, кешування, синхронізація з HealthKit/Health Connect.
- Реалізація — сканер штрихкодів, розрахунок КБЖУ, інтеграція з зовнішніми сервісами.
- Тестування — unit-тести, UI-тести, інтеграційне на відповідність еталонним даним.
- Документація та деплой — підготовка метаданих, реліз в App Store / Google Play.
- Пост-релізна підтримка — моніторинг помилок, доопрацювання під нові версії ОС.
Терміни та вартість
Базовий додаток з ручним введенням, сканером та інтеграцією в HealthKit/Health Connect — 6–10 тижнів. З розпізнаванням їжі по фото та аналітикою — 3–5 місяців. Вартість розраховується індивідуально залежно від складності функцій. Залиште заявку на консультацію — ми підберемо оптимальне рішення під ваш бюджет.
Наш досвід
Понад кілька років на ринку мобільної розробки. Реалізували 10+ проектів з трекінгом здоров'я. Використовуємо сучасний стек: Swift 5.9, Kotlin, Jetpack Compose, Flutter. Сертифікати та ліцензії підтверджують кваліфікацію команди.
Зв'яжіться з нами, щоб обговорити деталі. Ми допоможемо впровадити трекінг калорій у ваш додаток. Замовте розробку — отримайте надійне рішення.
Інтеграція з залізом: 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 дні.