Реализация фонового отслеживания геолокации в мобильном приложении
Фоновое отслеживание — это то место, где большинство команд получает первые жалобы от пользователей: «убивает батарею» или «перестаёт работать через час». Оба симптома — следствие неправильного выбора стратегии, а не самого факта фонового трекинга.
Почему это сложнее, чем кажется
iOS с версии 13 жёстко ограничивает фоновое выполнение. Даже с включённым Background Modes → Location updates система может приостановить приложение в режиме «suspended», и обновления геолокации перестанут поступать. Триггером для возобновления служит только значительное перемещение (Significant Location Change) или пересечение геозоны — если приложение не успело войти в «background task» до перехода в фон.
Android — своя картина. С версии 8.0 JobScheduler и Doze Mode ограничивают фоновые операции до одного раза в час при «неактивной» зарядке. На Android 10 появилось ACCESS_BACKGROUND_LOCATION как отдельное разрешение. На MIUI 12+, Samsung One UI 3+, OPPO ColorOS — ещё и производители добавляют собственные battery killers, которые убивают процесс раньше систематически.
Правильная архитектура для iOS
Три стратегии — выбираем по задаче:
1. Standard Location Updates — точные обновления каждые N метров. Нужен Foreground Service (фактически — приложение должно быть активным) или capability Background Location. Точность высокая, расход батареи высокий. Подходит для активного навигатора.
2. Significant Location Change Monitoring — startMonitoringSignificantLocationChanges(). Обновления при перемещении на ~500 метров или смене вышки. Очень экономичный. Работает даже при «terminated» состоянии — система запускает приложение в фоне. Подходит для трекинга доставки без требования к точности каждой секунды.
3. Visits Monitoring — startMonitoringVisits(). Определяет прибытие/отправление на основе анализа остановок. Минимальный расход батареи. Для аналитики перемещений, а не навигации.
Для реального курьерского трекинга комбинируем: при активном приложении — Standard Updates с desiredAccuracy = kCLLocationAccuracyBestForNavigation, при уходе в фон — переключаемся на Significant Location Change. Переключение в applicationDidEnterBackground / applicationWillEnterForeground.
func applicationDidEnterBackground(_ application: UIApplication) {
locationManager.stopUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()
}
func applicationWillEnterForeground(_ application: UIApplication) {
locationManager.stopMonitoringSignificantLocationChanges()
locationManager.startUpdatingLocation()
}
beginBackgroundTask(withName:expirationHandler:) даёт 30 секунд на завершение текущей операции при переходе в фон — используем для отправки последних точек на сервер.
Правильная архитектура для Android
Foreground Service с уведомлением — единственный надёжный способ. Без него на Android 8+ трекинг остановится в течение нескольких минут.
class LocationTrackingService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = buildTrackingNotification()
startForeground(NOTIF_ID, notification)
val request = LocationRequest.Builder(
Priority.PRIORITY_BALANCED_POWER_ACCURACY,
10_000L // каждые 10 секунд
)
.setMinUpdateDistanceMeters(20f)
.build()
fusedLocationClient.requestLocationUpdates(request, locationCallback, null)
return START_STICKY
}
}
START_STICKY гарантирует перезапуск сервиса системой при убийстве. Для устройств с агрессивным battery killer (Xiaomi/Samsung) добавляем BroadcastReceiver на BOOT_COMPLETED и MY_PACKAGE_REPLACED для автостарта.
Координаты буферизуем в Room локально — WorkManager с CONNECTED constraint отправляет их при наличии сети.
Flutter: два подхода
background_locator_2 — открытый пакет, использует platform-specific фоновые механизмы. Настройка через BackgroundLocator.registerLocationUpdate с LocationSettings. Работает через отдельный FlutterEngine в изолированном Dart-окружении.
flutter_background_geolocation (Transistor Software, платный) — более надёжный вариант с готовой обработкой iOS/Android батарейных ограничений, геозонами, автоматическим включением/выключением трекинга по расписанию.
Для продакшн-приложений с требованиями к надёжности выбираем платный пакет — $120 за лицензию окупаются за первую неделю поддержки.
Тестирование фонового трекинга
Самый частый баг — работает на дев-устройстве, не работает у части пользователей. Причина: тест-устройство не в Doze Mode, у разработчика нет MIUI. Чеклист для проверки:
- Тест с выключенным экраном на 30+ минут
- Тест с «Оптимизацией батареи» включённой
- Тест на Xiaomi с MIUI 12+, Samsung с One UI 4+
- Тест при переходе в авиарежим и обратно
- Проверка, что сервис перезапускается после reboot
Срок реализации: четыре-восемь дней — архитектура, реализация на нужных платформах, обработка edge cases, тестирование на реальных устройствах с разными прошивками.







