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

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

Разработаем мобильное приложение на базе 1С под Android. В процессе создания часто возникает потребность в голосовом оповещении пользователя, например, для озвучивания статуса задачи или навигационных подсказок. Для этого в 1С используется метод СредстваМультимедиа.ВоспроизвестиТекст(). Однако, если пользователь в этот момент слушает фоновую музыку (например, через сторонний плеер, такой как PowerAmp), возникает проблема: при произнесении текста музыка корректно ставится на паузу (или приглушается), но после окончания произнесения — плеер продолжает молчать. Музыка возобновляется только после полного закрытия приложения 1С.

Давайте подробно разберем эту ситуацию, выясним причину такого поведения и проанализируем возможные варианты решения проблемы.

Почему музыка не продолжает играть? Разберем механизм Audio Focus

Чтобы понять суть проблемы, нам нужно заглянуть "под капот" операционной системы Android. В Android одновременно могут воспроизводить звук несколько приложений. Чтобы они не мешали друг другу, используется системный сервис `AudioManager` и механизм аудиофокуса (Audio Focus).

Посмотрим по шагам, что происходит:

  1. Когда 1С вызывает метод ВоспроизвестиТекст, платформа запрашивает у системы временный аудиофокус (флаг AUDIOFOCUS_GAIN_TRANSIENT).
  2. Сторонний плеер (музыка) получает от системы уведомление о потере фокуса и ставит воспроизведение на паузу.
  3. После того как текст произнесен, приложение 1С обязано вернуть фокус системе, вызвав нативную команду abandonAudioFocus().
  4. Именно здесь кроется проблема: мобильная платформа 1С "забывает" послать эту команду. Аудиоканал остается заблокированным движком Text-To-Speech (TTS), и музыкальный плеер считает, что 1С всё ещё "разговаривает". Фокус освобождается лишь при уничтожении процесса 1С.

Почему штатные методы 1С не помогают?

Рассмотрим, какие попытки решения часто предпринимаются разработчиками внутри конфигурации, и почему они не работают:

Попытка 1: Принудительная остановка воспроизведения


&НаКлиенте 
Процедура ПослеПроизнесенияТекста(допПарам) Экспорт 
    #Если МобильноеПриложениеКлиент Тогда 
        СредстваМультимедиа.ОстановитьВоспроизведениеТекста(); 
    #КонецЕсли 
КонецПроцедуры

Вызов ОстановитьВоспроизведениеТекста() прерывает текущее чтение, но, к сожалению, не инициирует системный вызов освобождения аудиофокуса. Баг платформы сохраняется.

Попытка 2: Очистка объекта мультимедиа

Разработчики старой школы могут попробовать обнулить объект: СредстваМультимедиа = Неопределено;. Однако в современных версиях платформы СредстваМультимедиа — это глобальная функция (глобальный контекст), а не локальный объект, создаваемый через Новый. При попытке присвоения вы получите ошибку "Поле недоступно для записи".

Варианты обхода проблемы с помощью нативного кода (JavaКласс)

Поскольку мы выяснили, что перед нами классический баг мобильной платформы, мы можем попытаться обойти его, обратившись к API Android напрямую через механизм Новый JavaКласс.

Вариант 1: Принудительное снятие аудиофокуса

Мы можем написать код, который программно обратится к классу android.media.AudioManager и вызовет метод снятия фокуса. Логика решения выглядит так:

  1. Получаем текущий контекст приложения Android.
  2. Получаем системный сервис AUDIO_SERVICE.
  3. Приводим полученный сервис к Java-классу AudioManager.
  4. Вызываем метод abandonAudioFocus().

Этот код необходимо будет поместить в процедуру, которая срабатывает по завершении оповещения (через ОписаниеОповещения, переданное в метод ВоспроизвестиТекст).

Вариант 2: Отправка Intent мультимедийной кнопки

Если работа с AudioManager кажется сложной, рассмотрим альтернативный путь — имитацию нажатия кнопки "Play" на гарнитуре. Большинство плееров перехватывают это событие и продолжают воспроизведение.

С помощью объекта Новый Intent (также создаваемого через вызов Java-классов в мобильной платформе) мы можем сформировать широковещательное сообщение с действием ACTION_MEDIA_BUTTON и кодом клавиши KEYCODE_MEDIA_PLAY. Отправив такой интент (broadcast) системе после окончания речи 1С, мы заставим фоновый плеер "проснуться" и снять трек с паузы.

Подведем итоги

Проанализируем ситуацию в целом: мы имеем дело с недоработкой мобильной платформы 1С при работе с механизмом Audio Focus в ОС Android. Пока разработчики платформы не выпустят официальное исправление (патч), решить проблему исключительно штатными средствами 1С (без использования Java-классов) невозможно. Если возобновление музыки критично для пользовательского опыта вашего приложения, рекомендуется реализовать вызов abandonAudioFocus() через нативные средства Android, предоставляемые механизмом интеграции 1С с Java.

← На главную