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

Точність GPS і стабільний запис тренування у фоновому режимі — часта проблема під час розробки мобільних застосунків для спорту. Ми розробляємо модуль трекінгу під ключ, який вирішує ці завдання на iOS та Android. Наша команда бере на себе весь цикл — від збору даних до інтеграції з HealthKit і Health Connect, забезпечуючи надійну роботу та подальшу підтримку.

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

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

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

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

При розробці трекера тренувань ключова проблема — точність 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 місяці.

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

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

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

  • Розробка мобільного додатка для компанії FEEDME
    Розробка мобільного додатка для компанії FEEDME
    1009
  • Розробка мобільного додатку для компанії XOOMER
    Розробка мобільного додатку для компанії XOOMER
    902
  • Розробка мобільного додатку для компанії RHL
    Розробка мобільного додатку для компанії RHL
    1331
  • Розробка мобільного додатку для компанії ZIPPY
    Розробка мобільного додатку для компанії ZIPPY
    1179
  • Розробка мобільного додатку для компанії Affhome
    Розробка мобільного додатку для компанії Affhome
    1106
  • Розробка мобільного додатку для компанії FLAVORS
    Розробка мобільного додатку для компанії FLAVORS
    713