Разработка под мобильную платформу «1С:Предприятие 8» всегда сопряжена с преодолением специфических трудностей, вызванных различиями в операционных системах Android и iOS, особенностями прошивок сторонних производителей и поведением самой платформы при обновлении версий. В этой статье мы подробно разберем две классические проблемы, с которыми часто сталкиваются разработчики мобильных приложений на 1С: внезапный сбой авторизации при WS-соединениях и зависание стандартных средств камеры на некоторых современных смартфонах.
Мы детально проанализируем причины возникновения этих неполадок, рассмотрим практические кейсы и выработаем надежные, проверенные решения для обеспечения стабильной работы мобильного клиента.
Рассмотрим распространенную ситуацию: мобильное приложение, опубликованное на веб-сервере Apache, взаимодействует с центральной базой данных посредством Web-сервисов. Код инициализации соединения выглядит стандартно:
Определение = Новый WSОпределения("http://192.168.1.100/BaseMain/ws/SaveData?wsdl", "export", "958kf63", , 10, , Ложь);
Внезапно после очередного обновления платформы или изменения настроек сети на некоторых мобильных устройствах данная строка начинает вызывать исключение: «Ошибка работы с Интернет: No authentication found» (или аналогичное сообщение «No authentication challenges found»). При этом на части устройств обмен продолжает работать стабильно, даже если версии операционной системы и мобильной платформы совпадают. Выясним, почему так происходит.
Основная причина кроется в конфликте механизмов аутентификации на веб-сервере и ужесточении требований безопасности в новых версиях мобильной платформы 1С (начиная с 8.3.12). Проанализируем ключевые факторы:
Authorization: Basic ... или искажать SSL-рукопожатие, из-за чего веб-сервер перестает распознавать авторизационные данные мобильного клиента.Для устранения этой ошибки можно пойти несколькими путями. Разберем по шагам каждое решение.
Способ 1. Настройка файла публикации default.vrd
Самое простое и правильное решение — явно отключить использование аутентификации операционной системы в файле публикации веб-сервиса. Для этого найдем на сервере файл default.vrd, соответствующий нашей публикации, и отредактируем его, добавив параметр useOSAuthentication="false". Пример структуры файла:
<?xml version="1.0" encoding="UTF-8"?>
<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
base="/BaseMain"
ib="Connect="Srvr=server;Ref=BaseMain;""
useOSAuthentication="false">
<ws>
<point name="SaveData" alias="SaveData" enable="true"/>
</ws>
</point>
После сохранения изменений обязательно перезапустите веб-сервер (Apache или IIS).
Способ 2. Разделение публикаций для десктопных и мобильных пользователей
Если в вашей организации для обычных ПК-пользователей настроена сквозная доменная авторизация (Active Directory) через веб-сервер, отключение этой опции парализует их работу. В таком случае рекомендуется создать две независимые публикации на веб-сервере:
/BaseMain) настраивается с включенной аутентификацией ОС — для работы пользователей в веб-клиенте на ПК./BaseMainMobile) настраивается строго с параметром useOSAuthentication="false" — исключительно для мобильных устройств и Web-сервисов обмена.Способ 3. Проверка и установка SSL-сертификатов
Если обмен происходит по защищенному протоколу HTTPS, мобильное устройство обязательно должно доверять SSL-сертификату сервера. Если сертификат самоподписанный (часто используется для тестов), мобильное приложение 1С заблокирует соединение без объяснения причин, выдав общую ошибку работы с Интернет. Необходимо вручную импортировать корневой сертификат вашего сервера в системное хранилище доверенных сертификатов на каждом проблемном мобильном устройстве (через настройки безопасности Android/iOS).
Способ 4. Временный откат или обновление платформы
В качестве быстрого временного решения (workaround) можно выполнить откат мобильной платформы на более раннюю стабильную версию (например, с 8.3.12 на 8.3.11). Однако в долгосрочной перспективе правильнее обновить мобильную платформу до актуального релиза (например, ветки 8.3.14 или старше), предварительно исправив настройки веб-сервера согласно Способу 1.
---
Перейдем ко второй важнейшей проблеме — нестабильной работе встроенных мультимедийных средств. Разработчики часто используют следующий стандартный код для получения фотографий:
Разрешение = Новый РазрешениеКамерыУстройства;
Разрешение.Высота = 1024;
Разрешение.Ширина = 1365;
ДанныеФото = СредстваМультимедиа.СделатьФотоснимок(ТипКамерыУстройства.Авто, Разрешение, 70);
На многих современных смартфонах (особенно бренда Xiaomi с прошивками MIUI/HyperOS) вызов этого метода приводит к зависанию интерфейса: камера открывается, снимок делается, но после нажатия кнопки подтверждения экран застывает. Картинка возвращается в приложение только после того, как пользователь принудительно свернет и заново развернет мобильное приложение 1С.
Выясним причину этого поведения. Все дело в агрессивной оптимизации оперативной памяти мобильной ОС. Когда 1С вызывает системную камеру через СредстваМультимедиа, управление передается системному процессу съемки, а само приложение 1С уходит в фоновый режим. Операционная система смартфона в этот момент мгновенно приостанавливает («замораживает») графический контекст 1С для экономии ресурсов. При возвращении из камеры приложение 1С не получает сигнал на перерисовку интерфейса. Ручное сворачивание и разворачивание приложения заставляет операционную систему принудительно обновить графический слой 1С.
Чтобы обойти системные ограничения энергосбережения Android и избавиться от зависаний, мы можем отказаться от объекта СредстваМультимедиа и вызвать камеру как внешнее приложение с помощью объекта ЗапускПриложенияМобильногоУстройства (механизм Android Intents). Посмотрим на пример реализации:
// Определим путь для сохранения временного файла снимка
ИмяФайла = ПолучитьИмяВременногоФайла(".jpg");
ФайлКартинки = Новый Файл(ИмяФайла);
// Настраиваем интент для вызова стандартной камеры Android
ЗахватИзображения = Новый ЗапускПриложенияМобильногоУстройства("android.media.action.IMAGE_CAPTURE");
ЗахватИзображения.ДополнительныеДанные.Добавить("output", ФайлКартинки.ПолноеИмя, "Uri");
// Запускаем внешнее приложение камеры и ожидаем возврата управления
РезультатЗапуска = ЗахватИзображения.Запустить(Истина);
Если РезультатЗапуска = 0 Тогда
// Фото успешно сделано и сохранено во временный файл
Если ФайлКартинки.Существует() Тогда
ДвоичныеДанныеФото = Новый ДвоичныеДанные(ФайлКартинки.ПолноеИмя);
// Выполняем дальнейшую обработку полученного фото
КонецЕсли;
Иначе
Предупреждение("Не удалось запустить камеру или съемка была отменена.");
КонецЕсли;
Этот подход работает безупречно на всех Android-устройствах, поскольку операционная система корректно обрабатывает жизненный цикл приложений при явном вызове внешнего интента IMAGE_CAPTURE и возвращает управление в 1С без потери контекста отрисовки.
---
Главный недостаток вызова камеры через механизм интентов Android заключается в том, что этот способ абсолютно несовместим с iOS. На устройствах Apple (iPhone, iPad) нет концепции глобальных интентов, аналогичных Android. Попытка выполнить данный код на iOS приведет к аварийному завершению работы приложения.
Проанализируем ситуацию и построим универсальную архитектуру съемки. На iOS стандартный метод СредстваМультимедиа.СделатьФотоснимок() работает стабильно и без зависаний, поскольку политика управления памятью в iOS жестко регламентирует переходы состояний приложений, не допуская деградации интерфейса. Следовательно, нам необходимо разделить логику выполнения кода в зависимости от текущей операционной системы устройства.
Разберем по шагам построение универсальной функции получения фотографии:
&НаКлиенте
Процедура ВыполнитьСъемку()
#Если МобильноеПриложениеКлиент Тогда
// Проверяем тип операционной системы устройства
ИнформацияОСистеме = Новая СистемнаяИнформация;
ТипПлатформы = ИнформацияОСистеме.ТипПлатформы;
Если ТипПлатформы = ТипПлатформыКачестваМобильногоУстройства.Android Тогда
// Используем стабильный вызов через Android Intent
ВыполнитьСъемкуAndroid();
ИначеЕсли ТипПлатформы = ТипПлатформыКачестваМобильногоУстройства.iOS Тогда
// Используем стандартные средства мультимедиа iOS
ВыполнитьСъемкуiOS();
Иначе
Предупреждение("Данная операционная система не поддерживается.");
КонецЕсли;
#Иначе
Предупреждение("Съемка доступна только на мобильном устройстве!");
#КонецЕсли
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьСъемкуAndroid()
ИмяФайла = ПолучитьИмяВременногоФайла(".jpg");
ЗахватИзображения = Новый ЗапускПриложенияМобильногоУстройства("android.media.action.IMAGE_CAPTURE");
ЗахватИзображения.ДополнительныеДанные.Добавить("output", ИмяФайла, "Uri");
Если ЗахватИзображения.Запустить(Истина) = 0 Тогда
ФайлФото = Новый Файл(ИмяФайла);
Если ФайлФото.Существует() Тогда
ОбработатьПолученноеИзображение(ИмяФайла);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьСъемкуiOS()
Разрешение = Новый РазрешениеКамерыУстройства;
Разрешение.Высота = 1024;
Разрешение.Ширина = 1365;
Попытка
ДанныеФото = СредстваМультимедиа.СделатьФотоснимок(ТипКамерыУстройства.Авто, Разрешение, 70);
Если ДанныеФото <> Неопределено Тогда
ИмяФайла = ПолучитьИмяВременногоФайла(".jpg");
ДанныеФото.Записать(ИмяФайла);
ОбработатьПолученноеИзображение(ИмяФайла);
КонецЕсли;
Исключение
ЗаписатьЛогОшибки(ОписаниеОшибки());
Предупреждение("Ошибка при работе с камерой iOS: " + КраткоеПредставлениеОшибки(ОписаниеОшибки()));
КонецПопытки;
КонецПроцедуры
Рассмотрим два критических момента, о которых нужно помнить при использовании внешнего интента на Android:
IMAGE_CAPTURE камера фотографирует с максимальным разрешением, поддерживаемым физическим модулем устройства. Полученный файл может весить более 10 МБ. Передача таких объемов данных на сервер через мобильный интернет нецелесообразна. Начиная с версии платформы 8.3.14, в мобильной платформе появились отличные инструменты сжатия. Посмотрим на пример масштабирования картинки перед отправкой:
// Пример уменьшения размера изображения
КартинкаОригинал = Новый Картинка(ИмяФайла);
КартинкаСжатая = КартинкаОригинал.Преобразовать(ФорматКартинки.JPEG, 1024, 768);
КартинкаСжатая.Записать(ИмяФайла);
NSCameraUsageDescription и NSPhotoLibraryUsageDescription с текстовым описанием цели использования). Отсутствие этих настроек в манифесте приведет к моментальному закрытию («вылету») приложения при попытке вызвать фотосъемку на iOS.Применяя предложенные нами подходы к разграничению авторизации на веб-сервере и разделению логики работы с камерой под разные мобильные операционные системы, вы сможете добиться высочайшей стабильности и отказоустойчивости ваших мобильных решений на платформе «1С:Предприятие 8».