Как проиграть звуковые файлы по очереди в мобильном приложении 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке мобильных приложений на платформе 1С часто возникает задача воспроизвести несколько звуковых сигналов или фраз подряд (например, озвучить число или статус документа). Если просто написать несколько вызовов метода воспроизведения подряд, все звуки начнут звучать одновременно, создавая какофонию. Попытки использовать циклы с паузой («слипы») приводят к зависанию интерфейса приложения.

Разберем детально, почему так происходит, и рассмотрим три способа решения этой задачи: от простого к архитектурно правильному.

Почему звуки накладываются друг на друга?

Метод СредстваМультимедиа.ВоспроизвестиАудио в мобильной платформе работает асинхронно. Это означает, что когда платформа встречает эту строку кода, она отправляет команду операционной системе (Android или iOS) «начать проигрывание» и сразу же переходит к следующей строке кода, не дожидаясь окончания звука.

Если мы напишем такой код:


// Неправильный подход
СредстваМультимедиа.ВоспроизвестиАудио(Звук1);
СредстваМультимедиа.ВоспроизвестиАудио(Звук2);
СредстваМультимедиа.ВоспроизвестиАудио(Звук3);

Все три команды уйдут в систему практически мгновенно, и телефон начнет играть их одновременно. Использование циклов для задержки (паузы) на мобильном устройстве недопустимо, так как код 1С выполняется в основном потоке интерфейса. Любая искусственная пауза «заморозит» экран и может привести к ошибке «Приложение не отвечает».

Решение 1. Использование обработчика завершения (Рекомендуемый способ)

Наиболее корректный способ управления очередью звуков — использование механизма обратных вызовов (callback). Метод ВоспроизвестиАудио имеет параметр ОбработчикОстановкиВоспроизведения.

Мы можем создать цепочку (рекурсию): запускаем первый звук и передаем системе инструкцию: «когда этот звук закончится, вызови процедуру, которая запустит следующий».

Рассмотрим пример реализации через рекурсивный вызов:


&НаКлиенте
Процедура ПроигратьПлейлист(СписокЗвуков, Индекс = 0)
    
    // Если список закончился, выходим
    Если Индекс > СписокЗвуков.Количество() - 1 Тогда
        Возврат;
    КонецЕсли;
    
    ТекущийЗвук = СписокЗвуков[Индекс];
    
    // Создаем оповещение, которое сработает ПОСЛЕ окончания звука
    // Передаем тот же метод, но увеличиваем индекс на 1
    ДополнительныеПараметры = Новый Структура;
    ДополнительныеПараметры.Вставить("СписокЗвуков", СписокЗвуков);
    ДополнительныеПараметры.Вставить("СледующийИндекс", Индекс + 1);
    
    Оповещение = Новый ОписаниеОповещения("ОбработчикОкончанияЗвука", ЭтотОбъект, ДополнительныеПараметры);
    
    // Запускаем звук и передаем оповещение третьим параметром
    СредстваМультимедиа.ВоспроизвестиАудио(ТекущийЗвук, 0, Оповещение);

КонецПроцедуры

&НаКлиенте
Процедура ОбработчикОкончанияЗвука(ДополнительныеПараметры) Экспорт
    
    // Получаем параметры и запускаем следующий трек
    Список = ДополнительныеПараметры.СписокЗвуков;
    СледИндекс = ДополнительныеПараметры.СледующийИндекс;
    
    ПроигратьПлейлист(Список, СледИндекс);
    
КонецПроцедуры

Преимущества: Гарантирует отсутствие пауз и наложений, не блокирует интерфейс.

Решение 2. Использование обработчика ожидания

Если по каким-то причинам использование ОписаниеОповещения невозможно, можно воспользоваться методом ПодключитьОбработчикОжидания. Логика следующая: мы знаем длительность звука, запускаем его и взводим «будильник», который через нужное количество секунд запустит следующий звук.

Этот способ упомянут в теме как рабочий, но он менее надежен: если устройство «подвиснет» или длительность файла определена неверно, звуки могут наложиться или возникнет слишком длинная пауза.


&НаКлиенте
Процедура ЗапуститьОчередь()
    // Запускаем первый звук
    СредстваМультимедиа.ВоспроизвестиАудио(Звук1);
    
    // Зная, что звук длится 2 секунды, планируем следующий через 2.1 сек
    ПодключитьОбработчикОжидания("ЗапуститьВторойЗвук", 2.1, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ЗапуститьВторойЗвук()
    СредстваМультимедиа.ВоспроизвестиАудио(Звук2);
КонецПроцедуры

Решение 3. Объединение звуков в один файл

Если последовательность звуков всегда одинаковая (например, фраза приветствия), самым надежным и простым способом будет объединение их в один аудиофайл с помощью любого аудиоредактора. В этом случае коду 1С нужно будет вызвать команду воспроизведения всего один раз.

Важные нюансы

  1. Временное хранилище: При работе с мобильным приложением старайтесь не передавать звуковые файлы с сервера (через ПолучитьИзВременногоХранилища) каждый раз перед воспроизведением. Это вызывает задержки, зависящие от скорости интернета. Лучше кэшировать файлы на устройстве локально.
  2. Фоновый режим: Если экран устройства погаснет, воспроизведение цепочки может прерваться. Чтобы этого избежать, используйте параметр РазрешитьФоновое (четвертый параметр метода ВоспроизвестиАудио), установив его в Истина.
  3. Синтез речи: Если ваша задача — проговаривать числа или стандартные фразы, рассмотрите метод СредстваМультимедиа.СинтезРечи (TTS). Системный синтезатор речи на мобильных ОС обычно сам умеет выстраивать очередь фраз, что избавит вас от написания сложного кода.
← На главную