научиться добавлять в приложения, поддерживающие воспроизведения аудио, возможностей:
Приложение ориентированное на пользователя должно предоставлять ему привычный способ работы, если дело касается воспроизведения аудио контента, то пользователь вправе ожидать возможности управления громкостью звука с помощью клавиш, предусмотренных для этого на самом устройстве. В том числе, если на устройстве досупны кнопки управляющие самим процессом воспроизведения звука, то их использование должно вызывать соответствующие действия над аудиопотоком, используемым в приложении.
Для начала необходимо понять какой аудио поток будет использовать приложение.
Android поддерживает отдельный аудио поток для воспроизведения музыки, входящих звонков, предупреждений, напоминаний, системных звуков. Это сделано, чтобы позволить пользователю управлять громкостью каждого потока независимо.
Большинство из этих потоков связывается с системными событиями, таким образом, если приложение не является заменой будильника, то аудио будет воспроизводиться в потоке STREAM_MUSIC (константа класса AudioManager).
По умолчанию кнопки управления громкостью изменяют громкость активного аудио потока, если в данный момент ничего не воспроизводится, регулируется громкость входящего звонка. Пользователь игрового приложения или аудиопроигрывателя, нажимая на кнопки управления громкостью, скорей всего ожидает изменения громкости игры или музыки, даже если в данный момент в приложении не воспроизводятся ни какие звуки.
Android предоставляет метод setVolumeControlStream() для задания аудио потока, громкость которого будет регулироваться соответствующими кнопками устройства. В метод onCreate() активности, в которой выполняется воспроизведение аудио, необходимо добавить строку:
setVolumeControlStream(AudioManager.STREAM_MUSIC);
На многих устройствах доступны кнопки управления воспроизведением: play, pause, stop, skip и previous. Как только пользователь нажимает на одну из этих кнопок, система рассылает сообщение о действии ACTION_MEDIA_BUTTON. Для обработки таких нажатий в приложении, необходимо в файле манифеста приложения зарегистрировать приемник широковещательных сообщений (BroadcastReceiver) следующим образом:
<receiver android:name=".RemoteControlReceiver"> <intent-filter> <action android:name="android.intent.action.MEDIA_BUTTON"/> </intent-filter> </receiver> </example>
В реализации приемника необходимо определять какая кнопка была нажата и вызвала рассылку широковещательных сообщений. Intent-объект содержит эту информацию в ключе EXTRA_KEY_EVENT, а класс KeyEvent содержит набор констант KEYCODE_MEDIA_*, для представления каждой возможной медиа кнопки, например, KEYCODE_MEDIA_PLAY_PAUSE или KEYCODE_MEDIA_NEXT (полный список констант можно найти в описании класса KeyEvent).
Как получить информацию о нажатии медиа кнопки и выполнить соответствующие действия показывает следующий код:
public class RemoteControlReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
KeyEvent event =
(KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()) {
// реакция на нажатие кнопки
}
}
}
}
Необходимо программно указывать, когда приложение может получать информацию о событиях нажатия медиа кнопок.
Сначала необходимо создать экземпляр класса AudioManager, который позволит регистрировать и отменять регистрацию приемника событий нажатия медиа кнопок:
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
Далее необходимо зарегистрировать приемник:
//начать прослушивание нажатий кнопок am.registerMediaButtonEventReceiver(RemoteControlReceiver);
Зарегистрированный приемник широковещательных сообщений будет единственным приемником всех событий нажатий медиа кнопок, поэтому необходимо отменить регистрацию приемника, как только пропадет неоходимость в нем:
//закончить прослушивание нажатий кнопок am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
Обычно приложения отменяют регистрацию большинства своих приемников, когда они становятся неактивными или невидимыми, т.е. при вызове метода onStop(). Для приложения, воспроизводящего аудио, обычно важно получать события нажатия кнопок тогда, когда оно невидимо, поэтому лучше регистрировать и снимать регистрацию приемника событий нажатия медиа кнопок, когда приложение получает или теряет аудио фокус, соответственно.
Для избежания одновременного воспроизведения музыки разными приложениями 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) {
// восстановление уровня громкости
}
}
};
Пользователи имеют возможность выбора при прослушивании аудио на Android устройствах. Большинство устройств имеют встроенный динамик, выход для наушников, поддержку A2DP аудио и т.д.
Поведение приложения может зависить от устройства, на которое направлен вывод аудио контента. Можно запросить AudioManager определить какое устройство используется для вывода аудио, динамик мобильного устройства, проводные наушники или Bluetooth устройство.
if (isBluetoothA2dpOn()) {
//адаптировать вывод для Bluetooth
} else if (isSpeakerphoneOn()) {
//адаптировать вывод для динамика устройства
} else if (isWiredHeadsetOn()) {
// адаптировать вывод для наушников
} else {
//никто его не слышит, аудио все еще играет?
}
Когда наушники отсоединяются или Bluetooth устройство становится недоступным, аудио поток автоматически перенаправляется на встроенный динамик. Если громкость воспроизведения высокая, то неожиданный шум из динамиков может неприятно удивить, особенно окружающих.
К счастью система рассылает сообщение ACTION_AUDIO_BECOMING_NOISY, когда это происходит. Хорошей практикой является привычка регистрировать приемник широковещательных сообщений для получения этого сообщения, каждый раз как приложение воспроизводит аудио. В случае с воспроизведением музыки пользователи обычно ожидают приостановки воспроизведения, в случае с играми ожидается существенное понижение уровня громкости.
private class NoisyAudioStreamReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
// приостановить воспроизведение
}
}
}
private IntentFilter intentFilter =
new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private void startPlayback() {
registerReceiver(myNoisyAudioStreamReceiver, intentFilter);
}
private void stopPlayback() {
unregisterReceiver(myNoisyAudioStreamReceiver);
}
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.