Реалізація відслідження геолокації в реальному часі
Показати точку користувача на карті — п'ять строк коду. Передавати її на сервер кожні 5 секунд з мінімальним розрядом батареї, поки додаток у фоні, коректно обробляти втрату сигналу і переподключення — це зовсім інша історія.
Де звичайно виникають проблеми
Найчастіша помилка — не розділяти foreground і background режим відслідження. У foreground можна запускати CLLocationManager з desiredAccuracy: .bestForNavigation і distanceFilter: 5 — користувач активно дивиться на карту, батарея не в пріоритеті. В background той же режим убиває заряд за дві години і вызивает скарги.
На Android проблема гостріша: з версії 8.0 система агресивно убиває фонові процеси. LocationManager.requestLocationUpdates() з Service без startForeground() перестає отримувати обновлення через кілька хвилин на більшості прошивок. MIUI і One UI з налаштуванням «Оптимізація батареї» роблять це ще швидше — незалежно від налаштувань розробника.
Стек і архітектура
iOS
Для foreground — CLLocationManager з CLLocationAccuracy.best, callback в didUpdateLocations. Для background — allowsBackgroundLocationUpdates = true + capability «Background Modes → Location updates» в entitlements. Без цього флага фонові обновлення просто не приходять, і ні одна помилка в консоль не виводиться.
Координати буферизуємо локально (массив у пам'яті або Core Data) і відправляємо пачками через URLSession.shared.uploadTask кожні N секунд або при накопленні K точок. Одиночні HTTP-запити на кожне обновлення — антипаттерн: при поганому інтернеті черга зростає швидше, ніж розгребується.
Для економії батареї переключаємо режим залежно від контексту:
- Додаток активний:
desiredAccuracy = kCLLocationAccuracyBest,distanceFilter = 10 - Екран вимкнено:
desiredAccuracy = kCLLocationAccuracyHundredMeters,distanceFilter = 50 - Режим «довгий трекинг»: Significant Location Changes API замість постійного моніторингу
Android
FusedLocationProviderClient з play-services-location — єдиний правильний вибір для більшості проектів. Платформенний LocationManager дає менше контролю над слиянням джерел.
val request = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 5_000L)
.setMinUpdateDistanceMeters(10f)
.setWaitForAccurateLocation(false)
.build()
fusedLocationClient.requestLocationUpdates(
request,
locationCallback,
Looper.getMainLooper()
)
Фоновий трекинг — тільки через Foreground Service з повідомленням. Повідомлення не можна приховати за вимогами Android 9+. Сервіс регіструємо через startForeground() з FOREGROUND_SERVICE_TYPE_LOCATION (Android 10+).
При втраті з'єднання — Room як локальний буфер. WorkManager з Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED) відправляє накопичні точки при відновленні зв'язку.
Flutter
geolocator пакет для отримання позицій, background_locator_2 або flutter_background_geolocation (платний, але надійний) для фонового режиму. Координати через Isolate або FlutterEngine-background service передаємо в Dart-шар, зберігаємо в Isar або sqflite, синхронізуємо через Dio з retry-логікою.
Передача на сервер у реальному часі
Якщо потрібно показувати позицію іншим користувачам у реальному часі — HTTP-поллинг не підходить. WebSocket (socket.io або нативний URLSessionWebSocketTask / OkHttp WebSocket) або MQTT (легше по трафіку, краще для нестабільного з'єднання). Для Flutter — mqtt_client пакет.
Топік MQTT вида tracking/{userId}/location, QoS 1 для гарантії доставки без підтвердження прочитання. Сервер (Node.js + mosquitto broker або AWS IoT Core) рассилає обновлення підписникам.
Процес роботи
Проектування: режими трекинга, інтервали, буферизація, протокол передачі. Реалізація iOS та/або Android з коректним управлінням жизненным циклом сервісу. Реалізація серверної частини прийому координат (якщо потрібно). Тестування на реальних поїздках, перевірка поведінки при переключенні мережа/без мережі.
Строк: три-вісім днів залежно від платформ, наявності серверної частини і вимог до real-time відображення.







