При разработке и адаптации конфигураций 1С для мобильных устройств часто возникает необходимость программно определить, с какого типа клиента пользователь подключился к информационной базе. Это может быть важно для настройки интерфейса, логики работы или сбора статистики. В данной статье мы подробно рассмотрим, как выяснить, что пользователь зашел в 1С через Мобильный Клиент, а также разберем различия между Мобильным Приложением и Мобильным Клиентом.
Прежде чем переходить к методам определения, критически важно понять разницу между Мобильным Приложением и Мобильным Клиентом в экосистеме 1С:Предприятия. Это два разных способа работы с мобильными устройствами, и для их идентификации используются разные подходы.
Это автономное приложение, которое устанавливается непосредственно на мобильное устройство пользователя (например, смартфон или планшет). Ключевые особенности:
Этот вариант является аналогом тонкого клиента 1С, но специально адаптированным для работы на мобильных устройствах. Он предоставляет онлайн-доступ к основной информационной базе 1С, опубликованной на веб-сервере. Основные характеристики:
Понимание этих различий поможет нам более точно применять соответствующие методы определения типа клиента.
Для определения типа клиентского приложения на этапе компиляции кода 1С мы можем использовать специальные директивы препроцессора. Эти директивы позволяют включить или исключить блоки кода в зависимости от того, для какого клиентского приложения компилируется модуль.
Рассмотрим две ключевые директивы, которые помогут нам в нашей задаче:
#Если МобильноеПриложениеКлиент Тогда ... #КонецЕсли
Эта директива позволяет нам включить код, который будет выполняться только в том случае, если текущий модуль компилируется для мобильного приложения на стороне клиента. Она очень полезна для специфичной логики, присущей автономным мобильным приложениям.
Посмотрим на пример использования:
#Если МобильноеПриложениеКлиент Тогда
Сообщить("Обнаружен запуск в автономном Мобильном Приложении!");
// Здесь может быть специфичный код для работы с локальной базой или офлайн-режимом
НастройкаОбменаДанными();
#КонецЕсли;
Этот код будет скомпилирован и исполнен только тогда, когда приложение запущено именно как Мобильное Приложение.
#Если МобильныйКлиент Тогда ... #КонецЕсли
Несмотря на некоторые первоначальные сомнения в сообщении на форуме, эта директива действительно существует и предназначена для кода, специфичного для мобильного клиента. Она позволяет нам выделить логику, которая должна выполняться, когда пользователь работает с основной информационной базой через мобильный клиент (по аналогии с тонким клиентом).
Разберем пример:
#Если МобильныйКлиент Тогда
Сообщить("Обнаружен запуск через Мобильный Клиент!");
// Здесь может быть код, специфичный для онлайн-доступа через мобильное устройство
АдаптироватьИнтерфейсПодМобильныйКлиент();
#КонецЕсли;
Этот блок кода будет активен только при компиляции для Мобильного Клиента.
Мы можем объединить эти директивы для более гибкого определения типа клиента, как было предложено в одном из сообщений форума:
#Если МобильноеПриложениеКлиент Тогда
Приложение = НСтр("ru = 'мобильное приложение'");
#ИначеЕсли МобильныйКлиент Тогда
Приложение = НСтр("ru = 'мобильный клиент'");
#Иначе
// Если ни одно из вышеперечисленных условий не выполнилось,
// это может быть тонкий клиент, веб-клиент или толстый клиент.
#Если ТонкийКлиент Тогда
Приложение = НСтр("ru = 'тонкий клиент'");
#ИначеЕсли ВебКлиент Тогда
Приложение = НСтр("ru = 'веб-клиент'");
#ИначеЕсли ТолстыйКлиент Тогда
Приложение = НСтр("ru = 'толстый клиент'");
#Иначе
Приложение = НСтр("ru = 'неизвестный клиент'");
#КонецЕсли;
#КонецЕсли;
Сообщить("Приложение запущено как: " + Приложение);
Где можно использовать директивы препроцессора?
Инструкции препроцессора обрабатываются на этапе компиляции кода и глобально определяют, для какой сборки будет исполняться код. Их можно успешно применять в следующих клиентских модулях:
МодульУправляемогоПриложения).Важно понимать: эти директивы работают на стороне клиента и определяют среду, в которой компилируется и исполняется клиентский код.
Возникает вопрос: а что если нам нужно определить тип клиента на стороне сервера, например, в модуле сеанса (МодульСеанса) или в серверном общем модуле? Директивы препроцессора, рассмотренные выше, не могут быть использованы напрямую на сервере для определения типа клиента в момент старта сеанса, как верно подметил участник форума. Серверный код не "знает" о клиентской среде в момент своей компиляции и исполнения. Сеанс может быть запущен даже без участия клиента (например, фоновое задание, COM-соединение).
Для программного определения контекста сеанса на стороне сервера мы можем использовать несколько подходов:
Этот подход предполагает, что клиентское приложение самостоятельно определяет свой тип с помощью директив препроцессора, а затем передает эту информацию на сервер. Сервер может сохранить эту информацию, например, в параметрах сеанса.
Разберем по шагам, как это можно реализовать:
В обработчике события ПриНачалеРаботыСистемы() или подобном, мы определяем тип клиента и устанавливаем соответствующий параметр сеанса.
// МодульУправляемогоПриложения - ПриНачалеРаботыСистемы()
#Если МобильныйКлиент Тогда
УстановитьПараметрСеанса("ТипКлиента", "МобильныйКлиент");
#ИначеЕсли МобильноеПриложениеКлиент Тогда
УстановитьПараметрСеанса("ТипКлиента", "МобильноеПриложение");
#Иначе
// Для других типов клиентов (тонкий, веб, толстый)
#Если ТонкийКлиент Тогда
УстановитьПараметрСеанса("ТипКлиента", "ТонкийКлиент");
#ИначеЕсли ВебКлиент Тогда
УстановитьПараметрСеанса("ТипКлиента", "ВебКлиент");
#ИначеЕсли ТолстыйКлиент Тогда
УстановитьПараметрСеанса("ТипКлиента", "ТолстыйКлиент");
#Иначе
УстановитьПараметрСеанса("ТипКлиента", "НеизвестныйКлиент");
#КонецЕсли;
#КонецЕсли;
// Пример функции УстановитьПараметрСеанса (должна быть реализована на сервере)
// Пример: ОбщийМодульСервер.УстановитьПараметрСеанса(ИмяПараметра, Значение)
Процедура УстановитьПараметрСеанса(ИмяПараметра, Значение) Экспорт
// Вызов серверной функции для установки параметра сеанса
ОбщийМодульСервер.УстановитьПараметрСеансаНаСервере(ИмяПараметра, Значение);
КонецПроцедуры
И, соответственно, на сервере (например, в ОбщемМодуле с галочкой "Сервер"):
// ОбщийМодульСервер - Сервер
Процедура УстановитьПараметрСеансаНаСервере(ИмяПараметра, Значение) Экспорт
ПараметрыСеанса[ИмяПараметра] = Значение;
КонецПроцедуры
После установки параметра сеанса на клиенте, мы можем получить его значение на сервере.
// МодульСеанса - ПриНачалеСеанса()
Функция ПриНачалеСеанса()
// ... ваш код инициализации сеанса ...
Если ПараметрыСеанса.Свойство("ТипКлиента") Тогда
ТипКлиента = ПараметрыСеанса.ТипКлиента;
Если ТипКлиента = "МобильныйКлиент" Тогда
Сообщить("Пользователь подключился через Мобильный Клиент. Выполняем специфические действия...");
// Например, можно записать в журнал регистрации, установить специфические настройки
ЗаписатьВЖурналРегистрации("МобильныйКлиент", ТипКлиента);
ИначеЕсли ТипКлиента = "МобильноеПриложение" Тогда
Сообщить("Пользователь подключился через Мобильное Приложение.");
КонецЕсли;
Иначе
// Обработка случаев, когда параметр еще не установлен (например, для фоновых заданий)
Сообщить("Не удалось определить тип клиента из параметров сеанса.");
КонецЕсли;
// ... продолжение вашего кода ...
КонецФункции
Этот способ является достаточно надежным, так как информация передается явно от клиента.
РежимЗапускаКлиентскогоПриложения()
Функция РежимЗапускаКлиентскогоПриложения() является наиболее прямым и рекомендуемым способом определения режима запуска клиентского приложения текущего сеанса работы. Она доступна как на тонком клиенте, веб-клиенте, так и на сервере, толстом клиенте и внешнем соединении, что делает ее очень универсальной.
Посмотрим на ее применение:
// Доступно как на клиенте, так и на сервере
РежимЗапуска = РежимЗапускаКлиентскогоПриложения();
Если РежимЗапуска = РежимЗапускаКлиентскогоПриложения.МобильныйКлиент Тогда
Сообщить("Сеанс запущен в режиме Мобильного Клиента.");
// Выполнить специфические действия для Мобильного Клиента
ИначеЕсли РежимЗапуска = РежимЗапускаКлиентскогоПриложения.МобильноеПриложение Тогда
Сообщить("Сеанс запущен в режиме Мобильного Приложения.");
// Выполнить специфические действия для Мобильного Приложения
ИначеЕсли РежимЗапуска = РежимЗапускаКлиентскогоПриложения.ТонкийКлиент Тогда
Сообщить("Сеанс запущен в режиме Тонкого Клиента.");
ИначеЕсли РежимЗапуска = РежимЗапускаКлиентскогоПриложения.ВебКлиент Тогда
Сообщить("Сеанс запущен в режиме Веб-Клиента.");
Иначе
Сообщить("Сеанс запущен в другом режиме: " + РежимЗапуска);
КонецЕсли;
Эта функция возвращает значение из перечисления РежимЗапускаКлиентскогоПриложения. Среди возможных значений, которые нас интересуют:
РежимЗапускаКлиентскогоПриложения.МобильныйКлиентРежимЗапускаКлиентскогоПриложения.МобильноеПриложениеРежимЗапускаКлиентскогоПриложения.ТонкийКлиентРежимЗапускаКлиентскогоПриложения.ВебКлиентРежимЗапускаКлиентскогоПриложения.ТолстыйКлиентРежимЗапускаКлиентскогоПриложения.ВнешнееСоединение (для COM-соединений)РежимЗапускаКлиентскогоПриложения.ФоновоеЗаданиеИспользование РежимЗапускаКлиентскогоПриложения() является наиболее чистым и рекомендуемым способом, так как он предоставляет стандартизированное значение независимо от контекста вызова.
Этот способ больше подходит для административных задач или для анализа текущих подключений. Функция ПолучитьСеансыИнформационнойБазы() позволяет получить список всех активных сеансов в информационной базе. У каждого объекта сеанса есть свойство ИмяПриложения, которое может указывать на тип клиента.
Разберем пример использования:
// В серверном общем модуле или обработке с серверным вызовом
Для Каждого Сеанс ИЗ ПолучитьСеансыИнформационнойБазы() Цикл
Сообщить("Сеанс ID: " + Сеанс.НомерСеанса
+ ", Пользователь: " + Сеанс.ИмяПользователя
+ ", ИмяПриложения: " + Сеанс.ИмяПриложения);
Если Сеанс.ИмяПриложения = "MobileClient" Тогда // Примерное значение, требует уточнения
Сообщить("Найден сеанс Мобильного Клиента для пользователя: " + Сеанс.ИмяПользователя);
// Выполнить специфические действия
ИначеЕсли Сеанс.ИмяПриложения = "MobileApp" Тогда // Примерное значение, требует уточнения
Сообщить("Найден сеанс Мобильного Приложения для пользователя: " + Сеанс.ИмяПользователя);
ИначеЕсли Сеанс.ИмяПриложения = "WebServerExtension" Тогда
Сообщить("Найден сеанс Веб-клиента для пользователя: " + Сеанс.ИмяПользователя);
КонецЕсли;
КонецЦикла;
Важно: Значения свойства ИмяПриложения могут варьироваться в зависимости от версии платформы 1С и настроек публикации. Для точного определения всегда рекомендуется проверить актуальные значения при отладке или обратиться к свежей документации 1С. Тем не менее, этот метод дает общую картину активных сеансов и может быть полезен в определенных сценариях.
Если нам необходимо определить операционную систему мобильного устройства (iOS или Android) при работе с Мобильным Клиентом или Мобильным Приложением, мы можем воспользоваться объектом СистемнаяИнформация. Этот объект предоставляет доступ к различным системным параметрам, включая информацию об операционной системе.
Посмотрим на пример, как это можно сделать:
// Этот код должен выполняться на клиентской стороне (МобильныйКлиент или МобильноеПриложение)
#Если МобильныйКлиент Или МобильноеПриложениеКлиент Тогда
// Получаем версию ОС
ИнформацияОС = СистемнаяИнформация().ВерсияОС;
Если Найти(ВЕРХН(ИнформацияОС), "IOS") > 0 Тогда
Сообщить("Клиент работает на iOS.");
ИначеЕсли Найти(ВЕРХН(ИнформацияОС), "ANDROID") > 0 Тогда
Сообщить("Клиент работает на Android.");
Иначе
Сообщить("Клиент работает на неизвестной мобильной ОС: " + ИнформацияОС);
КонецЕсли;
#КонецЕсли;
Функция СистемнаяИнформация().ВерсияОС возвращает строку, содержащую информацию о версии операционной системы. Используя функции для работы со строками (например, Найти и ВЕРХН), мы можем определить, является ли ОС iOS или Android. Для расширения возможностей взаимодействия со средой Android можно применить внешнюю компоненту с набором системных утилит.
Таким образом, для точного определения того, что пользователь зашел через Мобильный Клиент или Мобильное Приложение, мы рекомендуем использовать комбинацию директив препроцессора в клиентских модулях и функцию РежимЗапускаКлиентскогоПриложения() для серверной логики. Это обеспечит гибкость и надежность вашего решения.