Аудиофокус запрещен что это
Аудиофокус — управление доступом к звуковой подсистеме
Это перевод статьи Respecting Audio Focus Kristan Uccello, Google Developer Relations
Считается грубым перебивать во время доклада, это показывает неуважение к докладчику и раздражает аудиторию. Если ваше приложение не учитывает правила работы с аудиофокусом, значит, оно не уважает остальные приложения и раздражает пользователя. Если Вы никогда не слышали об аудиофокусе, стоит обратить внимание на документацию Android developer training material.
Когда несколько приложений могут воспроизводить аудио важно думать о том, как они будут взаимодействовать. Чтобы избежать ситуации когда все плееры играют одновременно Андроид использует понятие аудиофокуса для контроля воспроизведения звуков: ваше приложение должно воспроизводить аудио только тогда, когда оно получило аудиофокус. В этой статье описаны несколько советов о том, как правильно и наилучшим для пользователя образом обрабатывать изменения состояния аудиофокуса.
Запрос аудиофокуса
Не надо быть жадным и запрашивать аудиофокус прямо в момент старта приложения; лучше подождать, пока приложение не начнет что-то делать с аудиопотоком. При получении аудиофокуса через сервис AudioManager, можно воспользоваться константами AUDIOFOCUS_GAIN* для обозначения необходимого режима фокуса.
В примере мы запрашиваем постоянный аудиофокус. Вместо этого, мы могли бы запросить временный (AUDIOFOCUS_GAIN_TRANSIENT) фокус, который подходит для воспроизведения звуков длительностью до 45 секунд.
Еще приложение может использовать режим “крякания” (AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) для ситуаций, когда допустимо совместное использование аудиоподсистемы вместе с другими приложениями (например, для фразы “жги еще” в фитнес-приложении, ожидая, что фоновая музыка не будет прерываться). Приложение, запрашивающее фокус в режиме “крякания”, не должно использовать аудиоподсистему дольше 15 секунд подряд.
Обрабатываем изменения состояния аудиофокуса
Для обработки событий изменения состояния аудиофокуса приложение должно создать экземпляр OnAudioFocusChangeListener. В этом обработчике необходимо обработать события AUDIOFOCUS_GAIN* и AUDIOFOCUS_LOSS*. Стоит заметить, что событие AUDIOFOCUS_GAIN имеет несколько особенностей, описанных во втором примере.
Константа AUDIOFOCUS_GAIN используется в коде в двух различных ролях. Во-первых, для получения аудиофокуса как в примере 1. При этом не происходит событие обработчика OnAudioFocusChangeListener, то есть при успешном запросе (и получении) аудиофокуса обработчик НЕ получит соответствующее событие AUDIOFOCUS_GAIN.
AUDIOFOCUS_GAIN также используется в реализации OnAudioFocusChangeListener как вариант события. Как указано ранее, событие AUDIOFOCUS_GAIN не возбуждается при запросе аудиофокуса. Напротив, оно может произойти только после возникновения соответствующего события AUDIOFOCUS_LOSS*. AUDIOFOCUS_GAIN — единственная константа, которая используется в обеих ситуациях.
Существуют четыре ситуации, которые необходимо учитывать в обработчике события изменения состояния аудиофокуса. Когда приложение получает событие AUDIOFOCUS_LOSS, это обычно означает, что обратно аудиофокус оно не получит. В этом случае приложение должно освободить ресурсы, связанные с аудиоподсистемой, и остановить воспроизведение. В качестве примера, представьте, что пользователь слушает музыку через ваше приложение, а затем запускает игру, которая забирает аудиофокус у аудиоплеера. Невозможно предсказать, через сколько времени пользователь закроет игру. Скорее всего, он перейдет на главный экран (оставив игру в фоне) и запустит еще одно приложение. Или он вернется в аудиоплеер, возобновив его работу, что потребует нового запроса аудиофокуса в onResume.
Однако есть другой случай, достойный обсуждения. Существует разница между потерей аудиофокуса навсегда (как в примере выше) или временно. Когда приложение получает событие AUDIOFOCUS_LOSS_TRANSIENT, ожидается, что приложение приостановит использование аудио до тех пор, пока оно не получит событие AUDIOFOCUS_GAIN. Когда возникает событие AUDIOFOCUS_LOSS_TRANSIENT приложение должно запомнить, что потеря фокуса временная, для того, чтобы при возврате фокуса разобраться, какое поведение корректно. (см. пример 2).
Иногда приложение теряет аудиофокус (т.е. получает AUDIOFOCUS_LOSS), а прервавшее приложение завершается, или каким-то другим образом теряет аудиофокус. В этой ситуации последнее приложение, которое имело аудиофокус, может получить событие AUDIOFOCUS_GAIN.
В последующем событии AUDIOFOCUS_GAIN приложение должно понять, получило ли оно аудиофокус после временной потери и должно просто возобновить проигрывание, либо восстановиться и настроить воспроизведение после полной потери фокуса.
Если приложение использует аудио только на короткое время (не более 45 секунд), оно должно запрашивать аудиофокус в режиме AUDIOFOCUS_GAIN_TRANSIENT и отпускать его сразу после завершения воспроизведения или записи звука. Аудиофокус в системе обрабатывается как стек: фокус получает то приложение, которое владело им последним.
Когда аудиофокус получен, самое время создать MediaPlayer или MediaRecorder и зарезервировать ресурсы. Также когда приложение получает AUDIOFOCUS_LOSS, хорошей практикой является освобождение всех зарезервированных ресурсов. Существует три варианта получения аудиофокуса, соответствующие разным вариантам потери фокуса. Неплохо бы явно обрабатывать все варианты потери фокуса в обработчике OnAudioFocusChangeListener.
Аудиофокус — управление доступом к звуковой подсистеме
Это перевод статьи Respecting Audio Focus Kristan Uccello, Google Developer Relations
Считается грубым перебивать во время доклада, это показывает неуважение к докладчику и раздражает аудиторию. Если ваше приложение не учитывает правила работы с аудиофокусом, значит, оно не уважает остальные приложения и раздражает пользователя. Если Вы никогда не слышали об аудиофокусе, стоит обратить внимание на документацию Android developer training material.
Когда несколько приложений могут воспроизводить аудио важно думать о том, как они будут взаимодействовать. Чтобы избежать ситуации когда все плееры играют одновременно Андроид использует понятие аудиофокуса для контроля воспроизведения звуков: ваше приложение должно воспроизводить аудио только тогда, когда оно получило аудиофокус. В этой статье описаны несколько советов о том, как правильно и наилучшим для пользователя образом обрабатывать изменения состояния аудиофокуса.
Запрос аудиофокуса
Не надо быть жадным и запрашивать аудиофокус прямо в момент старта приложения; лучше подождать, пока приложение не начнет что-то делать с аудиопотоком. При получении аудиофокуса через сервис AudioManager, можно воспользоваться константами AUDIOFOCUS_GAIN* для обозначения необходимого режима фокуса.
В примере мы запрашиваем постоянный аудиофокус. Вместо этого, мы могли бы запросить временный (AUDIOFOCUS_GAIN_TRANSIENT) фокус, который подходит для воспроизведения звуков длительностью до 45 секунд.
Еще приложение может использовать режим “крякания” (AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) для ситуаций, когда допустимо совместное использование аудиоподсистемы вместе с другими приложениями (например, для фразы “жги еще” в фитнес-приложении, ожидая, что фоновая музыка не будет прерываться). Приложение, запрашивающее фокус в режиме “крякания”, не должно использовать аудиоподсистему дольше 15 секунд подряд.
Обрабатываем изменения состояния аудиофокуса
Для обработки событий изменения состояния аудиофокуса приложение должно создать экземпляр OnAudioFocusChangeListener. В этом обработчике необходимо обработать события AUDIOFOCUS_GAIN* и AUDIOFOCUS_LOSS*. Стоит заметить, что событие AUDIOFOCUS_GAIN имеет несколько особенностей, описанных во втором примере.
Константа AUDIOFOCUS_GAIN используется в коде в двух различных ролях. Во-первых, для получения аудиофокуса как в примере 1. При этом не происходит событие обработчика OnAudioFocusChangeListener, то есть при успешном запросе (и получении) аудиофокуса обработчик НЕ получит соответствующее событие AUDIOFOCUS_GAIN.
AUDIOFOCUS_GAIN также используется в реализации OnAudioFocusChangeListener как вариант события. Как указано ранее, событие AUDIOFOCUS_GAIN не возбуждается при запросе аудиофокуса. Напротив, оно может произойти только после возникновения соответствующего события AUDIOFOCUS_LOSS*. AUDIOFOCUS_GAIN — единственная константа, которая используется в обеих ситуациях.
Существуют четыре ситуации, которые необходимо учитывать в обработчике события изменения состояния аудиофокуса. Когда приложение получает событие AUDIOFOCUS_LOSS, это обычно означает, что обратно аудиофокус оно не получит. В этом случае приложение должно освободить ресурсы, связанные с аудиоподсистемой, и остановить воспроизведение. В качестве примера, представьте, что пользователь слушает музыку через ваше приложение, а затем запускает игру, которая забирает аудиофокус у аудиоплеера. Невозможно предсказать, через сколько времени пользователь закроет игру. Скорее всего, он перейдет на главный экран (оставив игру в фоне) и запустит еще одно приложение. Или он вернется в аудиоплеер, возобновив его работу, что потребует нового запроса аудиофокуса в onResume.
Однако есть другой случай, достойный обсуждения. Существует разница между потерей аудиофокуса навсегда (как в примере выше) или временно. Когда приложение получает событие AUDIOFOCUS_LOSS_TRANSIENT, ожидается, что приложение приостановит использование аудио до тех пор, пока оно не получит событие AUDIOFOCUS_GAIN. Когда возникает событие AUDIOFOCUS_LOSS_TRANSIENT приложение должно запомнить, что потеря фокуса временная, для того, чтобы при возврате фокуса разобраться, какое поведение корректно. (см. пример 2).
Иногда приложение теряет аудиофокус (т.е. получает AUDIOFOCUS_LOSS), а прервавшее приложение завершается, или каким-то другим образом теряет аудиофокус. В этой ситуации последнее приложение, которое имело аудиофокус, может получить событие AUDIOFOCUS_GAIN.
В последующем событии AUDIOFOCUS_GAIN приложение должно понять, получило ли оно аудиофокус после временной потери и должно просто возобновить проигрывание, либо восстановиться и настроить воспроизведение после полной потери фокуса.
Если приложение использует аудио только на короткое время (не более 45 секунд), оно должно запрашивать аудиофокус в режиме AUDIOFOCUS_GAIN_TRANSIENT и отпускать его сразу после завершения воспроизведения или записи звука. Аудиофокус в системе обрабатывается как стек: фокус получает то приложение, которое владело им последним.
Когда аудиофокус получен, самое время создать MediaPlayer или MediaRecorder и зарезервировать ресурсы. Также когда приложение получает AUDIOFOCUS_LOSS, хорошей практикой является освобождение всех зарезервированных ресурсов. Существует три варианта получения аудиофокуса, соответствующие разным вариантам потери фокуса. Неплохо бы явно обрабатывать все варианты потери фокуса в обработчике OnAudioFocusChangeListener.
Таблица 1. Смысл констант получения и потери аудиофокуса
GAIN | LOSS |
AUDIOFOCUS_GAIN | AUDIOFOCUS_LOSS |
AUDIOFOCUS_GAIN_TRANSIENT (*) | AUDIOFOCUS_LOSS_TRANSIENT |
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK (*) | AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK |
Замечание: константа используется в двух местах. Когда запрашивается аудиофокус, она передается как подсказка AudioManager; она же используется как вариант события в OnAudioFocusChangeListener. Константы получения фокуса, обозначенные (*), используются только при запросе аудиофокуса. Константы потери фокуса используются только в обработчике OnAudioFocusChangeListener.
Таблица 2. Типы аудиопотоков.
Тип | Описание |
STREAM_ALARM | Будильник |
STREAM_DTMF | Тоновый набор |
STREAM_MUSIC | Воспроизведение мультимедиа (музыка, подкасты, видео) |
STREAM_NOTIFICATION | Уведомления |
STREAM_RING | Телефонный звонок |
STREAM_SYSTEM | Системные звуки |
Приложение запрашивает аудиофокус у AudioManager (как в примере по ссылке в конце статьи). Параметрами являются необязательный обработчик, подсказка с типом аудиоканала (таблица 2) и тип аудиофокуса из таблицы 1. Любая инициализация аудио должна производиться, только если система разрешила получение аудиофокуса (AudioManager.AUDIOFOCUS_REQUEST_GRANTED).
Замечание: Если происходит телефонный разговор, система не разрешит получение аудиофокуса (AUDIOFOCUS_REQUEST_FAILED) и не отправит приложению событие AUDIOFOCUS_GAIN после завершения звонка.
Краткое описание реакции приложения на события OnAudioFocusChange() описано в таблице 3.
В случае потери аудиофокуса необходимо быть уверенным, что фокус потерян окончательно. Если приложение получает событие AUDIOFOCUS_LOSS_TRANSIENT или AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK, оно может придержать зарезервированные ресурсы (не вызывать release()), т.к. скорее всего скоро произойдет новое событие изменения аудиофокуса. Стоит сохранять информацию о временной потере фокуса в каком-нибудь флаге или путем перехода в отдельную вершину графа состояний.
Если приложение запрашивало постоянный аудиофокус в режиме AUDIOFOCUS_GAIN и получило событие AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK, подходящей реакцией будет сделать громкость потише (не забыв сохранить старое значение громкости) и затем вернуть громкость при получении события AUDIOFOCUS_GAIN (см. картинку).
Таблица 3. Реакция приложения при изменении состояния аудиофокуса.
Тип смены фокуса | Реакция |
AUDIOFOCUS_GAIN | Событие получения после события потери фокуса: Возобновить воспроизведение медиа, если состояние приложения не противоречат этому. Например, пользователь нажал паузу до события потери фокуса. |
AUDIOFOCUS_LOSS | Остановить воспроизведение, освободить ресурсы |
AUDIOFOCUS_LOSS_TRANSIENT | Приостановить воспроизведение и сохранить флажок о том, что потеря фокуса временная, для того, чтобы при обработке AUDIOFOCUS_GAIN можно было при необходимости возобновить воспроизведение. Не освобождать ресурсы. |
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK | Сделать громкость тише или приостановить воспроизведение, не забывая отслеживать состояние как в случае с AUDIOFOCUS_LOSS_TRANSIENT. Не освобождать ресурсы. |
Заключение и что почитать
Русские Блоги
Два или более приложения Android могут одновременно воспроизводить звук в один и тот же выходной поток. Система все перемешивает. Хотя это технически впечатляет, пользователей это очень раздражает. Чтобы избежать одновременного воспроизведения всех музыкальных приложений, в Android введена концепция фокусировки звука. Только одно приложение может фокусировать звук одновременно.
Когда вашему приложению требуется вывод звука, оно должно запрашивать фокус звука. Когда он находится в фокусе, он может воспроизводить звук. Однако после фокусировки звука вы не сможете удерживать его, пока не закончите воспроизведение. Другое приложение может запросить фокус, и это вытеснит ваш аудио фокус. В этом случае ваше приложение должно приостановить воспроизведение или уменьшить громкость, чтобы пользователям было легче услышать новый источник звука.
Аудио ориентировано на сотрудничество. Приложениям рекомендуется следовать рекомендациям по аудиофокусу, но система не применяет эти правила. Если приложение хочет продолжить громкое воспроизведение после потери фокуса звука, ничто не может его остановить. Это плохой опыт, и пользователи, скорее всего, удалят приложения, у которых такой плохой опыт.
Хорошо работающее звуковое приложение должно управлять звуковым фокусом в соответствии со следующими общими рекомендациями:
Обработка аудиофокуса различается в зависимости от версии Android:
Аудио фокус на Android 8.0 и выше
Начиная с Android 8.0 (уровень API 26), когда вы вызываете requestAudioFocus (), вы должны предоставить параметр AudioFocusRequest. Чтобы освободить аудиофокус, вызовите метод AbandonAudioFocusRequest (), который также принимает AudioFocusRequest в качестве параметра. При запросе и отказе от фокуса следует использовать один и тот же экземпляр AudioFocusRequest.
Чтобы создать AudioFocusRequest, используйте AudioFocusRequest. Builder. Поскольку запрос фокуса всегда должен указывать запрошенный тип, этот тип включается в конструктор конструктора. Используйте метод построителя, чтобы задать другие поля запроса.
нужно FocusGain Поля; все остальные поля необязательны. Объясните основной метод:
audioattributes описывает варианты использования системных приложений. Когда приложение получает или теряет фокус звука, система будет смотреть на них. Атрибуты заменяют концепцию типов потоков. В Android 8.0 (уровень API 26) и выше любая операция, кроме регулировки громкости, не поддерживает тип потока. Используйте те же атрибуты в запросе фокуса, что и в аудиоплеере (как показано в таблице ниже).
Используйте одинAudioAttributes.BuilderСначала укажите атрибуты, а затем используйте этот метод для назначения атрибутов запросу.
Если не указано, AudioAttributes по умолчанию AudioAttributes.USAGE_MEDIA 。
Когда другое приложение запрашивает использование AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK При выполнении обработки фокуса сфокусированное приложение обычно не получает обратный вызов onAudioFocusChange (), потому что система может выполнить эту операцию сама. Если вам нужно приостановить воспроизведение вместо уменьшения громкости, вызовите setWillPauseWhenDucked (true), создайте и установите OnAudioFocusChangeListener, как описано в разделе «Автоматическое приглушение» ниже.
Когда фокус заблокирован другим приложением, запрос аудиофокуса может завершиться ошибкой. Этот метод допускает отложенное усиление фокуса: возможность асинхронного получения фокуса, когда фокус доступен.
Обратите внимание, что усиление с задержкой фокуса допустимо только при указании AudioManager.OnAudioFocusChangeListener. Поскольку ваше приложение должно получить обратный вызов, чтобы знать, что фокус был разрешен для получения.
OnAudioFocusChangeListener требуется только тогда, когда в запросе указано willPauseWhenDucked (true) или setAcceptsDelayedFocusGain (true).
В следующем примере показано, как использовать AudioFocusRequest.Bulder для создания AudioFocusRequest и запроса и отказа от фокуса звука:
Автоматическое ныряние
В Android 8.0 (уровень API 26), когда другое приложение использует AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK При запросе фокуса система может снизить громкость и возобновить воспроизведение звука, не вызывая приложение onAudioFocusChange() Перезвонить.
В приложениях для воспроизведения музыки и видео автоматическое уменьшение громкости является приемлемым поведением, но бесполезно при воспроизведении голосового содержимого (например, в приложении аудиокниги). В этом случае приложение следует приостановить.
Задержка в фокусе
Чтобы обрабатывать задержанное усиление фокуса, вы должны создать OnAudioFocusChangeListener, который использует метод обратного вызова onAudioFocusChange () для достижения желаемого поведения и зарегистрировать слушателя, вызвав setOnAudioFocusChangeListener ().
До Android 8.0 аудио фокус
Когда вы вызываете requestAudioFocus (), вы должны указать подсказку продолжительности, которая может использоваться другим приложением, которое в данный момент сфокусировано и воспроизводит:
Если вы планируете воспроизводить звук в обозримом будущем (например, при воспроизведении музыки), запросите постоянный звуковой фокус (AUDIOFOCUS_GAIN), и вы хотите, чтобы предыдущий держатель звукового фокуса прекратил воспроизведение.
Запросите временный фокус (AUDIOFOCUS_GAIN_TRANSIENT), если вы хотите воспроизводить звук только в течение короткого времени и хотите, чтобы предыдущий владелец приостановил воспроизведение.
Запросите переходный фокус приглушения (AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK), чтобы указать, что вы хотите воспроизводить звук только в течение короткого периода времени, и если предыдущий владелец фокуса «пригнул» (опустил) свой аудиовыход, вы все равно можете продолжить воспроизведение. Оба аудиовыхода микшируются в аудиопоток. Ducking особенно подходит для приложений, которые периодически используют аудиопотоки, например, для звуковых дорожек.
Для метода requestAudioFocus () также требуется AudioManager.OnAudioFocusChangeListener. Этот слушатель должен быть создан в том же действии или службе, что и ваш медиа-сеанс. Он реализует обратный вызов onAudioFocusChange (), и ваше приложение получит этот обратный вызов, когда другие приложения получат или откажутся от аудио-фокуса.
Следующий фрагмент кода запрашивает постоянный фокус аудио на потоке STREAM_MUSIC и регистрирует OnAudioFocusChangeListener для обработки последующих изменений в фокусе звука. (ПодРеакция на изменение звукового фокусаЧасть обсуждает смену слушателей. )
Когда вы закончите играть, вызовите AbandonAudioFocus ().
Это уведомит систему о том, что вам больше не нужен фокус, и отменит регистрацию связанного OnAudioFocusChangeListener. Если вы запрашиваете временный фокус, это уведомит приостановленное или приглушенное приложение, что оно может продолжить воспроизведение или возобновить громкость.
Реакция на изменение звукового фокуса
Когда приложение получает звуковой фокус, оно должно иметь возможность освободить его, когда другое приложение запрашивает собственный звуковой фокус. Когда это происходит, ваше приложение получает вызов метода onAudioFocusChange () в AudioFocusChangeListener, который был указан при вызове requestAudioFocus ().
Параметр focusChange, переданный в onAudioFocusChange (), указывает на происходящее изменение. Он соответствует подсказке продолжительности, используемой приложением для получения фокуса. Ваше приложение должно ответить соответствующим образом.
Переходный не в фокусе
Если изменение фокуса временное (AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK или AUDIOFOCUS_LOSS_TRANSIENT), приложение должно уменьшить громкость (если вы не полагаетесь на автоматическое приглушение) или приостановить воспроизведение, но сохранить то же состояние другими способами.
Во время временной потери фокуса звука вы должны продолжать отслеживать изменения в фокусе звука и подготовиться к возобновлению обычного воспроизведения после восстановления фокуса. Когда блокирующее приложение теряет фокус, вы получите обратный вызов ( AUDIOFOCUS_GAIN ). На этом этапе вы можете восстановить нормальный уровень громкости или возобновить воспроизведение.
Постоянная потеря внимания
Если потеря фокуса звука необратима ( AUDIOFOCUS_LOSS ), другое приложение воспроизводит звук. Ваше приложение должно немедленно приостановить воспроизведение, потому что оно никогда не получит AUDIOFOCUS_GAIN Перезвонить. Чтобы возобновить воспроизведение, пользователь должен предпринять явные действия, например нажать элемент управления воспроизведением в уведомлении или пользовательском интерфейсе приложения.
Следующий фрагмент кода демонстрирует, как реализовать OnAudioFocusChangeListener и его обратный вызов onAudioFocusChange (). Обратите внимание, что обработчик используется для задержки выполнения обратного вызова операции остановки, когда звуковой фокус теряется навсегда.
Обработчик использует Runnable, как показано ниже.
Управление аудио-фокусом
Важно знать как должны взаимодействовать несколько приложений, который потенциально могут проигрывать звук. Android использует аудио-фокус, чтобы только одно приложений, захватившее фокус, могло воспроизводить звук в текущий момент времени.
Прежде чем начать воспроизведение, ваше приложение должно запросить и получить аудио-фокус. Кроме того, приложение должно следить за потерей фокуса и правильным образом обрабатывать такие ситуации.
Запрос аудио-фокуса
Итак, приложение должно захватить аудио-фокус нужного аудио-потока перед началом воспроизведения любых звуков. Это можно сделать с помощью метода requestAudioFocus(), который возвращает AUDIOFOCUS_REQUEST_GRANTED в случае успеха.
Вам нужно указать, какой поток вы используете и ожидаете временный или постоянный фокус. Запросите временный фокус, если собираетесь воспроизводить короткие звуки (например инструкции по навигации). Запросите постоянный фокус, если планируете без остановки воспроизводить звук в обозримом будущем (например, проигрывать музыку в плеере).
В следующем примере показано как запросить постоянный фокус для музыкального потока. Вы должны запросит фокус немедленно перед началом воспроизведения, например сразу после нажатия пользователем кнопки “воспроизвести” в плеере или при начале нового уровня в игре (для воспроизведения музыки на заднем фоне):
Сразу после окончания воспроизведения вызовите метод abandonAudioFocus() для отказа от фокуса. Это уведомит систему о том, что аудио-фокус вам больше не нужен и отменит регистрацию AudioManager.OnAudioFocusChangeListener. В случае отказа от временного фокуса, любое прерванное приложение может продолжить воспроизведение.
Для запроса временного фокуса есть дополнительный параметр: хотите ли вы использовать “ducking”. “Правильные” приложения обычно немедленно заглушают воспроизведение при потере фокуса. При запросе временного фокуса можно использовать ducking. Вы сообщаете приложению, что оно может продолжить воспроизведение немного убавив громкость, пока фокус находится у вас.
Ducking особенно подходит для приложений, которые прерывисто используют аудио-поток, например навигаторы, которые указывают направление движения.
Всякий раз, когда другое приложение запрашивает фокус как описано выше, оно выбирает между постоянным и временным (с поддержкой ducking или нет) фокусом, которые вы указали при регистрации.
Обработка потери аудио-фокуса
Если ваше приложение может запросить фокус, оно может его также потерять при запросе другого приложения. Как приложение будет обрабатывать потерю фокуса, зависит от того, как он был потерян.
Метод обратного вызова onAudioFocusChange() вызывается при изменении слушателя, которого вы зарегистрировали при запросе фокуса и принимает в качестве параметра тип события. Возможные события являются близнецами для типов фокуса, которые мы уже рассмотрели – постоянная потеря, временная потеря и временная потеря с разрешенным ducking.
Вообще говоря, временная потеря фокуса должна приглушить звук в вашем приложении, но оставить остальное состояние прежним. Вы должны продолжать отслеживать изменения фокуса и быть готовы возобновить воспроизведение, как только фокус вернулся.
Если потеря фокуса является постоянной, значит другое приложение сейчас используется для прослушивания аудио и ваше приложение должно эффективно себя завершить. Эффективно завершить, значит остановить воспроизведение, выключить обработчики нажатия на медиа-кнопки и отказаться от фокуса. Таким образом, чтобы возобновить воспроизведение в вашем приложении, пользователю будет необходимо явно указать вашему приложению это сделать.
В следующем примере показано, как приостановить воспроизведение при временной потере фокуса и заново его возобновить как только фокус вернулся. Если потеря является постоянной, отключить обработчики медиа-кнопок и остановить отслеживание фокуса: