Разработаем мобильное приложение на базе 1С под Android. В процессе создания часто возникает потребность в голосовом оповещении пользователя, например, для озвучивания статуса задачи или навигационных подсказок. Для этого в 1С используется метод СредстваМультимедиа.ВоспроизвестиТекст(). Однако, если пользователь в этот момент слушает фоновую музыку (например, через сторонний плеер, такой как PowerAmp), возникает проблема: при произнесении текста музыка корректно ставится на паузу (или приглушается), но после окончания произнесения — плеер продолжает молчать. Музыка возобновляется только после полного закрытия приложения 1С.
Давайте подробно разберем эту ситуацию, выясним причину такого поведения и проанализируем возможные варианты решения проблемы.
Чтобы понять суть проблемы, нам нужно заглянуть "под капот" операционной системы Android. В Android одновременно могут воспроизводить звук несколько приложений. Чтобы они не мешали друг другу, используется системный сервис `AudioManager` и механизм аудиофокуса (Audio Focus).
Посмотрим по шагам, что происходит:
ВоспроизвестиТекст, платформа запрашивает у системы временный аудиофокус (флаг AUDIOFOCUS_GAIN_TRANSIENT).abandonAudioFocus().Рассмотрим, какие попытки решения часто предпринимаются разработчиками внутри конфигурации, и почему они не работают:
Попытка 1: Принудительная остановка воспроизведения
&НаКлиенте
Процедура ПослеПроизнесенияТекста(допПарам) Экспорт
#Если МобильноеПриложениеКлиент Тогда
СредстваМультимедиа.ОстановитьВоспроизведениеТекста();
#КонецЕсли
КонецПроцедуры
Вызов ОстановитьВоспроизведениеТекста() прерывает текущее чтение, но, к сожалению, не инициирует системный вызов освобождения аудиофокуса. Баг платформы сохраняется.
Попытка 2: Очистка объекта мультимедиа
Разработчики старой школы могут попробовать обнулить объект: СредстваМультимедиа = Неопределено;. Однако в современных версиях платформы СредстваМультимедиа — это глобальная функция (глобальный контекст), а не локальный объект, создаваемый через Новый. При попытке присвоения вы получите ошибку "Поле недоступно для записи".
Поскольку мы выяснили, что перед нами классический баг мобильной платформы, мы можем попытаться обойти его, обратившись к API Android напрямую через механизм Новый JavaКласс.
Вариант 1: Принудительное снятие аудиофокуса
Мы можем написать код, который программно обратится к классу android.media.AudioManager и вызовет метод снятия фокуса. Логика решения выглядит так:
AUDIO_SERVICE.AudioManager.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.