Реалізація GPS-трекінгу транспорту в мобільному IoT-додатку
GPS-трекер на транспортному засобі надсилає пакет кожні 10 секунд. Це 8640 записів на добу на один об'єкт. При 50 транспортних засобах — 432 000 точок на день. Ми вирішуємо задачу відображення поточної позиції в реальному часі та перегляду історії без гальм за допомогою оптимізованої клієнт-серверної архітектури на Flutter/React Native. Ключова складність — не просто отримати координати, а забезпечити плавне відображення на карті без лагів при високій частоті оновлень. Ми реалізуємо WebSocket-з'єднання для миттєвої доставки даних, дискретизацію маршрутів за алгоритмом Дугласа-Пекера та кластеризацію маркерів для роботи з флотом будь-якого розміру. Такий підхід дозволяє економити до 30% бюджету порівняно з паралельною розробкою двох нативних додатків.
Як забезпечити real-time оновлення позиції?
Мобільний додаток отримує дані через WebSocket, а не polling. Різниця відчутна:
| Параметр |
Polling (HTTP) |
WebSocket (Server-Sent Events) |
| Затримка |
від 10 секунд |
1–2 секунди |
| Навантаження на сервер |
N запитів на секунду |
одне з'єднання |
| Трафік |
заголовки + тіло при кожному запиті |
мінімальний оверхед |
Ми використовуємо WebSocket з бінарним протоколом (наприклад, WebSocket в Dart/TypeScript). Сервер пушить оновлення відразу після отримання пакета від трекера, затримка мінімальна. WebSocket знижує затримку в 5–10 разів порівняно з polling, що критично для екстрених алертів.
Скільки точок можна відображати на карті без втрати продуктивності?
Історія за день — від 5 000 до 15 000 точок. Рендерити їх усі — лаг на слабких пристроях. Рішення: дискретизація за алгоритмом Дугласа-Пекера (Douglas-Peucker) на сервері. При zoom 10 достатньо ~500 точок, при zoom 17 — повна деталізація. Клієнт запитує трек з параметром зуму.
Для відображення великої кількості транспортних засобів використовуємо кластеризацію: маркери групуються при віддаленні, показуючи лічильник. На Flutter використовуємо Supercluster, на нативних платформах — GMSMarkerClusterer (Android) / CMClusterAnnotationView (iOS).
Отримання даних від IoT-трекерів
Апаратні GPS-трекери (Teltonika FMB140, Queclink GV620, Concox GT06N) надсилають дані по TCP/UDP на сервер телематики. Мобільний додаток не взаємодіє з трекером безпосередньо — це завдання сервера. Клієнт отримує оброблений потік через WebSocket або REST API.
Різниця між WebSocket і polling у цьому сценарії відчутна. Polling кожні 10 секунд на 50 об'єктів = постійні HTTP-запити, overhead на handshake, затримка до 10 секунд. WebSocket з серверними подіями: сервер пушить оновлення відразу при отриманні нового пакета від трекера, затримка — 1–2 секунди, немає зайвих запитів.
Відображення на карті
Кожен трекер — маркер на карті з іконкою транспортного засобу, напрямком руху (bearing) і статусом. Три ключові моменти:
Bearing-анімація. Трекер змінює напрямок — іконка повертається плавно. На Android: ObjectAnimator.ofFloat(marker, "rotation", oldBearing, newBearing).setDuration(500). На iOS: CABasicAnimation(keyPath: "transform.rotation.z") на шарі маркера.
Плавне переміщення. Маркер рухається до нової координати без стрибків. Використовуємо ValueAnimator з LatLngInterpolator на Android; на iOS — CABasicAnimation з CGPoint interpolation через MKAnnotationView.coordinate.
Кластеризація. При zoom нижче 12 окремі маркери зливаються. Обираємо кластеризатор під платформу: Supercluster (Flutter), GMSMarkerClusterer (Android) або CMClusterAnnotationView (iOS). Кластер показує лічильник транспортних засобів всередині.
Історія треку
Історія за день — від 5 000 до 15 000 точок. Малювати Polyline з 10 000 точок напряму — лаг при render. Два підходи:
Дискретизація Дугласа-Пекера на сервері. При запиті історії сервер спрощує трек з епсілон-параметром, залежним від рівня зуму: при zoom 10 достатньо ~500 точок, при zoom 17 — повна деталізація. Клієнт запитує трек з параметром зуму.
LOD при прокручуванні. Завантажуємо трек за вибраний період шматками при скролі часового слайдера. Поза видимою областю — не рендеримо.
Зупинки в треку обчислюються на сервері: кластер точок з speed < 5 км/год довше N хвилин = зупинка. Адреса — reverse geocoding через Google Maps Geocoding API або Nominatim, кешується в базі.
Швидкість та алерти
Перевищення швидкісного режиму, різке гальмування, різке прискорення — обчислюється з сирих даних телематики (speed, accelerometer якщо трекер підтримує). Алерт надсилається через FCM/APNs push з high priority. У додатку — UNNotificationCategory з action «Відкрити карту» для iOS, PendingIntent з deep link для Android.
Геозонні алерти: в'їзд/виїзд із зони. Перевірка ST_Contains в PostGIS при кожному вхідному пакеті — сотні тисяч перевірок на добу при великому флоті. Оптимізація: просторовий індекс GIST на geometry колонці, R-tree на геозонах в пам'яті (GeoHashing для первинної фільтрації).
Що робити, якщо кількість геозон перевищує 1000?
При великій кількості геозон продуктивність перевірки критична. Ми використовуємо наступний підхід:
| Кількість геозон |
Час перевірки ST_Contains |
Оптимізація |
| 100 |
0.5 мс |
без індексу |
| 1000 |
5 мс |
GIST індекс |
| 10000 |
50 мс |
R-tree + GeoHash |
Такий стек дозволяє обробляти до 10 000 геозон із затримкою менше 50 мс на одну перевірку.
З практики: трекінг цементовозів
Подробиці кейсу
35 машин, інтервал запису 15 сек, історія на 90 днів. Проблема при перегляді історії за місяць: Polyline з 720 000 точок вішав UI на 4–5 секунд на Samsung A32. Після впровадження динамічної дискретизації (200 точок при zoom 10, 5000 при zoom 16) — відображення стало плавним.
Що входить у роботу над проєктом
- Розробка серверного API телематики (якщо потрібно)
- Інтеграція з популярними трекерами (Teltonika, Queclink, Concox)
- Мобільний додаток на Flutter/React Native з підтримкою iOS та Android
- Налаштування WebSocket-з'єднання та push-сповіщень (FCM/APNs)
- Реалізація геозон та алертів
- Документація по API та навчання команди замовника
- Технічна підтримка протягом 1 місяця після запуску
Терміни та вартість
Терміни реалізації: від 2 до 6 тижнів залежно від складності інтеграції та вимог до функціоналу. Вартість розраховується індивідуально після аналізу вашого проєкту. Ми гарантуємо якість та дотримання термінів завдяки досвіду 5+ років та понад 20 успішних проєктів у сфері IoT та телематики. Середня вартість володіння таким рішенням на 5 років нижча на 40% за рахунок єдиної кодової бази.
Отримайте консультацію щодо вашого проєкту — ми оцінимо складність інтеграції та запропонуємо оптимальне рішення. Замовте розробку додатку для GPS-трекінгу з гарантією якості.
Карти та геолокація в мобільних додатках: Google Maps, MapKit, геофенсинг, трекінг
Ми інтегруємо геолокацію та картографічні сервіси в мобільні додатки — це не просто «додати карту». Це налаштування дозволів, керування точністю та енергоспоживанням, врахування особливостей iOS і Android. Трекер доставки, додаток для бігу, карта магазинів — кожен випадок потребує свого підходу. Замовте консультацію — оцінимо ваш проєкт за 2 години.
Дозволи: одне з найчастіших джерел поганих відгуків
На iOS дозвіл на геолокацію — найчутливіший після мікрофона та камери. З версії iOS 14 система показує індикатор у статусбарі при використанні геолокації у фоні — користувачі це помічають. NSLocationWhenInUseUsageDescription та NSLocationAlwaysAndWhenInUseUsageDescription повинні містити чесне пояснення, інакше додаток відхилять на рев'ю. Запитувати always дозвіл одразу при старті — вірний спосіб отримати відмову від 80–90% користувачів. Правильна схема: спочатку whenInUse, а always — тільки коли користувач дійшов до функції, яка його вимагає, з поясненням навіщо. App Store Review Guidelines (Section 5.1) вимагають чіткого обґрунтування.
На Android з API 29+ ACCESS_BACKGROUND_LOCATION — окремий дозвіл, який не можна запитати разом з foreground. Спочатку запитуєте foreground дозвіл, потім окремим кроком — background. Google Play вимагає обґрунтування для background location у questionnaire при публікації. Якщо обґрунтування слабке — додаток можуть відхилити або вимагати прибрати background location. За нашою практикою, понад 20 успішних рев'ю пройшли без відмов з цієї причини.
Як збалансувати точність та енергоспоживання?
Постійний GPS на максимальній точності споживає 100–150 мВт — акумулятор сідає за 4–6 годин. Для більшості завдань це надмірно. Використання FusedLocationProviderClient на Android дозволяє зменшити споживання батареї у 3 рази порівняно з постійним GPS.
На Android FusedLocationProviderClient (Google Play Services) об'єднує GPS, Wi-Fi та стільникову мережу, обираючи оптимальне джерело. LocationRequest.Builder з пріоритетами:
-
PRIORITY_HIGH_ACCURACY — GPS увімкнено, для навігації
-
PRIORITY_BALANCED_POWER_ACCURACY — точність ~100 метрів, Wi-Fi + стільникова
-
PRIORITY_LOW_POWER — точність ~10 км, тільки стільникова
-
PRIORITY_PASSIVE — координати від інших додатків, без активного запиту
Для трекера пробіжки в активному режимі — HIGH_ACCURACY з інтервалом 2–5 секунд. Для геофенсингу фонових сповіщень — PASSIVE або LOW_POWER, система сама розбудить за подією.
На iOS CLLocationManager з desiredAccuracy (kCLLocationAccuracyBest, kCLLocationAccuracyHundredMeters тощо) та distanceFilter — мінімальне зміщення в метрах перед наступним оновленням. Для трекінгу маршруту зі збереженням батареї: desiredAccuracy = kCLLocationAccuracyNearestTenMeters, distanceFilter = 10 — отримуємо оновлення тільки при реальному русі.
Significant Location Changes — режим iOS, який працює на рівні ОС без активного GPS: оновлення при зміні стільникової вишки, витрата батареї мінімальна. Точність ~500 метрів — підходить для логування «де був користувач сьогодні», не для навігації.
Як обрати картографічний SDK? Порівняльний аналіз
| SDK |
Платформа |
Офлайн-карти |
Кастомний стиль |
Без Google Services |
| Google Maps SDK |
iOS/Android |
Ні (тільки Maps API) |
Так (Cloud-based) |
Ні |
| MapKit |
iOS |
Ні |
Обмежено |
Так |
| Mapbox Maps |
iOS/Android |
Так |
Повністю |
Так |
| HERE Maps |
iOS/Android |
Так |
Так |
Так |
| OpenStreetMap + MapLibre |
iOS/Android/Flutter |
Так |
Повністю |
Так |
Google Maps SDK — вибір за замовчуванням для більшості проєктів: знайомий UI, хороша документація, Directions API, Places Autocomplete. Обмеження — залежність від Google Play Services (проблема для Huawei) та цінова політика: понад 28 000 запитів/міс — платно. Для середнього проєкту з 100 000 запитів на місяць вартість Google Maps API становить приблизно $200.
Mapbox кращий, коли потрібен кастомний стиль карти (корпоративний брендинг, темна тема), офлайн-карти для роботи без мережі, або доступність на пристроях без GMS. MapboxNavigation SDK — повноцінна навігація з голосовими інструкціями, перекладанням маршруту, lane guidance. Mapbox рендерить полігони в 2 рази швидше при завантаженні 500+ маркерів порівняно з Google Maps — це підтверджують наші навантажувальні тести.
Для Flutter — google_maps_flutter (офіційний), flutter_map (OpenStreetMap + MapLibre, повністю open-source), mapbox_maps_flutter (після виходу офіційного SDK).
Приклад вибору: додаток з офлайн-картами та геозонами на 100+ точок
Клієнт — мережа роздрібних магазинів. Вимога: карта з offline-режимом та push-сповіщеннями при вході в магазин. Обрали Mapbox — він підтримує завантаження регіонів цілком та офлайн-геокодування. Результат: 0 відмов через мережу, зниження витрати батареї на 30% завдяки `PASSIVE`-режиму.
Геофенсинг: причини затримки спрацювання
Геофенсинг — запуск події при вході/виході з географічної зони (коло заданого радіусу). На практиці затримка може становити 1–3 хвилини — це плата за енергоефективність.
На Android — GeofencingClient з Google Location Services. Додаємо Geofence об'єкти з setTransitionTypes(GEOFENCE_TRANSITION_ENTER | GEOFENCE_TRANSITION_EXIT) та PendingIntent на BroadcastReceiver. Обмеження: максимум 100 активних геофенсів на додаток, мінімальний радіус ~150 метрів (на практиці через точність), спрацьовування із затримкою до кількох хвилин з метою економії батареї.
На iOS — CLCircularRegion + CLLocationManager.startMonitoring(for:). Ліміт: 20 регіонів на додаток. ОС керує коли перевіряти — розробник не контролює затримку. Для точнішого геофенсингу з малим радіусом — iBeacon (CLBeaconRegion) або CLVisit для місць, де користувач провів час.
Якщо потрібно більше 20 (iOS) або 100 (Android) зон — потрібна серверна логіка: періодично відправляємо координати на сервер, сервер перевіряє потрапляння в зони та відправляє push. Менш точно за часом, але масштабується на тисячі зон.
Трекінг маршрутів і фонова геолокація
Трекінг маршруту пробіжки або маршруту кур'єра у фоні — технічно різні завдання.
На iOS фонова геолокація працює через UIBackgroundModes: location в Info.plist. Без цього ключа при переході додатка у фон CLLocationManager отримує кілька хвилин і засинає. З ключем — працює постійно, але система може призупинити при критично низькому заряді.
Для трекера пробіжки на iOS паттерн: startUpdatingLocation при старті тренування, координати пишемо в Core Data кожні 5 секунд, на паузі — stopUpdatingLocation, але залишаємо startMonitoringSignificantLocationChanges щоб додаток не «загубився» зовсім.
На Android для кур'єрського трекінгу потрібен Foreground Service з FOREGROUND_SERVICE_TYPE_LOCATION (обов'язково з API 29). Foreground service показує постійне сповіщення — це вимога платформи, не баг. Без нього Android Doze вб'є оновлення геолокації. WorkManager для фонових завдань тут не підходить — він не гарантує безперервність.
Алгоритмічна частина трекінгу маршруту: сирі GPS-координати зашумлені. Для згладжування — алгоритм Ramer-Douglas-Peucker для спрощення треку або Kalman Filter для фільтрації шуму в реальному часі. Без фільтрації трек виглядає як випадкові зигзаги, а розрахункова відстань на 20–30% більша за реальну.
Як ми впроваджуємо карти та геолокацію: покроковий процес
- Аналіз сценаріїв — визначаємо, чи потрібен foreground/background, точність, кількість геозон, необхідність офлайн-режиму.
- Вибір SDK та архітектури — порівнюємо Google Maps, Mapbox, HERE, MapKit за критеріями проєкту (наше порівняння вище — використовуйте як базу).
- Інтеграція та налаштування дозволів — прописуємо Info.plist / AndroidManifest.xml, тестуємо рев'ю-чеки (App Store Review Guidelines Section 4.2/5.1, Google Play policy).
- Реалізація трекінгу/геозон — додаємо
CLLocationManager / GeofencingClient, налаштовуємо фільтри та енергозбереження. Для отримання безкоштовної консультації напишіть нам.
- Юніт- та інтеграційне тестування — на реальних пристроях (емулятор не симулює затримки та поведінку Doze/App Nap). Перевіряємо не менше 50 сценаріїв.
- Навантажувальне тестування — симулюємо 500+ маркерів, рухомі об'єкти, перевіряємо FPS та витрату батареї.
- Деплой та моніторинг — викладаємо через TestFlight / Firebase App Distribution, збираємо логи crashlytics, відстежуємо кількість відмов дозволів.
Терміни та що входить у роботу
| Етап |
Термін |
Склад deliverables |
| Базова інтеграція карти з маркерами та пошуком |
1–2 тижні |
Вихідний код (Swift/Kotlin/Dart), документація API, інструкція зі збірки |
| Геофенсинг з push-сповіщеннями |
2–3 тижні |
Код геозон, налаштування FCM/APNs, тестові зони, звіт по затримках |
| Повноцінний трекінг маршрутів (фон, згладжування, серверна синхр.) |
4–6 тижнів |
Код з Kalman фільтром, серверна частина (опціонально), моніторинг батареї |
Що ви отримаєте в будь-якому випадку:
- Вихідний код з коментарями (Swift, Kotlin, Dart, TypeScript)
- Інтеграцію з вашим бекендом (REST/GraphQL/WebSocket)
- Підтримку 1 місяць після здачі (виправлення багів, допомога з рев'ю сторів)
- Інструкцію з публікації в App Store та Google Play (включаючи обґрунтування для background location)
- Сертифікати code signing, provisioning profiles, ключі Google Maps/Mapbox
Наші компетенції: 10+ років досвіду в мобільній розробці, 50+ проєктів з геолокацією, сертифіковані розробники Apple та Google (Google Associate Android Developer). Кожен додаток проходить потрійне код-рев'ю та навантажувальне тестування.
Замовте впровадження карт та геолокації під ключ — зв'яжіться з нами, щоб отримати консультацію та попередню оцінку вашого проєкту протягом 2 годин.