Трекінг тренувань у мобільному додатку: GPS, пульс, BLE

При розробці трекера тренувань ключова проблема — точність GPS і безперервність запису у фоновому режимі. Навіть на флагманах сирий GPS дає шум 5–15 метрів, а система може вбити процес додатка через 15 секунд після згортання. Без правильної фільтрації трек рясніє «зигзагами», а втрата даних при краш

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Трекінг тренувань у мобільному додатку: GPS, пульс, BLE
Середній
~3-5 днів

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

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    894
  • 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

При розробці трекера тренувань ключова проблема — точність GPS і безперервність запису у фоновому режимі. Навіть на флагманах сирий GPS дає шум 5–15 метрів, а система може вбити процес додатка через 15 секунд після згортання. Без правильної фільтрації трек рясніє «зигзагами», а втрата даних при краші — втрата мотивації користувача. Додатково, на Android без Foreground Service додаток може бути вбито будь-якої миті, а на iOS навіть з дозволом «Always» система може призупиняти оновлення при низькому заряді батареї. Особливо складний випадок, коли спортсмен біжить у лісосмузі — GPS-сигнал слабшає і трек починає «плавати» без Kalman-фільтра.

Ми пропонуємо модуль трекінгу під ключ, який вирішує ці задачі: від збору даних до інтеграції з платформенними сховищами здоров'я. Наша команда з 5-річним досвідом у мобільній розробці гарантує стабільність запису на iOS і Android. За 3–5 тижнів ви отримуєте готовий трекер бігу з GPS, дистанцією та темпом. Для складніших завдань — з ЧСС, BLE-датчиками та кількома типами активностей — термін складає 2–4 місяці. Ми використовуємо перевірені алгоритми та конфігурації, які показали високу точність у більш ніж 15 комерційних проєктах.

Тепер детально розберемо, як ми забезпечуємо точність треку, роботу у фоні та інтеграцію з носимими пристроями.

Архітектура сесії тренування

Центральний елемент — WorkoutSession (або як ви її називаєте), кінцевий автомат зі станами:

Idle → Preparing → Active → Paused → Active → Finishing → Saved 

Переходи тригеряться користувачем (кнопки Start/Pause/Finish) і системою (втрата GPS, розряд батареї). Весь стан зберігається в WorkoutRepository, персистується через Room (Android) або CoreData/SQLite (iOS) після кожного оновлення — щоб при краші відновити сесію.

@Entity data class WorkoutPoint( @PrimaryKey(autoGenerate = true) val id: Long = 0, val sessionId: String, val timestamp: Long, val latitude: Double?, val longitude: Double?, val altitude: Double?, val heartRate: Int?, val speed: Double?, val distance: Double ) 

Кожні 5 секунд вставляємо новий запис у БД. При завершенні тренування — агрегуємо все в WorkoutSummary. Проміжні точки не видаляємо — вони потрібні для побудови треку.

Як гарантувати точність GPS-треку?

Як фільтрувати GPS-шум?

Сирі GPS-дані містять шум ±5–15 м. На маршруті це візуально виглядає як «зигзаги» замість прямого відрізка. Фільтруємо через Kalman-фільтр — він точніший, ніж ковзне середнє, і адаптується до динаміки руху. На прямих ділянках Kalman дає точність ±2 м проти ±5 м у ковзного середнього; на поворотах — ±4 м проти ±10 м. У 80% проєктів ми використовуємо саме Kalman-фільтр — він дає приріст точності на 60% на поворотах.

Для мобільної розробки не потрібно реалізовувати Kalman з нуля. На Android — FusedLocationProviderClient уже застосовує внутрішню фільтрацію. На iOS — CLLocationManager з kCLLocationAccuracyBestForNavigation використовує сенсорний fusion. Додатково: відкидаємо точки з horizontalAccuracy > 20 м.

Кроки налаштування фільтрації:

  1. Ініціалізуйте LocationManager з точністю kCLLocationAccuracyBestForNavigation (iOS) або створіть FusedLocationProviderClient (Android).
  2. Встановіть мінімальну відстань оновлення — 5 м.
  3. У callback відкидайте точки з horizontalAccuracy > 20.
  4. Застосуйте Kalman-фільтр для згладжування решти точок.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last, location.horizontalAccuracy <= 20, location.horizontalAccuracy >= 0 else { return } if let previous = lastLocation { let segment = location.distance(from: previous) totalDistance += segment } lastLocation = location trackPoints.append(location) } 

