Разработка мобильных приложений на платформе "1С:Предприятие" с использованием push-уведомлений и локальных уведомлений часто сопряжена с рядом неочевидных трудностей. Мы рассмотрим полный цикл настройки и реализации push-уведомлений, начиная от конфигурации Firebase Cloud Messaging (FCM) и заканчивая отправкой из основной базы 1С, а также разберем, как избежать распространенных ошибок.
Наш опыт показывает, что одной из главных причин, по которой push-уведомления могут не приходить, является метод отладки. Мы выяснили, что на мобильных платформах версий 8.3.18 и 8.3.19, а возможно и других, уведомления могут работать некорректно или не приходить вовсе при использовании приложения мобильной платформы 1С для отладки. Это часто вводит в заблуждение и заставляет думать, что проблема в коде.
Для корректной проверки работоспособности push-уведомлений мы настоятельно рекомендуем не использовать приложение мобильной платформы от 1С для отладки, а вместо этого собирать полноценный APK/IPA файл приложения. Именно при тестировании на собранном приложении уведомления начинают приходить так, как задумано. Это критически важный момент, который может сэкономить вам множество часов отладки.
Прежде чем мы начнем работать с кодом, нам необходимо подготовить наш проект в Firebase. Помните, что с июня 2019 года Google прекратил поддержку GCM, поэтому мы используем исключительно Firebase Cloud Messaging (FCM).
Создаем проект в консоли Firebase: Переходим на сайт Firebase и создаем новый проект. Мы можем назвать его как угодно.
Настраиваем Cloud Messaging: После создания проекта переходим в его настройки (значок шестеренки) и выбираем закладку "Cloud Messaging". Здесь мы увидим поля Server key и Sender ID. Эти идентификаторы критически важны для работы с уведомлениями, поэтому мы рекомендуем хранить их в основной базе 1С для централизованного доступа.
Server key – необходим для отправки уведомлений из нашей базы 1С.Sender ID – используется для формирования идентификатора подписчика на мобильном устройстве (хотя, как мы увидим далее, для FCM этот параметр в 1С можно опустить).Добавляем мобильное приложение в Firebase: На закладке "GENERAL" в разделе "Your apps" добавляем наше мобильное приложение. Для Android-приложений это означает выбор иконки Android и указание Android package name. Это очень важный момент. Android package name необходимо взять из сборщика мобильного приложения 1С. В справочнике "Мобильные приложения" для нашей группы приложений мы найдем раздел "Идентификаторы мобильных приложений", где и будет указано это имя. Убедитесь, что оно точно совпадает с тем, что мы указываем в Firebase.
Выгружаем google-services.json: После добавления приложения в Firebase, из консоли из вновь созданного приложения мы выгружаем файл google-services.json. Этот файл содержит всю необходимую конфигурацию Firebase для нашего мобильного приложения. Затем мы добавляем его в соответствующее поле в сборщике мобильного приложения 1С при создании нашего приложения. Этот файл гарантирует правильную инициализацию Firebase SDK на мобильном устройстве.
После настройки Firebase мы переходим к мобильному приложению. Наша задача здесь — получить уникальный идентификатор устройства (токен) от Firebase, который позволит нам отправлять уведомления конкретному приложению на этом устройстве. Этот идентификатор необходимо передать в основную базу 1С для дальнейшего использования.
Мы используем метод ДоставляемыеУведомления.ПолучитьИдентификаторПодписчикаУведомлений(). Критически важно: для работы с FCM этот метод следует вызывать без параметра НомерПриложенияGoogleCloud. Если мы передадим этот параметр, метод вернет идентификатор GCM, который не будет корректно работать с Firebase Cloud Messaging и приведет к ошибке MismatchSenderId при отправке.
Разберем пример кода, который мы размещаем в обработчике события ПриНачалеРаботыСистемы мобильного приложения:
#Если МобильноеПриложениеКлиент Тогда
Попытка
// Получаем идентификатор подписчика. Важно: для FCM вызываем без параметра.
ИдентификаторПодписчикаУведомлений = ДоставляемыеУведомления.ПолучитьИдентификаторПодписчикаУведомлений;
// Передаем полученный идентификатор в основную базу 1С
ОбменДанными.ПередатьИдентификаторПодписчикаУведомлений(ИдентификаторПодписчикаУведомлений);
Исключение
// Здесь мы можем реализовать логирование или уведомление пользователя
// о том, что не удалось получить или передать идентификатор уведомлений.
// Например: Сообщить("Не удалось получить или передать идентификатор для push-уведомлений.");
КонецПопытки
#КонецЕсли
Как мы видим, мы сначала пытаемся получить идентификатор, а затем передать его в основную базу. Метод ОбменДанными.ПередатьИдентификаторПодписчикаУведомлений() — это наша собственная процедура для взаимодействия с центральной базой. Давайте рассмотрим, как она может быть реализована:
// Пример процедуры в модуле объекта обмена данными основной базы,
// который мобильное приложение вызывает через веб-сервис или HTTP-сервис.
Процедура ПередатьИдентификаторПодписчикаУведомлений(ИдентификаторПодписчикаУведомлений) Экспорт
// Предполагается, что ОбменДаннымиПовтИсп.ИнициализироватьПараметрыДляОбмена
// возвращает структуру с настроенным WS-прокси для взаимодействия.
СтруктураПараметров = ОбменДаннымиПовтИсп.ИнициализироватьПараметрыДляОбмена;
Если НЕ СтруктураПараметров.WSПрокси = Неопределено Тогда
Попытка
// Находим операцию веб-сервиса для передачи идентификатора
Операция = СтруктураПараметров.WSПрокси.ТочкаПодключения.Интерфейс.Операции.Получить("ПередатьИдентификаторПодписчикаУведомлений");
// Если требуется передача кода узла или других параметров,
// создаем соответствующие объекты XDTO.
КодУзла = СтруктураПараметров.WSПрокси.ФабрикаXDTO.Создать(Операция.Параметры.Получить("КодУзла").Тип, Константы.КодПланаОбменаТекущегоКлиента.Получить);
// Сериализуем идентификатор подписчика в формат XDTO для передачи через веб-сервис
Сериализатор = Новый СериализаторXDTO(СтруктураПараметров.WSПрокси.ФабрикаXDTO);
ИдентификаторXDTO = Сериализатор.ЗаписатьXDTO(ИдентификаторПодписчикаУведомлений);
// Выполняем вызов веб-сервиса
Ответ = СтруктураПараметров.WSПрокси.ПередатьИдентификаторПодписчикаУведомлений(КодУзла, ИдентификаторXDTO);
// Здесь мы можем обработать Ответ, если веб-сервис что-то возвращает
Исключение
// Логируем ошибку, если не удалось передать идентификатор
// ЗаписьЖурналаРегистрации("ПередачаИдентификатора", УровеньЖурналаРегистрации.Ошибка, , , "Ошибка при передаче идентификатора подписчика уведомлений: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Основная задача этого кода — принять идентификатор, полученный с мобильного устройства, и сохранить его в нашей центральной базе данных. Мы можем хранить эти идентификаторы в регистре сведений, связанном с пользователем или устройством, чтобы в дальнейшем отправлять push-уведомления конкретным адресатам.
После того как мы получили и сохранили идентификаторы подписчиков, мы можем отправлять push-уведомления из нашей основной базы 1С через API Firebase Cloud Messaging. Для этого мы будем использовать HTTP-запрос.
Нам понадобятся Server key из Firebase (полученный на Шаге 1) и список идентификаторов устройств, которым мы хотим отправить уведомление. Разберем пример процедуры отправки:
// Процедура для отправки push-уведомления из основной базы 1С
Процедура ОтправитьPushУведомление(МассивУстройств, ПараметрыУведомления) Экспорт
// ПараметрыУведомления - структура, содержащая Заголовок и Текст уведомления.
// Адрес API Firebase Cloud Messaging
АдресСервера = "fcm.googleapis.com";
АдресРесурса = "/fcm/send";
// Используем защищенное соединение SSL
ssl = Новый ЗащищенноеСоединениеOpenSSL;
Соединение = Новый HTTPСоединение(АдресСервера,,,,,,ssl);
// Формируем тело сообщения для Firebase.
// Это часть, которая будет отображаться в уведомлении на устройстве.
ТелоСообщения = Новый Структура;
ТелоСообщения.Вставить("title", ПараметрыУведомления.Заголовок); // Заголовок уведомления
ТелоСообщения.Вставить("body", ПараметрыУведомления.Текст); // Текст уведомления (для отображения)
ТелоСообщения.Вставить("sound", "default"); // Использование стандартного звука уведомления
// Дополнительные данные, которые могут быть обработаны в приложении
ТелоСообщения.Вставить("custom_data", "какие-либо дополнительные данные");
// Основные параметры запроса к FCM.
// Здесь мы указываем, кому отправляем (registration_ids) и что отправляем (notification или data).
// Мы используем "notification" для отображаемых уведомлений и "data" для произвольных данных,
// которые обрабатываются приложением. Можно использовать и то, и другое.
ПараметрыСообщения = Новый Структура;
// registration_ids - массив идентификаторов устройств, на которые отправляем.
// Каждый идентификатор мы получили ранее с помощью ДоставляемыеУведомления.ПолучитьИдентификаторПодписчикаУведомлений().
ПараметрыСообщения.Вставить("registration_ids", МассивУстройств);
// Если нам нужно, чтобы уведомление обязательно появилось в шторке,
// используем ключ "notification".
ПараметрыСообщения.Вставить("notification", ТелоСообщения);
// Если нам нужно передать произвольные данные, которые приложение обработает,
// даже если оно в фоновом режиме, используем ключ "data".
// В этом случае, если приложение активно, оно получит эти данные без отображения уведомления.
// Если приложение неактивно, уведомление может быть показано системой Android/iOS,
// если в поле "data" содержится информация, похожая на "notification" (title, body).
// Рекомендуется отправлять "notification" и "data" отдельно или комбинировать.
// Для нашего примера мы помещаем данные в "notification" для отображения.
// Если нам нужны кастомные данные, которые не будут отображаться напрямую,
// мы можем использовать отдельный ключ "data":
// ПараметрыСообщения.Вставить("data", Новый Структура("ключ1", "значение1", "ключ2", "значение2"));
// Сериализуем структуру ПараметрыСообщения в формат JSON.
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку;
ЗаписатьJSON(ЗаписьJSON, ПараметрыСообщения);
СтрокаТелоЗапроса = ЗаписьJSON.Закрыть;
// Создаем HTTP-запрос.
Запрос = Новый HTTPЗапрос(АдресРесурса);
Запрос.Заголовки.Вставить("Content-Type", "application/json"); // Указываем тип контента
// В заголовок Authorization добавляем Server key из Firebase.
// КлючСервера - это переменная или константа, содержащая ваш Server key.
Запрос.Заголовки.Вставить("Authorization", "key="+КлючСервера);
// Устанавливаем тело запроса в формате JSON.
Запрос.УстановитьТелоИзСтроки(СтрокаТелоЗапроса, КодировкаТекста.UTF8);
// Отправляем запрос и получаем ответ от сервера Firebase.
Попытка
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
// Анализируем ответ от Firebase. Код 200 означает успешную отправку.
Если Ответ.КодСостояния = 200 Тогда
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку);
СтруктураОтвета = ПрочитатьJSON(ЧтениеJSON);
// Мы можем логировать СтруктураОтвета для анализа результатов отправки,
// например, сколько уведомлений было успешно доставлено, сколько провалилось.
// Сообщить("Ответ от Firebase: " + Ответ.ПолучитьТелоКакСтроку);
Иначе
// Обрабатываем ошибки, если код состояния не 200
// Сообщить("Ошибка отправки push-уведомления. Код состояния: " + Ответ.КодСостояния +
// " Тело ответа: " + Ответ.ПолучитьТелоКакСтроку);
КонецЕсли;
Исключение
// Логируем общую ошибку соединения или отправки запроса
// ЗаписьЖурналаРегистрации("ОтправкаPushУведомления", УровеньЖурналаРегистрации.Ошибка, , , "Ошибка при отправке push-уведомления: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
В этом коде МассивУстройств — это массив строк, где каждая строка — это идентификатор подписчика уведомлений для отдельного мобильного устройства. ПараметрыУведомления — это структура, которую мы формируем для каждого уведомления, например, с полями Заголовок и Текст. КлючСервера — это наш Server key из Firebase.
Если все настроено правильно, то при получении кода ответа 200 от Firebase, уведомления должны приходить на мобильные устройства мгновенно. Это очень приятный момент после дней или недель работы.
Когда push-уведомление приходит на устройство, оно может быть просто отображено системой (например, в шторке уведомлений), или же наше мобильное приложение может его обработать, если оно активно. Для этого мы должны подключить обработчик уведомлений в мобильном приложении 1С.
Мы используем метод ДоставляемыеУведомления.ПодключитьОбработчикУведомлений(). Этот обработчик будет вызываться как для локальных, так и для push-уведомлений.
// В модуле мобильного приложения или другом подходящем месте (например, при старте приложения):
// Подключение обработчика локальных и push-уведомлений
// Предполагаем, что "УведомленияКлиент" - это имя общего модуля,
// где будет определена процедура "ОбработкаУведомлений".
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработкаУведомлений", УведомленияКлиент);
#Если МобильноеПриложениеКлиент Тогда
ДоставляемыеУведомления.ПодключитьОбработчикУведомлений(ОписаниеОповещения);
#КонецЕсли
// Пример реализации процедуры ОбработкаУведомлений в общем модуле "УведомленияКлиент"
Процедура ОбработкаУведомлений(ДанныеУведомления, ЭтоЛокальноеУведомление) Экспорт
Если ЭтоЛокальноеУведомление Тогда
// Мы можем здесь обработать локальное уведомление,
// например, обновить какие-то данные в приложении или показать сообщение.
Сообщить("Получено локальное уведомление: Заголовок: " + ДанныеУведомления.Заголовок +
", Текст: " + ДанныеУведомления.Текст);
// Доступ к данным локального уведомления через ДанныеУведомления.
// Пример: ДанныеУведомления.Идентификатор, ДанныеУведомления.ИдентификаторПериодическогоУведомления
Иначе
// Мы обрабатываем push-уведомление.
// ДанныеУведомления будет содержать структуру с переданными из основной базы полями
// (например, title и body из секции "notification" или любые данные из секции "data").
Сообщить("Получено push-уведомление: Заголовок: " + ДанныеУведомления.Заголовок +
", Текст: " + ДанныеУведомления.Текст);
// Здесь мы можем выполнить дополнительные действия, например:
// - Открыть определенную форму в приложении.
// - Запросить более подробные данные из основной базы 1С,
// так как размер push-уведомления ограничен.
// - Обновить данные в локальной базе мобильного приложения.
// - Если мы передавали custom_data, то можно получить к ним доступ:
// Если ДанныеУведомления.Свойство("custom_data") Тогда
// Сообщить("Дополнительные данные: " + ДанныеУведомления.custom_data);
// КонецЕсли;
КонецЕсли;
КонецПроцедуры
В параметрах обработчика ДанныеУведомления — это структура, содержащая данные уведомления, а ЭтоЛокальноеУведомление — булево значение, указывающее тип уведомления. Если приложение активно и находится на переднем плане, этот обработчик будет вызван немедленно. Если приложение находится в фоновом режиме или закрыто, системное уведомление будет отображено, и обработчик может быть вызван при запуске приложения по нажатию на это уведомление.
В процессе работы с push-уведомлениями мы можем столкнуться с рядом трудностей. Разберем наиболее частые из них и способы их решения:
Ошибка MismatchSenderId: Эта ошибка указывает на расхождение между идентификатором отправителя (Sender ID), используемым в запросе на отправку, и идентификатором отправителя, связанным с токеном регистрации устройства. Это происходит, если:
Server key в заголовке Authorization при отправке запроса из 1С. Убедитесь, что ключ скопирован из настроек проекта Firebase (Настройки -> Cloud Messaging -> Учетные данные для проекта).google-services.json в мобильном приложении (например, не совпадает package_name с applicationId в сборщике 1С).Решение: Убедитесь, что Sender ID, используемый для генерации токена устройства, соответствует Sender ID проекта Firebase, с которого вы отправляете. Возможно, потребуется перегенерировать токен на устройстве с корректным файлом google-services.json и обновить его в вашей базе 1С.
Настройки телефона: Убедитесь, что для вашего 1С-приложения включены все необходимые разрешения на показ уведомлений в настройках самого телефона. Мы часто забываем проверить стандартные системные настройки.
Поддержка Google-сервисов: Проверьте, что на тестируемом телефоне активирован Google-аккаунт и установлены Google Play Services. Без них Firebase не сможет функционировать.
Разница между GCM и FCM: Как мы уже упоминали, метод ДоставляемыеУведомления.ПолучитьИдентификаторПодписчикаУведомлений() без параметра возвращает идентификатор FCM. Если же передать туда НомерПриложенияGoogleCloud, он вернет идентификатор GCM. Для современных приложений мы всегда используем FCM. Убедитесь, что ваш код получения идентификатора не передает лишних параметров.
Статус приложения: Push-уведомления должны приходить и отображаться, даже если мобильное приложение находится в фоновом режиме (запущено, но неактивно) или полностью выгружено из памяти. Если они не приходят в этих сценариях, это может указывать на проблему с регистрацией токена или конфигурацией Firebase.
Помимо push-уведомлений, платформа 1С позволяет работать с локальными уведомлениями. Они используются для реализации напоминаний и других событий, которые мобильное приложение устанавливает само для себя. Локальные уведомления могут сработать, когда приложение неактивно, и не требуют связи с центральной базой или внешними сервисами.
Существуют моментальные, запланированные и периодические локальные уведомления. Для их обработки также используется метод ДоставляемыеУведомления.ПодключитьОбработчикУведомлений(), как мы рассмотрели ранее. Внутри обработчика мы можем определить тип уведомления по параметру ЭтоЛокальноеУведомление и соответствующим образом его обработать.
Мы столкнулись с ситуацией, когда локальные уведомления приходили не сразу, а с задержкой, иногда даже на следующий день. Это может быть связано с особенностями работы операционной системы на конкретном устройстве (например, режимы энергосбережения), но, как правило, при корректной настройке они срабатывают в заданное время.
Платформа "1С:Предприятие" предлагает и другие механизмы уведомлений. Например, "Сервис 1С:Центр уведомлений" и "Сервер взаимодействия". Этот механизм позволяет отправлять уведомления мобильным клиентам о различных событиях, таких как входящие сообщения или звонки, используя инфраструктуру 1С. Для этого необходимо зарегистрировать отправителя уведомлений в "Сервисе 1С:Центр уведомлений" и получить ключ доступа, который затем используется для настройки сервера взаимодействия.
Кроме того, Firebase предоставляет мощные инструменты аналитики. Мы можем использовать их для отслеживания эффективности наших уведомлений, включая количество открытий, нажатий и общую конверсию. Это помогает нам оптимизировать нашу стратегию уведомлений и улучшать взаимодействие с пользователями.
Мы рассмотрели полный цикл работы с push-уведомлениями в мобильном приложении 1С, включая ключевые моменты настройки Firebase, получения и передачи идентификатора устройства, а также отправку уведомлений из основной базы. Помните, что важнейшим этапом является тестирование на собранном APK/IPA приложении, а не на отладочной мобильной платформе 1С, что позволит нам избежать многих проблем и успешно доставлять уведомления нашим пользователям.