Для избежания одновременного воспроизведения музыки разными приложениями Android использует понятие аудио фокус. Музыку может воспроизводить только то приложение, которое в данный момент времени владеет аудио фокусом, поэтому до начала воспроизведения музыки приложение должно запросить и получить аудио фокус. Более того оно должно знать, как отслеживать потерю аудио фокуса и соответствующим образом реагировать в случае потери.
Запрос на получение аудио фокуса выполняется вызовом метода requestAudioFocus(), который в случае успеха возвращает константу AUDIOFOCUS_REQUEST_GRANTED. При этом необходимо указывать какой поток используется и какого рода аудио фокус требуется: временный или постоянный. Временный фокус предполагает воспроизведение короткого аудио произведения, например, инструкций по навигации. Постоянный фокус предполагает длительное воспроизведение аудио контента, например, прослушивание музыки.
Запрос фокуса необходимо выполнять непосредственно перед началом воспроизведения, например, когда пользователь нажимает кнопку play. Следующий код демонстрирует запрос на постоянный аудио фокус:
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
//запрос аудио фокуса для воспроизведения
int result = am.requestAudioFocus(afChangeListener,
//используя поток музыки
AudioManager.STREAM_MUSIC,
//запрос постоянного фокуса
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
// начало воспроизведения
}
Как только заканчивается воспроизведение, необходимо вызвать метод abandonAudioFocus(), который сообщает системе, что аудио фокус больше не требуется и отменяет регистрацию соответствующего AudioManager.OnAudioFocusChangeListener В случае освобождения временного фокуса, любое приостановленное приложение может продолжить воспроизведение.
//освобождение аудио фокуса при завершении воспроизведения
am.abandonAudioFocus(afChangeListener);
При запросе временного аудио фокуса существует дополнительная опция: возможность так называемого "ducking". В обычных условиях приложение, теряющее аудио фокус, заглушает воспроизведение, при запросе временного аудио фокуса с возможностью "ducking", работавшему до этого аудио приложению дается возможность лишь приглушить воспроизведение до возвращения фокуса к нему.
//запрос аудио фокуса для воспроизведения
int result = am.requestAudioFocus(afChangeListener,
//используя поток музыки
AudioManager.STREAM_MUSIC,
//запрос фокуса
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// начало воспроизведения
}
"Ducking" особенно подходит для приложений, которые используют аудио поток периодически, например, для озвучивания рекомендаций водителю.
Приложение может потерять аудио фокус, как ему реагировать на потерю фокуса зависит от способа этой потери. Метод onAudioFocusChange() слушателя изменений аудио фокуса, зарегистрированного при запросе аудио фокуса, получает параметр, описывающий событие изменения фокуса. Потеря фокуса может быть постоянной или временной с возможностью "ducking" или без нее.
Временная потеря аудио фокуса заставляет приложение заглушить воспроизведение аудио потока, но сохраняет состояние воспроизведения. Необходимо следить за изменениями состояния аудио фокуса и быть готовым продолжить воспроизведение после возвращения фокуса.
Если потеря аудио фокуса является постоянной, приложение должно корректно завершиться, т.е. остановить воспроизведение, удалить слушателей событий от медиа кнопок и освободить аудио фокус. Для возобновления проигрывания аудио контента необходимо дождаться действия от пользователя, например, нажатия кнопки play.
Следующий фрагмент кода описывает приостановку воспроизведения в случае временной потери фокуса, возобновление воспроизведения при возвращении фокуса. В случае постоянной потери выполняется отмена регистрации приемника событий нажатия медиа кнопок и останавливается отслеживание событий изменения фокуса.
OnAudioFocusChangeListener afChangeListener = new
OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT){
//приостановить воспроизведение
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
//продолжить воспроизведение
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
am.abandonAudioFocus(afChangeListener);
// прекратить воспроизведение
}
}
};
В случае временной потери аудио фокуса с возможностью "ducking" вместо паузы лучше использовать снижение уровня громкости.
"Ducking" это и есть процесс снижения уровня громкости воспроизведения аудио потока, чтобы позволить другому приложению воспроизвести свой аудио контент. Следующий фрагмент кода снижает громкость при временной потере фокуса, после возвращения фокуса восстанавливает прежний уровень громкости
OnAudioFocusChangeListener afChangeListener = new
OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
// снижение громкости
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// восстановление уровня громкости
}
}
};
Достарыңызбен бөлісу: |