Розрахунок дистанції та темпу

Дистанція — сума відстаней між послідовними GPS-точками (CLLocation.distance(from:) на iOS, Location.distanceTo() на Android). Темп (хв/км) = 1000 / швидкість (м/с) / 60. Швидкість беремо з CLLocation.speed / Location.speed — вони обчислюються за доплерівським зсувом, точніше ніж різниця координат.

При speed < 0 (немає достовірних даних) — використовуємо швидкість з координат.

Чому важливий фоновий режим?

Без фонової роботи GPS вимикається через 15 секунд після згортання додатка. На iOS додаємо UIBackgroundModes = location в Info.plist і запитуємо дозвіл «Always». На Android запускаємо Foreground Service з повідомленням — інакше система вб'є процес при нестачі пам'яті.

class WorkoutTrackingService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { val notification = buildTrackingNotification() startForeground(NOTIFICATION_ID, notification) startLocationUpdates() return START_STICKY } } 

START_STICKY — система перезапустить сервіс, якщо вб'є процес, з null інтентом. Обробляємо null і відновлюємо стан з Room.

Чек-лист налаштування фонового режиму для iOS і Android

iOS:

  • Додати UIBackgroundModes = location в Info.plist
  • Запросити дозвіл на завжди (requestAlwaysAuthorization)
  • Використовувати allowsBackgroundLocationUpdates = true
  • Для ініціації сесії використовувати CLMonitor (починаючи з iOS 17)

Android:

  • Оголосити FOREGROUND_SERVICE_LOCATION дозвіл (з API 29)
  • Запустити startForeground з каналом повідомлення
  • Використовувати START_STICKY для перезапуску
  • Обробляти null Intent в onStartCommand

Порівняння методів фільтрації GPS

Метод Точність на прямій Точність на поворотах Обчислювальна складність
Ковзне середнє ±5 м ±10 м Низька
Kalman-фільтр ±2 м ±4 м Середня
Системний FusedLocation ±3 м ±5 м Низька (вбудований)

Порівняння фонової роботи iOS vs Android

Платформа Механізм Вимоги Надійність
iOS Background Location Permission «Always», UIBackgroundModes Висока, але може призупинити при низькому заряді
Android Foreground Service Notification, START_STICKY Дуже висока, перезапуск при вбивстві

Інтеграція з носимими пристроями

ЧСС від Apple Watch — через HKWorkoutBuilder на iOS (Watch автоматично додає семпли). На Android — Wear OS через HealthServicesClient або Bluetooth GATT з профілем Heart Rate (UUID 0x180D).

Bluetooth GATT для зовнішніх датчиків (нагрудний пояс Polar H10, Wahoo TICKR):

val hrServiceUUID = UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb") val hrCharacteristicUUID = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb") override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { if (characteristic.uuid == hrCharacteristicUUID) { val flag = characteristic.properties val format = if (flag and 0x01 != 0) { BluetoothGattCharacteristic.FORMAT_UINT16 } else { BluetoothGattCharacteristic.FORMAT_UINT8 } val heartRate = characteristic.getIntValue(format, 1) ?: 0 onHeartRateReceived(heartRate) } } 

Збереження в HealthKit / Health Connect

Після завершення тренування записуємо повний HKWorkout (iOS) або ExerciseSessionRecord (Android) з усіма вкладеними метриками: дистанція, ЧСС, маршрут. На iOS — HKWorkoutRouteBuilder для GPS-треку. Користувач повинен бачити тренування в системному додатку «Здоров'я» або Health Connect. Health Connect API доступний на Android 10+.

Що входить в роботу

  • Архітектурна документація та діаграми станів сесії
  • Вихідний код з коментарями та unit-тестами
  • Інтеграція з обраними датчиками (BLE, носимі)
  • Налаштування фонового режиму та повідомлень
  • Інструкція з деплою в App Store / Google Play
  • Підтримка протягом 2 місяців після здачі

Терміни

Базовий трекер бігу з GPS, дистанцією та темпом — 3–5 тижнів. Повний трекер з ЧСС, BLE-датчиками, кількома типами активностей, експортом GPX та інтеграцією в платформові сховища — 2–4 місяці.

Зв'яжіться з нами для оцінки вашого проєкту — ми підберемо оптимальне рішення під ваш стек і бюджет. Замовте розробку трекінгу під ключ і отримайте стабільний модуль з гарантією якості.