Аудиовход обычно поступает со встроенного микрофона, внешнего микрофона или аудиоинтерфейса, подключенного к устройству. Аудиовход также может поступать из телефонного разговора.
Иногда два или более приложений могут захотеть «захватить» один и тот же аудиовход. Они могут выполнять разные задачи. Например, некоторые приложения, которые получают аудио, могут «записывать», как простой диктофон, в то время как другие приложения могут «слушать», как Google Assistant или служба специальных возможностей, которая реагирует на голосовые команды.
В любом случае эти приложения хотят получать аудиовход. На этой странице мы используем термин «захват» независимо от того, записывает ли приложение или просто слушает.
Если два или более приложений хотят захватить аудио одновременно, может возникнуть проблема с доставкой аудиосигнала из одного источника для всех них. На этой странице описывается, как система Android распределяет аудиовход между несколькими приложениями, которые захватывают аудио.
Поведение до Android 10
До Android 10 входной аудиопоток мог быть захвачен только одним приложением за раз. Если какое-то приложение уже записывало или прослушивало аудио, ваше приложение могло создать объект AudioRecord
, но при вызове AudioRecord.startRecording()
возвращалась ошибка, и запись не начиналась.
Исключением из этого правила было то, что привилегированное приложение (например, Google Assistant или служба доступности) имело разрешение android.permission.CAPTURE_AUDIO_HOTWORD
и использовало источник звука типа HOTWORD
. В этом случае другое приложение могло начать запись. Когда это происходило, привилегированное приложение завершало работу, а новое приложение захватывало входные данные.
Еще одно изменение было добавлено в Android 9: только приложения, работающие на переднем плане (или служба переднего плана), могли захватывать аудиовход. Когда приложение без службы переднего плана или компонента пользовательского интерфейса переднего плана начинало захват, приложение продолжало работать, но получало тишину, даже если это было единственное приложение, захватывающее аудио в тот момент.
Поведение Android 10
До Android 10 поведение было таким: «первым пришел, первым обслужен». Как только приложение начинает захватывать звук, никакие другие приложения не могут получить доступ к аудиовходу, пока приложение, которое захватывает звук, не остановится.
Android 10 устанавливает схему приоритетов, которая может переключать входной аудиопоток между приложениями во время их работы. В большинстве случаев, если новое приложение получает аудиовход, предыдущее приложение, которое захватывало звук, продолжает работать, но получает тишину. В некоторых случаях система может продолжать передавать аудио обоим приложениям. Различные сценарии обмена описаны ниже.
Эта схема похожа на то, как аудиофокус обрабатывает несколько приложений, конкурирующих за использование аудиовыхода. Однако аудиофокус управляется программными запросами на получение и снятие фокуса, в то время как схема переключения ввода, описанная здесь, основана на политике приоритетов, которая применяется автоматически всякий раз, когда новое приложение начинает захватывать аудио.
Для записи звука Android различает два типа приложений:
- «Обычные» приложения устанавливаются пользователем.
- «Привилегированные» приложения предустановлены на устройстве. К ним относятся Google Assistant и все службы доступности.
Кроме того, приложение обрабатывается по-другому, если оно использует «чувствительный к конфиденциальности» источник звука: CAMCORDER
или VOICE_COMMUNICATION
.
Правила приоритетности использования и совместного использования аудиовхода следующие:
- Привилегированные приложения имеют более высокий приоритет, чем обычные приложения.
- Приложения с видимым пользовательским интерфейсом на переднем плане имеют более высокий приоритет, чем фоновые приложения.
- Приложения, захватывающие звук из источника, конфиденциальность которого важна, имеют более высокий приоритет, чем приложения, которые таковыми не являются.
- Два обычных приложения никогда не смогут записывать звук одновременно.
- В некоторых ситуациях привилегированное приложение может использовать общий аудиовход с другим приложением.
- Если два фоновых приложения с одинаковым приоритетом захватывают звук, то приоритет имеет последнее запущенное приложение.
Обмен сценариями
Когда два приложения пытаются захватить звук, они оба могут получить входной сигнал, или одно из них может получить тишину.
Существует четыре основных сценария:
- Помощник + обычное приложение
- Служба доступности + обычное приложение
- Два обычных приложения
- Голосовой вызов + обычное приложение
Помощник + обычное приложение
Assistant — это привилегированное приложение, поскольку оно предустановлено и имеет роль RoleManager.ROLE_ASSISTANT
. Любое другое предустановленное приложение с этой ролью обрабатывается аналогично.
Android разделяет входящий звук в соответствии со следующими правилами:
Помощник может принимать звук (независимо от того, находится ли он на переднем плане или в фоновом режиме), если другое приложение, использующее чувствительный к конфиденциальности источник звука, уже не осуществляет запись.
Приложение получает звук, если у Помощника нет видимого компонента пользовательского интерфейса в верхней части экрана.
Обратите внимание, что оба приложения получают звук только тогда, когда Ассистент работает в фоновом режиме, а другое приложение не захватывает звук из источника звука, конфиденциальность которого имеет значение.
Служба доступности + обычное приложение
AccessibilityService
требует строгого объявления .
Android разделяет входящий звук в соответствии со следующими правилами:
Если пользовательский интерфейс сервиса находится сверху, и сервис, и приложение получают аудиовход. Такое поведение предлагает такие функции, как управление голосовым вызовом или видеозахватом с помощью голосовых команд.
Если сервис не находится наверху, этот случай рассматривается как обычный случай с двумя приложениями ниже.
Два обычных приложения
Когда два приложения выполняют захват одновременно, только одно приложение получает звук, а другое получает тишину.
Android разделяет входящий звук в соответствии со следующими правилами:
- Если ни одно из приложений не является чувствительным к конфиденциальности, то приложение с пользовательским интерфейсом сверху получает аудио. Если ни одно из приложений не имеет пользовательского интерфейса, то то, которое начало захват последним, получает аудио.
- Если одно из приложений чувствительно к конфиденциальности, оно получает звук, а другое приложение получает тишину, даже если у него есть пользовательский интерфейс или оно начало запись совсем недавно.
- Если оба приложения чувствительны к конфиденциальности, то приложение, которое начало запись последним, получает звук, а другое получает тишину.
Голосовой вызов + обычное приложение
Голосовой вызов активен, если аудиорежим, возвращаемый AudioManager.getMode()
, равен MODE_IN_CALL
или MODE_IN_COMMUNICATION
.
Android разделяет входящий звук в соответствии со следующими правилами:
- Звонок всегда принимает аудиосигнал.
- Приложение может записывать звук, если оно является службой специальных возможностей .
Приложение может захватить голосовой вызов, если это привилегированное (предустановленное) приложение с разрешением
CAPTURE_AUDIO_OUTPUT
.Чтобы захватить восходящий канал (TX), нисходящий канал (RX) голосового вызова или оба канала, приложение должно указать источники звука
MediaRecorder.AudioSource.VOICE_UPLINK
илиMediaRecorder.AudioSource.VOICE_DOWNLINK
и/или устройствоAudioDeviceInfo.TYPE_TELEPHONY
.
Поведение Android 11
Android 11 (API уровня 30) соблюдает описанную выше схему приоритетов Android 10. Он также предоставляет новые методы в AudioRecord
, MediaRecorder
и AAudioStream
, которые включают и отключают возможность одновременного захвата звука, независимо от выбранного варианта использования.
Новые методы:
-
AudioRecord.Builder.setPrivacySensitive()
-
AudioRecord.isPrivacySensitive()
-
MediaRecorder.setPrivacySensitive()
-
MediaRecorder.isPrivacySensitive()
-
AAudioStreamBuilder_setPrivacySensitive()
-
AAudioStream_isPrivacySensitive()
Когда setPrivacySensitive()
имеет true
, вариант использования захвата является частным, и даже привилегированный помощник не может производить захват одновременно. Эта настройка переопределяет поведение по умолчанию, которое зависит от источника звука. Например, VOICE_COMMUNICATION
является частным по умолчанию, а UNPROCESSED
— нет.
Изменения конфигурации
Когда несколько приложений одновременно захватывают звук, только одно или два из них «активны» (получают звук); остальные отключены (получают тишину). Когда активные приложения меняются, звуковая структура может перенастроить аудиотракты в соответствии со следующими правилами:
- Устройство аудиовхода для каждого активного приложения может меняться (например, со встроенного микрофона на подключенную Bluetooth-гарнитуру).
- Включается предварительная обработка, связанная с активным приложением с наивысшим приоритетом. Вся остальная предварительная обработка игнорируется.
Поскольку активное приложение может быть отключено, когда приложение с более высоким приоритетом становится активным, вы можете зарегистрировать AudioManager.AudioRecordingCallback на объекте AudioRecord
или MediaRecorder
, чтобы получать уведомления об изменении конфигурации. Возможные изменения могут быть следующими:
- Захват с отключенным или отключенным звуком
- Устройство изменено
- Предварительная обработка изменена
- Изменены свойства потока (частота дискретизации, маска канала, формат выборки)
Вы должны вызвать AudioRecord.registerAudioRecordingCallback()
до начала захвата. Обратный вызов выполняется только тогда, когда приложение получает аудио и происходит изменение.
Метод onRecordingConfigChanged()
возвращает AudioRecordingConfiguration
, содержащий текущее состояние аудиозахвата. Используйте следующие методы, чтобы узнать об изменении:
-
isClientSilenced()
- Возвращает значение true, если звук, возвращаемый клиенту, в настоящее время отключается из-за политики захвата.
-
getAudioDevice()
- Возвращает активное аудиоустройство.
-
getEffects()
- Возвращает активный эффект предварительной обработки. Обратите внимание, что активный эффект может не совпадать с возвращаемыми
getClientEffects()
если клиент не является активным приложением с наивысшим приоритетом. -
getFormat()
- Возвращает свойства потока. Обратите внимание, что фактические аудиоданные, полученные клиентом, всегда соответствуют требуемому формату, возвращаемому
getClientFormat()
. Фреймворк автоматически выполняет необходимую передискретизацию, канал и преобразование формата из формата, используемого на аппаратном интерфейсе, в формат, указанный клиентом. -
AudioRecord.getActiveRecordingConfiguration()
. - Возвращает активную конфигурацию записи.
Общий вид всех активных записей на устройстве можно получить, вызвав AudioManager.getActiveRecordingConfigurations()
.
Аудиовход обычно поступает со встроенного микрофона, внешнего микрофона или аудиоинтерфейса, подключенного к устройству. Аудиовход также может поступать из телефонного разговора.
Иногда два или более приложений могут захотеть «захватить» один и тот же аудиовход. Они могут выполнять разные задачи. Например, некоторые приложения, которые получают аудио, могут «записывать», как простой диктофон, в то время как другие приложения могут «слушать», как Google Assistant или служба специальных возможностей, которая реагирует на голосовые команды.
В любом случае эти приложения хотят получать аудиовход. На этой странице мы используем термин «захват» независимо от того, записывает ли приложение или просто слушает.
Если два или более приложений хотят захватить аудио одновременно, может возникнуть проблема с доставкой аудиосигнала из одного источника для всех них. На этой странице описывается, как система Android распределяет аудиовход между несколькими приложениями, которые захватывают аудио.
Поведение до Android 10
До Android 10 входной аудиопоток мог быть захвачен только одним приложением за раз. Если какое-то приложение уже записывало или прослушивало аудио, ваше приложение могло создать объект AudioRecord
, но при вызове AudioRecord.startRecording()
возвращалась ошибка, и запись не начиналась.
Исключением из этого правила было то, что привилегированное приложение (например, Google Assistant или служба доступности) имело разрешение android.permission.CAPTURE_AUDIO_HOTWORD
и использовало источник звука типа HOTWORD
. В этом случае другое приложение могло начать запись. Когда это происходило, привилегированное приложение завершало работу, а новое приложение захватывало входные данные.
Еще одно изменение было добавлено в Android 9: только приложения, работающие на переднем плане (или служба переднего плана), могли захватывать аудиовход. Когда приложение без службы переднего плана или компонента пользовательского интерфейса переднего плана начинало захват, приложение продолжало работать, но получало тишину, даже если это было единственное приложение, захватывающее аудио в тот момент.
Поведение Android 10
До Android 10 поведение было таким: «первым пришел, первым обслужен». Как только приложение начинает захватывать звук, никакие другие приложения не могут получить доступ к аудиовходу, пока приложение, которое захватывает звук, не остановится.
Android 10 устанавливает схему приоритетов, которая может переключать входной аудиопоток между приложениями во время их работы. В большинстве случаев, если новое приложение получает аудиовход, предыдущее приложение, которое захватывало звук, продолжает работать, но получает тишину. В некоторых случаях система может продолжать передавать аудио обоим приложениям. Различные сценарии обмена описаны ниже.
Эта схема похожа на то, как аудиофокус обрабатывает несколько приложений, конкурирующих за использование аудиовыхода. Однако аудиофокус управляется программными запросами на получение и снятие фокуса, в то время как схема переключения ввода, описанная здесь, основана на политике приоритетов, которая применяется автоматически всякий раз, когда новое приложение начинает захватывать аудио.
Для записи звука Android различает два типа приложений:
- «Обычные» приложения устанавливаются пользователем.
- «Привилегированные» приложения предустановлены на устройстве. К ним относятся Google Assistant и все службы доступности.
Кроме того, приложение обрабатывается по-другому, если оно использует «чувствительный к конфиденциальности» источник звука: CAMCORDER
или VOICE_COMMUNICATION
.
Правила приоритетности использования и совместного использования аудиовхода следующие:
- Привилегированные приложения имеют более высокий приоритет, чем обычные приложения.
- Приложения с видимым пользовательским интерфейсом на переднем плане имеют более высокий приоритет, чем фоновые приложения.
- Приложения, захватывающие звук из источника, конфиденциальность которого важна, имеют более высокий приоритет, чем приложения, которые таковыми не являются.
- Два обычных приложения никогда не смогут записывать звук одновременно.
- В некоторых ситуациях привилегированное приложение может использовать общий аудиовход с другим приложением.
- Если два фоновых приложения с одинаковым приоритетом захватывают звук, то приоритет имеет последнее запущенное приложение.
Обмен сценариями
Когда два приложения пытаются захватить звук, они оба могут получить входной сигнал, или одно из них может получить тишину.
Существует четыре основных сценария:
- Помощник + обычное приложение
- Служба доступности + обычное приложение
- Два обычных приложения
- Голосовой вызов + обычное приложение
Помощник + обычное приложение
Assistant — это привилегированное приложение, поскольку оно предустановлено и имеет роль RoleManager.ROLE_ASSISTANT
. Любое другое предустановленное приложение с этой ролью обрабатывается аналогично.
Android разделяет входящий звук в соответствии со следующими правилами:
Помощник может принимать звук (независимо от того, находится ли он на переднем плане или в фоновом режиме), если другое приложение, использующее чувствительный к конфиденциальности источник звука, уже не осуществляет запись.
Приложение получает звук, если у Помощника нет видимого компонента пользовательского интерфейса в верхней части экрана.
Обратите внимание, что оба приложения получают звук только тогда, когда Ассистент работает в фоновом режиме, а другое приложение не захватывает звук из источника звука, конфиденциальность которого имеет значение.
Служба доступности + обычное приложение
AccessibilityService
требует строгого объявления .
Android разделяет входящий звук в соответствии со следующими правилами:
Если пользовательский интерфейс сервиса находится сверху, и сервис, и приложение получают аудиовход. Такое поведение предлагает такие функции, как управление голосовым вызовом или видеозахватом с помощью голосовых команд.
Если сервис не находится наверху, этот случай рассматривается как обычный случай с двумя приложениями ниже.
Два обычных приложения
Когда два приложения выполняют захват одновременно, только одно приложение получает звук, а другое получает тишину.
Android разделяет входящий звук в соответствии со следующими правилами:
- Если ни одно из приложений не является чувствительным к конфиденциальности, то приложение с пользовательским интерфейсом сверху получает аудио. Если ни одно из приложений не имеет пользовательского интерфейса, то то, которое начало захват последним, получает аудио.
- Если одно из приложений чувствительно к конфиденциальности, оно получает звук, а другое приложение получает тишину, даже если у него есть пользовательский интерфейс или оно начало запись совсем недавно.
- Если оба приложения чувствительны к конфиденциальности, то приложение, которое начало запись последним, получает звук, а другое получает тишину.
Голосовой вызов + обычное приложение
Голосовой вызов активен, если аудиорежим, возвращаемый AudioManager.getMode()
, равен MODE_IN_CALL
или MODE_IN_COMMUNICATION
.
Android разделяет входящий звук в соответствии со следующими правилами:
- Звонок всегда принимает аудиосигнал.
- Приложение может записывать звук, если оно является службой специальных возможностей .
Приложение может захватить голосовой вызов, если это привилегированное (предустановленное) приложение с разрешением
CAPTURE_AUDIO_OUTPUT
.Чтобы захватить восходящий канал (TX), нисходящий канал (RX) голосового вызова или оба канала, приложение должно указать источники звука
MediaRecorder.AudioSource.VOICE_UPLINK
илиMediaRecorder.AudioSource.VOICE_DOWNLINK
и/или устройствоAudioDeviceInfo.TYPE_TELEPHONY
.
Поведение Android 11
Android 11 (API уровня 30) соблюдает описанную выше схему приоритетов Android 10. Он также предоставляет новые методы в AudioRecord
, MediaRecorder
и AAudioStream
, которые включают и отключают возможность одновременного захвата звука, независимо от выбранного варианта использования.
Новые методы:
-
AudioRecord.Builder.setPrivacySensitive()
-
AudioRecord.isPrivacySensitive()
-
MediaRecorder.setPrivacySensitive()
-
MediaRecorder.isPrivacySensitive()
-
AAudioStreamBuilder_setPrivacySensitive()
-
AAudioStream_isPrivacySensitive()
Когда setPrivacySensitive()
имеет true
, вариант использования захвата является частным, и даже привилегированный помощник не может производить захват одновременно. Эта настройка переопределяет поведение по умолчанию, которое зависит от источника звука. Например, VOICE_COMMUNICATION
является частным по умолчанию, а UNPROCESSED
— нет.
Изменения конфигурации
Когда несколько приложений одновременно захватывают звук, только одно или два из них «активны» (получают звук); остальные отключены (получают тишину). Когда активные приложения меняются, звуковая структура может перенастроить аудиотракты в соответствии со следующими правилами:
- Устройство аудиовхода для каждого активного приложения может меняться (например, со встроенного микрофона на подключенную Bluetooth-гарнитуру).
- Включается предварительная обработка, связанная с активным приложением с наивысшим приоритетом. Вся остальная предварительная обработка игнорируется.
Поскольку активное приложение может быть отключено, когда приложение с более высоким приоритетом становится активным, вы можете зарегистрировать AudioManager.AudioRecordingCallback на объекте AudioRecord
или MediaRecorder
, чтобы получать уведомления об изменении конфигурации. Возможные изменения могут быть следующими:
- Захват с отключенным или отключенным звуком
- Устройство изменено
- Предварительная обработка изменена
- Изменены свойства потока (частота дискретизации, маска канала, формат выборки)
Вы должны вызвать AudioRecord.registerAudioRecordingCallback()
до начала захвата. Обратный вызов выполняется только тогда, когда приложение получает аудио и происходит изменение.
Метод onRecordingConfigChanged()
возвращает AudioRecordingConfiguration
, содержащий текущее состояние аудиозахвата. Используйте следующие методы, чтобы узнать об изменении:
-
isClientSilenced()
- Возвращает значение true, если звук, возвращаемый клиенту, в настоящее время отключается из-за политики захвата.
-
getAudioDevice()
- Возвращает активное аудиоустройство.
-
getEffects()
- Возвращает активный эффект предварительной обработки. Обратите внимание, что активный эффект может не совпадать с возвращаемыми
getClientEffects()
если клиент не является активным приложением с наивысшим приоритетом. -
getFormat()
- Возвращает свойства потока. Обратите внимание, что фактические аудиоданные, полученные клиентом, всегда соответствуют требуемому формату, возвращаемому
getClientFormat()
. Фреймворк автоматически выполняет необходимую передискретизацию, канал и преобразование формата из формата, используемого на аппаратном интерфейсе, в формат, указанный клиентом. -
AudioRecord.getActiveRecordingConfiguration()
. - Возвращает активную конфигурацию записи.
Общий вид всех активных записей на устройстве можно получить, вызвав AudioManager.getActiveRecordingConfigurations()
.