При разработке мобильных приложений на платформе 1С:Предприятие часто возникает необходимость в использовании локальных уведомлений для информирования пользователя о важных событиях, даже когда приложение неактивно. Однако, как показывает практика, процесс реализации этой функциональности может быть сопряжен с рядом подводных камней, связанных с контекстом выполнения, версиями платформы и правильным использованием API. В этой статье мы подробно разберем, как избежать типичных ошибок и успешно настроить локальные уведомления в вашем мобильном приложении.
Давайте вместе пройдем путь от первоначальных проблем до полного и корректного решения, опираясь на опыт разработчиков и документацию.
Одна из первых проблем, с которой мы можем столкнуться, — это ошибка "Переменная не определена" при попытке работы с объектом ДоставляемыеУведомления из серверного кода. Рассмотрим пример из исходного запроса:
&НаСервере
Процедура Тест()
ДатаПоявления = ТекущаяДата+5;
Уведомление = Новый ДоставляемоеУведомление;
Увеведомление.Заголовок = "Заголовок";
Уведомление.Текст = "Текст";
Уведомление.ДатаПоявленияУниверсальноеВремя = ДатаПоявления;
Уведомление.ЗвуковоеОповещение = ЗвуковоеОповещение.ПоУмолчанию;
ДоставляемыеУведомления.ДобавитьЛокальноеУведомление(Уведомление); // Здесь возникает ошибка
КонецПроцедуры
Как мы видим, код пытается добавить уведомление в процедуре с директивой &НаСервере. Однако, если мы обратимся к справке по объекту ДоставляемыеУвеведомления, мы выясним, что его доступность ограничена. Синтаксис-помощник однозначно указывает:
Доступность: Мобильное приложение(клиент).
Это означает, что объект ДоставляемыеУведомления предназначен исключительно для выполнения на стороне мобильного клиента. Попытки использовать его на сервере приведут к ошибке "Переменная не определена", поскольку в серверном контексте такого объекта просто не существует.
Решение: Нам необходимо перенести весь код, связанный с созданием и добавлением локального уведомления, в клиентский контекст. Для этого мы будем использовать директиву &НаКлиенте.
&НаКлиенте
Процедура АналитикаНажатие(Элемент)
// Проверяем, что работаем в мобильном приложении
#Если МобильноеПриложениеКлиент Тогда
ДатаПоявления = ТекущаяДата+5;
Уведомление = Новый ДоставляемоеУведомление;
Уведомление.Заголовок = "Заголовок";
Уведомление.Текст = "Текст";
Уведомление.ДатаПоявленияУниверсальноеВремя = ДатаПоявления;
Уведомление.ЗвуковоеОповещение = ЗвуковоеОповещение.ПоУмолчанию;
ДоставляемыеУведомления.ДобавитьЛокальноеУведомление(Уведомление); // Теперь это работает корректно
#КонецЕсли
КонецПроцедуры
Используя директиву компиляции #Если МобильноеПриложениеКлиент Тогда, мы гарантируем, что этот код будет доступен только при работе в мобильном приложении, что является хорошей практикой.
После того как мы разобрались с контекстом выполнения и успешно добавили уведомление, следующей задачей становится обработка события получения этого уведомления. Для этого мы подключаем специальный обработчик. На первый взгляд, может показаться логичным передать имя процедуры обработчика строкой, например, так:
Процедура ПриНачалеРаботыСистемы()
#Если МобильноеПриложениеКлиент Тогда
// Эта строка приведет к ошибке
ДоставляемыеУведомления.ПодключитьОбработчикУведомлений("ПриПолучиенииУведомления");
#КонецЕсли
КонецПроцедуры
Однако, такая запись приводит к ошибке: "Ошибка при вызове метода контекста (ПодключитьОбработчикУведомлений) по причине: Недопустимое значение параметра (параметр номер '1')". Это происходит потому, что метод ПодключитьОбработчикУведомлений не принимает строковое имя процедуры напрямую.
Решение: Для подключения обработчиков событий в 1С используется специальный объект ОписаниеОповещения. Он позволяет явно указать процедуру, которая будет вызвана при наступлении события, и, при необходимости, модуль, в котором эта процедура находится.
Согласно документации, метод ПодключитьОбработчикУведомлений() ожидает в качестве параметра объект ОписаниеОповещения. Разберем синтаксис:
Синтаксис: ПодключитьОбработчикУведомлений(<Обработчик>)
Параметры:
<Обработчик> (обязательный)
Тип: ОписаниеОповещения;
Описание: Используется для описания вызова процедуры программного модуля, который будет осуществлен при наступлении какого-либо ожидаемого события, такого как закрытие формы или немодального диалога.
Таким образом, мы должны создать экземпляр ОписаниеОповещения, передав ему имя нашей процедуры-обработчика и, опционально, имя модуля (если обработчик находится в общем модуле). Если процедура находится в том же модуле, где происходит подключение (например, в модуле управляемого приложения), то в качестве имени модуля можно указать пустую строку или не указывать вовсе, если процедура объявлена глобально или в текущем модуле без явного указания.
Давайте посмотрим, как правильно подключить обработчик:
Процедура ПриНачалеРаботыСистемы()
#Если МобильноеПриложениеКлиент Тогда
// Создаем описание оповещения, указывая имя процедуры-обработчика и модуль
// Если процедура в МодулеУправляемогоПриложения, можно передать "МодульУправляемогоПриложения"
// или использовать "ЭтотОбъект" или оставить пустым, если обработчик в том же модуле.
// В нашем случае, так как процедура-обработчик будет находиться в том же модуле управляемого приложения,
// достаточно указать имя процедуры. Для надежности можно использовать "ЭтотОбъект".
Оп = Новый ОписаниеОповещения("ПриПолучиенииУведомления", ЭтотОбъект);
ДоставляемыеУведомления.ПодключитьОбработчикУведомлений(Оп);
#КонецЕсли
КонецПроцедуры
Таким образом, мы корректно передаем параметр типа ОписаниеОповещения, и платформа сможет правильно подключить наш обработчик.
После того как мы исправили подключение обработчика, следующая сложность может проявиться в виде "падения" приложения (краша) при попытке вызова уведомления или просто в том, что процедура-обработчик не срабатывает. Это может быть связано с двумя основными причинами: отсутствием ключевого слова Экспорт у процедуры-обработчика и/или некорректной сигнатурой (количеством и типами параметров) этой процедуры.
Изначально обработчик мог выглядеть так:
Процедура ПриПолучиенииУведомления(Уведомление, Локальное, Показано)
Если Локальное Тогда
Сообщить("Прибыло уведомление с текстом: " + Уведомление.Текст);
Иначе
Сообщить("Прибыло пусш уведомление с текстом: " + Увеведомление.Текст);
КонецЕсли;
КонецПроцедуры
Давайте выясним причины проблем и найдем решение.
Экспорт: Процедура-обработчик, которая вызывается платформой по событию (в данном случае, по получению уведомления), должна быть экспортной. Это означает, что она должна быть доступна для вызова извне текущего модуля. Если ключевого слова Экспорт нет, платформа не сможет найти и вызвать эту процедуру. В некоторых версиях платформы это может приводить к ошибкам компиляции, в других — к тому, что процедура просто не вызывается без явных сообщений об ошибке, или даже к неожиданному завершению работы приложения.Уведомление, Локальное, Показано и ДополнительныеПараметры. Отсутствие параметра ДополнительныеПараметры (даже если он не используется и передается пустым) приведет к ошибке "Недопустимое значение параметра" или падению приложения.Решение: Исправим процедуру-обработчик, добавив ключевое слово Экспорт и включив все необходимые параметры в сигнатуру.
&НаКлиенте
Процедура ПриПолучиенииУведомления(Уведомление, Локальное, Показано, ДополнительныеПараметры) Экспорт
// Процедура теперь корректно объявлена и готова к приему уведомлений
Если Локальное = Истина Тогда
Сообщить("Прибыло локальное уведомление с текстом: " + Увеведомление.Текст);
Иначе
Сообщить("Прибыло Push-уведомление с текстом: " + Уведомление.Текст);
КонецЕсли;
КонецПроцедуры
Обратите внимание, что параметр ДополнительныеПараметры теперь присутствует в сигнатуре, даже если в данном конкретном случае мы его не используем. Это критически важно для корректной работы.
Теперь, когда мы решили все основные проблемы, давайте соберем весь рабочий код в единое целое, чтобы у нас был полноценный пример отправки и обработки локальных уведомлений в мобильном приложении 1С.
// *** В Модуле Управляемого Приложения ***
// Процедура, вызываемая при старте системы
Процедура ПриНачалеРаботыСистемы()
#Если МобильноеПриложениеКлиент Тогда
// 1. Правильное подключение обработчика уведомлений через ОписаниеОповещения
Оп = Новый ОписаниеОповещения("ПриПолучиенииУведомления", ЭтотОбъект);
ДоставляемыеУведомления.ПодключитьОбработчикУведомлений(Оп);
#КонецЕсли
КонецПроцедуры
// Процедура-обработчик получения уведомлений
// Должна быть ЭКСПОРТНОЙ и иметь правильную сигнатуру
&НаКлиенте
Процедура ПриПолучиенииУведомления(Уведомление, Локальное, Показано, ДополнительныеПараметры) Экспорт
Если Локальное = Истина Тогда
Сообщить("Прибыло локальное уведомление с текстом: " + Уведомление.Текст);
Иначе
Сообщить("Прибыло Push-уведомление с текстом: " + Уведомление.Текст);
КонецЕсли;
КонецПроцедуры
// *** В форме или модуле, где нужно отправить уведомление ***
// Пример процедуры для отправки локального уведомления (например, по нажатию кнопки)
&НаКлиенте
Процедура АналитикаНажатие(Элемент)
#Если МобильноеПриложениеКлиент Тогда
// 2. Создание и добавление уведомления только на клиенте
ДатаПоявления = ТекущаяДата() + 5 * 60; // Уведомление появится через 5 минут
Уведомление = Новый ДоставляемоеУведомление;
Уведомление.Заголовок = "Напоминание!";
Уведомление.Текст = "Не забудьте выполнить важное действие.";
// Дата появления должна быть в универсальном времени
Уведомление.ДатаПоявленияУниверсальноеВремя = ДатаПоявления;
// Звуковое оповещение по умолчанию
Уведомление.ЗвуковоеОповещение = ЗвуковоеОповещение.ПоУмолчанию;
// Опционально: можно добавить произвольные данные
// Уведомление.Данные = Новый Структура("Ключ", "Значение");
// Опционально: задать интервал повтора (если нужно повторяющееся уведомление)
// Уведомление.ИнтервалПовтора = 3600; // Повторять каждый час
ДоставляемыеУведомления.ДобавитьЛокальноеУведомление(Уведомление);
Сообщить("Локальное уведомление запланировано на " + Формат(ДатаПоявления, "ДФ=dd.MM.yyyy HH:mm:ss"));
#КонецЕсли
КонецПроцедуры
В этом примере мы демонстрируем полный цикл работы: подключение обработчика при старте приложения и добавление локального уведомления по действию пользователя. Это должно служить надежной основой для вашей реализации. Для ознакомления с комплексным сценарием использования таймеров и оповещений подойдёт пример разработки мобильного приложения с нуля.
Для полноценного понимания и эффективного использования локальных уведомлений в мобильном приложении 1С, давайте рассмотрим некоторые дополнительные, но не менее важные аспекты:
Локальные уведомления, после того как вы их добавили через ДоставляемыеУведомления.ДобавитьЛокальноеУведомление(), управляются операционной системой мобильного устройства. Платформа 1С:Предприятие лишь предоставляет API для их создания и регистрации в системе. После этого операционная система берет на себя ответственность за их планирование, отображение и взаимодействие с пользователем. Это означает, что даже если ваше приложение будет закрыто, уведомление все равно сработает в назначенное время.
Локальные уведомления могут быть запланированы на определенную дату и время с помощью свойства ДатаПоявленияУниверсальноеВремя. Важно помнить, что если вы хотите получить повторяющееся уведомление, необходимо указать свойство ИнтервалПовтора (в секундах). Если ИнтервалПовтора не задан, уведомление будет доставлено только один раз. Для разового уведомления достаточно лишь установить ДатаПоявленияУниверсальноеВремя.
При создании уведомления мы можем задать ему уникальный идентификатор, присвоив значение свойству Идентификатор. Это очень полезно, если в дальнейшем нам потребуется отменить конкретное, ранее запланированное уведомление. Метод ДоставляемыеУведомления.ОтменитьЛокальноеУведомление(Идентификатор) позволяет убрать уведомление из очереди операционной системы. Если идентификатор не указан, платформа или операционная система могут присвоить его автоматически, что затруднит отмену конкретного уведомления.
С каждым уведомлением можно связать произвольные данные. Для этого используйте свойство Данные, тип которого Произвольный. Эти данные будут переданы в вашу процедуру-обработчик при получении уведомления, что позволяет передавать контекст или дополнительную информацию для реакции приложения на конкретное уведомление. Например, вы можете передать идентификатор документа или задачу, чтобы при нажатии на уведомление открыть соответствующую форму в приложении.
Для локальных уведомлений доступна настройка звукового оповещения через свойство ЗвуковоеОповещение. Мы можем выбрать стандартные системные звуки (например, ЗвуковоеОповещение.ПоУмолчанию) или, при наличии соответствующей поддержки платформы и операционной системы, указать собственный звуковой файл. Возможность настройки вибрации также присутствует и часто определяется настройками операционной системы и самого уведомления.
Поведение локальных уведомлений, когда мобильное приложение активно и находится на переднем плане, может различаться в зависимости от операционной системы и ее версии. В некоторых случаях уведомление может не отображаться как всплывающее окно, а сразу передаваться в процедуру-обработчик, если приложение "слушает" эти события. Важно протестировать это поведение на целевых устройствах.
При возникновении проблем с локальными уведомлениями, особенно когда приложение "падает", крайне рекомендуется использовать отладку. Отладка на мобильном устройстве или эмуляторе позволит нам точно определить место возникновения ошибки и ее причину. В мобильной разработке также очень полезно просматривать логи устройства (например, с помощью ADB для Android или Xcode для iOS), которые могут содержать более детальную информацию об исключениях, даже если платформа 1С не выводит их явно.
Как показывает опыт из форума, проблемы с локальными уведомлениями могут быть связаны с конкретными версиями платформы. Например, в одном из сообщений упоминалось, что версия 8.3.10.69 вызывала проблемы, которые решились переходом на 8.3.11.57. Поэтому, при столкновении с неразрешимыми проблемами, всегда рекомендуется проверить актуальность используемой версии платформы и мобильного клиента 1С:Предприятия. Обновление до более стабильной или новой версии, где проблема могла быть исправлена, часто является эффективным решением.
Таким образом, для успешной работы с локальными уведомлениями в мобильном приложении 1С мы должны использовать актуальную версию платформы, выполнять код на стороне клиента, правильно подключать обработчик через ОписаниеОповещения, соблюдать актуальную сигнатуру процедуры-обработчика, а также эффективно использовать возможности отладки и глубокое понимание жизненного цикла уведомлений.