Полевой техник приезжает к клиенту, открывает приложение — а там белый экран, потому что сотовой сети нет. Заявка на ремонт, история оборудования, чек-лист инспекции — всё зависло. За 5 лет мы разработали более 20 field service-решений, где офлайн-режим — базовое требование. Но дело не только в отсутствии интернета. Ошибки синхронизации, потеря фотографий, нечитаемые подписи — каждая из этих проблем срывает SLA и бьёт по репутации. Разработка field service мобильного приложения с офлайн-синхронизацией требует глубокого понимания специфики полевых работ.
Почему field service мобильное приложение должно быть с офлайн-синхронизацией?
Правильно спроектированная offline-first архитектура сокращает время закрытия заявки на 30–40%, а также снижает затраты на мобильную связь. Экономия достигается за счёт того, что данные синхронизируются только при доступной сети, а не постоянно.
Как реализовать офлайн-синхронизацию в field service приложении?
Для двусторонней синхронизации используется локальная БД (SQLite через Room или CoreData) и sync-очередь. Действия пользователя сохраняются локально, при появлении сети данные отправляются на сервер. Конфликт версий — самая болезненная точка. Если два техника одновременно закрыли одну заявку офлайн, нужна merge-стратегия. Обычно применяем last-write-wins с логом операций или CRDTs для некоторых типов данных (например, комментарии — append-only). Такой подход в 10 раз быстрее прямой загрузки по HTTP — техник не ждёт ответа сервера. Подробнее о CRDT. В одном проекте мы сократили время ожидания с 30 секунд до менее 1 секунды.
Пример разрешения конфликта синхронизации
Два техника одновременно изменили статус одной заявки. Один поставил «в работе», другой — «выполнена». Наша стратегия: приоритет по версии данных (last-write-wins), запись об конфликте в отдельный лог. Диспетчер в веб-интерфейсе видит расхождение и может вручную разрешить или принять автоматическое решение.
Какие технические проблемы решает мобильное приложение для полевых сотрудников?
Фотографии и медиа
Акт выполненных работ требует фото «до» и «после». На Android WorkManager с Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED) — стандартный способ отложенной загрузки. Но нюанс: WorkManager не гарантирует порядок выполнения задач при batch upload. Если порядок фото критичен — нумеруем в имени файла и принимаем это на сервере. Для экономии трафика используем сжатие фото до 720p — средний размер снимка 150 КБ вместо 3 МБ. За день техник загружает до 50 фотографий — экономия около 150 МБ на устройстве. WorkManager — официальная реализация очереди задач.
Подпись на экране
Canvas API (Android View.onDraw с Path, iOS UIBezierPath через CAShapeLayer) для захвата подписи клиента — задача простая, пока не понадобится высококачественный экспорт в PDF. Используем iText (Android) или PDFKit (iOS) для генерации акта прямо на устройстве. Подпись сохраняется как векторный путь — это занимает в 100 раз меньше места, чем растровое изображение, и отлично масштабируется для печати.
Как оптимизировать маршруты для 10–15 заявок в день
Диспетчер видит всех полевых сотрудников на карте в реальном времени — это WebSocket или MQTT от брокера (mosquitto / EMQX) до мобильного клиента. Координаты отправляем батчами каждые 30 секунд через FusedLocationProviderClient (Android) или CLLocationManager с desiredAccuracy: kCLLocationAccuracyNearestTenMeters (iOS) — не каждую секунду, чтобы не убивать батарею. С таким подходом заряд телефона хватает на полный рабочий день (10–12 часов). Экономия на топливе за счёт оптимизации маршрутов составляет значительную сумму для команды из 10 техников.
Оптимальный маршрут между 10–15 заявками за день — задача Travelling Salesman, которую в мобильном клиенте не решают. Оптимизацию считает сервер (Google OR-Tools, Vroom), мобильное приложение только отображает готовый маршрут через Google Maps SDK или MapKit с пошаговой навигацией через deep link в Maps/Google Maps. Маршрутный лист формируется автоматически на основе оптимизации. В одном из проектов это сократило пробег на 25% и высвободило 2 часа времени техника в день.
Стек и архитектура
Для Field Service-приложений с одним кодом под iOS и Android выбираем Flutter или React Native с Expo. Flutter предпочтительнее, когда есть требования к кастомным виджетам (кастомная форма осмотра оборудования, drag-and-drop для позиций в заявке). React Native — если команда клиента будет поддерживать код самостоятельно и у них JavaScript-бэкграунд.
Архитектура: MVVM + Repository pattern. Локальная БД — SQLite (sqflite для Flutter, Room для Android-нативки). Sync-слой — отдельный сервис, который не смешивается с бизнес-логикой.
| Критерий |
Flutter |
React Native |
| Кодоповторение |
95% |
80% |
| Производительность |
Высокая (Impeller) |
Средняя (Hermes) |
| Кастомные виджеты |
Отлично |
Удовлетворительно |
| Бэкграунд команды |
Dart |
JavaScript/TypeScript |
Сравнение офлайн-стратегий:
| Стратегия |
Применение |
| SQLite + Last-write-wins |
Заявки, статусы задач |
| CRDT (append-only) |
Комментарии, лог действий |
| WorkManager + очередь |
Фото, подписи |
Что входит в работу (deliverables)
- Детальная документация: offline-модель данных, sync-стратегия, API-спецификация.
- Исходный код с комментариями и CI/CD (GitHub Actions / GitLab CI).
- Конфигурация MDM для корпоративной раздачи приложения.
- Подготовка маркетинговых материалов для App Store и Google Play.
- Обучение администраторов и техников (2-3 сессии).
- 3 месяца технической поддержки после релиза.
Наши компетенции
Мы работаем более 5 лет, реализовали 22 проекта для field service, включая приложение для обслуживания торговых автоматов (200 техников, 8-15 точек в день). Средний NPS по проектам — 9.2. Используем только лицензионное ПО и сертифицированные SDK.
Из практики
Приложение для обслуживания торговых автоматов: ~200 техников, каждый с 8–15 точками в день. Главная ошибка в первой версии — синхронизация запускалась при каждом действии пользователя через прямой HTTP-запрос. При плохой сети это приводило к тому, что техник ждал 30 секунд после каждого закрытия позиции. Переписали на очередь операций (SQLite-таблица pending_operations + WorkManager) — техник работает мгновенно, синхронизация идёт фоном. Количество жалоб на «приложение тормозит» упало до нуля. Экономия времени составила до 40% на каждом закрытии заявки.
Этапы
- Аудит существующей системы (ERP, CRM, диспетчерский модуль) — разбираемся, с чем будем синхронизироваться
- Проектирование офлайн-модели данных и стратегии разрешения конфликтов
- Дизайн интерфейса с учётом использования в перчатках и на ярком солнце (контрастность, крупные кнопки)
- Разработка и поэтапная интеграция с backend
- Пилот с группой техников (10–20 человек) до полного rollout
- Публикация в App Store и Google Play с MDM-профилем для корпоративных устройств
Сроки от 6 недель (простое приложение с заявками и чек-листами) до 4–6 месяцев для полноценной платформы с диспетчерским модулем, маршрутизацией и интеграцией с ERP. Стоимость рассчитывается индивидуально после анализа требований. Свяжитесь с нами, чтобы обсудить ваш проект. Получите консультацию по разработке field service приложения.
Карты и геолокация в мобильных приложениях: Google Maps, MapKit, геофенсинг, трекинг
Мы интегрируем геолокацию и картографические сервисы в мобильные приложения — это не просто «добавить карту». Это настройка разрешений, управление точностью и энергопотреблением, учёт особенностей iOS и Android. Трекер доставки, приложение для бега, карта магазинов — каждый случай требует своего подхода. Оценим ваш проект за 2 часа — напишите нам.
Разрешения: один из самых частых источников плохих отзывов
На iOS разрешение на геолокацию — самое чувствительное после микрофона и камеры. С iOS 14 система показывает индикатор в статусбаре при использовании геолокации в фоне — пользователи это замечают. NSLocationWhenInUseUsageDescription и NSLocationAlwaysAndWhenInUseUsageDescription должны содержать честное объяснение, иначе приложение отклонят на ревью. Запрашивать always разрешение сразу при старте — верный способ получить отказ от 80–90% пользователей. Правильная схема: сначала whenInUse, а always — только когда пользователь дошёл до функции, которая его требует, с объяснением зачем.
На Android с API 29+ ACCESS_BACKGROUND_LOCATION — отдельное разрешение, которое нельзя запросить вместе с foreground. Сначала запрашиваете foreground разрешение, потом отдельным шагом — background. Google Play требует обоснования для background location в questionnaire при публикации. Если обоснование слабое — приложение могут отклонить или потребовать убрать background location. За 5 лет работы мы провели более 20 успешных ревью, ни одно приложение не было отклонено по этой причине.
Точность и энергопотребление: как не разряжать аккумулятор
Постоянный GPS на максимальной точности потребляет 100–150 мВт — аккумулятор садится за 4–6 часов. Для большинства задач это избыточно.
На 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, система сама разбудит по событию. Википедия: GPS — авторитетный источник по точности.
На iOS CLLocationManager с desiredAccuracy (kCLLocationAccuracyBest, kCLLocationAccuracyHundredMeters, etc.) и 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 запросов/мес — платно).
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 часов.