Разработка мобильных приложений на платформе 1С открывает широкие возможности, среди которых особое место занимает работа с геоданными. Однако разработчики часто сталкиваются с проблемой: метод получения координат по провайдеру "gps" возвращает пустые значения (Неопределено) или вызывает исключения, в то время как получение данных через "network" работает стабильно. При этом сторонние карты (например, Яндекс.Карты, Google Maps или 2ГИС) мгновенно определяют положение устройства даже в глубине здания.
В этой статье мы подробно разберем физические и программные причины такого поведения систем геопозиционирования, проанализируем внутреннее устройство работы служб геолокации в мобильной платформе 1С и рассмотрим наиболее надежные практики написания кода для стабильного определения координат в любых условиях.
Для понимания сути проблемы первым делом необходимо разграничить физические принципы работы различных датчиков. Спутниковая система позиционирования (GPS/ГЛОНАСС) работает напрямую с космическими аппаратами. Сигнал от спутников передается на сверхвысоких частотах и обладает крайне малой мощностью. Он легко ослабляется и полностью блокируется физическими препятствиями:
Находясь внутри кирпичного или монолитного здания, мобильное устройство физически не способно «услышать» сигналы достаточного количества спутников (минимум 4 спутника для определения трехмерных координат). Именно поэтому, как только автор темы протестировал устройство на открытом воздухе, провайдер "gps" мгновенно вернул актуальные данные.
Кроме того, важную роль играет технология A-GPS (Assisted GPS). При «холодном старте» (первом включении GPS-приемника после долгого простоя) устройству требуется загрузить информацию об орбитах спутников (альманах и эфемериды). Напрямую со спутников этот процесс занимает до 12.5 минут в идеальных условиях. Технология A-GPS позволяет скачать эти данные за секунды через мобильный интернет или Wi-Fi. Если тестируемый планшет или смартфон не имеет SIM-карты и отключен от сети, холодный старт GPS на улице может занять очень много времени, а в помещении гарантированно завершится неудачей.
Многие разработчики задаются вопросом: «Почему навигаторы на моем телефоне определяют местоположение даже в подвале, а 1С — нет?».
Секрет кроется в использовании высокоуровневых системных служб операционных систем. Современные мобильные ОС используют гибридные провайдеры (например, Fused Location Provider API на Android и CoreLocation на iOS). Эти службы работают комплексно:
Мобильная платформа 1С при явном указании провайдера "gps" напрямую задействует аппаратный GPS-чип устройства, заставляя его искать спутники вопреки физической невозможности их обнаружения. Провайдер же "network" использует исключительно данные сотовых вышек и Wi-Fi-точек, что дает быстрый, но гораздо менее точный результат (погрешность может составлять от 50 метров до нескольких километров).
Рассмотрим детальнее метод, с которого начинал автор темы:
ТекущийПровайдер = "gps";
Попытка
ДМ = СредстваГеопозиционирования.ПолучитьПоследнееМестоположение(ТекущийПровайдер);
Исключение
ДМ = Неопределено;
КонецПопытки;
Метод ПолучитьПоследнееМестоположение() имеет критически важную особенность: он не обращается к датчикам устройства в режиме реального времени. Этот метод лишь мгновенно считывает последнее сохраненное значение координат из системного кэша операционной системы устройства.
Если до запуска вашего приложения 1С ни одна другая программа не запрашивала координаты по GPS (например, устройство только что включили или оно долго лежало в спящем режиме), системный кэш будет пуст. В этом случае метод вернет Неопределено, даже если вы стоите посреди чистого поля.
Напротив, если на устройстве в фоновом режиме работает навигатор, постоянно обновляющий кэш, то ПолучитьПоследнееМестоположение() мгновенно отдаст вам свежие и точные координаты без затрат заряда батареи.
Жесткое прописывание строк "gps" или "network" в коде приложения считается устаревшей практикой. На различных устройствах и версиях ОС имена провайдеров могут отличаться или быть заблокированными политиками конфиденциальности. Для надежного определения провайдера платформой предусмотрены специальные методы.
Выясним причину, почему лучше использовать динамический выбор. Для этого обратимся к автоматическому подбору провайдера по критериям точности и энергопотребления:
// Получаем провайдера с наивысшей точностью, который доступен на устройстве в данный момент
ПараметрыВыбора = Новый КритерииВыбораПровайдераГеопозиционирования;
ПараметрыВыбора.Точность = ТочностьГеопозиционирования.Высокая;
// Параметр Истина гарантирует, что будут проверяться только включенные пользователем службы
Провайдер = СредстваГеопозиционирования.ПолучитьСамогоТочногоПровайдера(ПараметрыВыбора, Истина);
Если Провайдер <> Неопределено Тогда
ИмяПровайдера = Провайдер.Имя;
Иначе
// Если точный провайдер отключен в настройках устройства, пробуем энергоэкономичный
Провайдер = СредстваГеопозиционирования.ПолучитьСамогоЭнергоЭкономичногоПровайдера(Истина);
ИмяПровайдера = ?(Провайдер = Неопределено, "network", Провайдер.Имя);КонецЕсли;
Для принудительного запуска датчиков и обновления информации в кэше разработчики часто используют метод СредстваГеопозиционирования.ОбновитьМестоположение(). Однако этот метод является синхронным (блокирующим) и принимает параметр таймаута (в секундах):
Если СредстваГеопозиционирования.ОбновитьМестоположение(ИмяПровайдера, 30) Тогда
ДанныеМестоположения = СредстваГеопозиционирования.ПолучитьПоследнееМестоположение(ИмяПровайдера);
КонецЕсли;
Проанализируем подводные камни этой конструкции. Если вы передаете имя провайдера "gps" и устанавливаете таймаут в 5–10 секунд, метод практически всегда будет возвращать Ложь. Спутниковый чип физически не успеет "проснуться", связаться со спутниками и рассчитать координаты за такое короткое время. Интерфейс приложения при этом будет полностью заблокирован на все время ожидания, вызывая раздражение пользователя.
Наиболее современным, надежным и "красивым" решением для мобильных платформ является использование асинхронной подписки на события изменения местоположения. В этом случае приложение не зависает в ожидании ответа датчиков, а продолжает плавно работать. Как только операционная система получит новые координаты (неважно, через Wi-Fi, сотовые вышки или спутники), она сама передаст их в ваше приложение 1С.
Рассмотрим по шагам реализацию этого механизма:
Шаг 1. Подключение обработчика событий в модуле управляемого приложения или формы:
&НаКлиенте
Процедура НачатьОтслеживаниеГеопозиции()
#Если МобильноеПриложениеКлиент Тогда
// Обязательно проверяем, включены ли службы геолокации в настройках устройства
Если Не СредстваГеопозиционирования.ИспользованиеДанныхГеопозиционированияВключено() Тогда
ПоказатьПредупреждение(, "Пожалуйста, включите службы геолокации в настройках вашего смартфона.");
Возврат;
КонецЕсли;
// Настраиваем параметры подписки
ИнтервалОпроса = 10; // получать обновления не чаще чем раз в 10 секунд
Погрешность = 5; // игнорировать изменения менее чем на 5 метров
СредстваГеопозиционирования.ПодключитьОбработчикИзмененияМестоположения(
"ОбработкаИзмененияКоординат",
ИнтервалОпроса,
Погрешность
);
#КонецЕсли
КонецПроцедуры
Шаг 2. Описание процедуры-обработчика, в которую система будет передавать координаты:
&НаКлиенте
Процедура ОбработкаИзмененияКоординат(ДанныеМестоположения, ИмяПровайдера, ДатаОбновления, Отказ) Экспорт
Если Отказ Тогда
ЗаписатьЛогОшибки("Ошибка получения геоданных от провайдера: " + ИмяПровайдера);
Возврат;
КонецЕсли;
Если ДанныеМестоположения <> Неопределено Тогда
Широта = ДанныеМестоположения.Координаты.Широта;
Долгота = ДанныеМестоположения.Координаты.Долгота;
Скорость = ДанныеМестоположения.Скорость;
Точность = ДанныеМестоположения.Точность;
// Выполняем полезную работу, например, записываем координаты в БД или отображаем на карте
ОбработатьНовыеКоординаты(Широта, Долгота, Точность, ДатаОбновления);
КонецЕсли;
КонецПроцедуры
Шаг 3. Не забываем отключать обработчик при закрытии формы или выходе из приложения во избежание быстрой разрядки батареи устройства:
&НаКлиенте
Процедура ПриЗакрытии(Отказ)
#Если МобильноеПриложениеКлиент Тогда
СредстваГеопозиционирования.ОтключитьОбработчикИзмененияМестоположения();
#КонецЕсли
КонецПроцедуры
В современных реалиях безопасности мобильных систем код может не работать из-за жестких ограничений операционных систем. Начиная с Android 12, при первом запросе геопозиции пользователю предлагается выбор уровня конфиденциальности:
"gps". В этом режиме устройство будет отвечать исключительно по провайдеру "network".Если ваш пользователь выбрал вариант «Приблизительно», попытка принудительного обращения к "gps" всегда будет вызывать исключение или возвращать пустое значение.
Также помните про разрешения для фоновой работы. Если ваше приложение должно записывать трек перемещения сотрудника при заблокированном экране телефона или когда приложение свернуто, при сборке мобильного приложения в конфигураторе 1С обязательно необходимо активировать разрешение ACCESS_BACKGROUND_LOCATION (Разрешить работу с геопозицией в фоновом режиме). Без этого операционная система мгновенно «усыпит» все фоновые потоки 1С, как только пользователь уберет телефон в карман.
Подводя итог, сформируем оптимальный и отказоустойчивый алгоритм получения координат в 1С:
СредстваГеопозиционирования.ИспользованиеДанныхГеопозиционированияВключено().ПолучитьПоследнееМестоположение() без жесткого указания провайдера.ПодключитьОбработчикИзмененияМестоположения().Такой гибкий и современный подход гарантирует стабильную работу мобильного приложения 1С как под открытым небом, так и внутри сложных архитектурных сооружений.