AudioManager вводит задержку в setMode(MODE_IN_COMMUNICATION)
Я пытаюсь воспроизвести звук через динамик, даже если наушники включены, НО, если в фоновом режиме воспроизводится музыка, я хочу, чтобы музыка воспроизводилась в наушниках до тех пор, пока звук не будет воспроизведен.
Поэтому я предпринимаю следующие шаги:
- Перед воспроизведением звука я получаю audioFocus, поэтому вся фоновая музыка останавливается
- После получения audioFocus я установил
MODE_COMMUNICATION
AudioManager, поэтому звук может быть воспроизведен на динамике. - После окончания звука я оставляю AudioFocus и возвращаюсь обратно
MODE_NORMAL
вAudioManager
, поэтому фоновая музыка может продолжать играть в наушниках.
Странно то, что это зависит от устройства, на некоторых устройствах это нормально, но на устройствах Nexus 6P (Huawei) после установки MODE_COMMUNICATION
Перед воспроизведением звука задерживается 3-4 секунды. Если я проигрываю звук без задержки, он не воспроизводится ни на динамике, ни на наушниках.
ВОПРОС
Как узнать, какую задержку установить до воспроизведения звука? Есть ли какой-нибудь слушатель, которого я могу подключить, так что можете уведомить меня об этом после установки MODE_COMMUNICATION
звук готов к игре?
Я не хочу устанавливать задержку, даже если она не нужна!
Решение заключается не в установке режима в конструктор класса (чтобы пропустить задержку), потому что мне нужно, чтобы звук воспроизводился на динамике в определенный момент!
PS: я играю звук с AudioTrack
, но я попробовал с MediaPlayer
а также (настройка setAudioStreamType(MODE_IN_COMMUNICATION)
), но безуспешно, задержка еще есть!
Так какие-нибудь предложения?
2 ответа
Если устройство поддерживает уровень API 31 или выше, можно использовать AudioManager.OnModeChangedListener для обнаружения изменения режима звука на MODE_IN_COMMUNICATION, примерно так:
val am = getSystemService(AUDIO_SERVICE) as AudioManager
var audioModeChangedListener = AudioManager.OnModeChangedListener { mode ->
if (mode == AudioManager.MODE_IN_COMMUNICATION) {
Log.d(TAG, "Audio mode changed to MODE_IN_COMMUNICATION")
if (audioModeChangedListener != null) {
am.removeOnModeChangedListener(audioModeChangedListener!!)
audioModeChangedListener = null
}
// start playing
}
}
am.addOnModeChangedListener(mainExecutor, audioModeChangedListener!!)
Log.d(TAG, "Setting audio mode to MODE_IN_COMMUNICATION")
am.mode = AudioManager.MODE_IN_COMMUNICATION
Если кто-нибудь наткнется на этот пост, то, что сработало для меня, было позвонить AudioManager.setMode()
а затем воссоздавая мой MediaPlayer
(через конструктор, а не create()
) и используя setAudioAttributes()
для изменения источника вывода.
Kotlin фрагмент:
fun switchOutput(inCommunication: Boolean) {
//STEP 1: Change the AudioManager's audio mode
if(inCommunication) {
audioManager.mode = AudioManager.MODE_IN_CALL
audioManager.isSpeakerphoneOn = false
} else {
audioManager.mode = AudioManager.MODE_NORMAL
audioManager.isSpeakerphoneOn = true
}
//STEP 2: Recreate the MediaPlayer
if (player != null) {
try {
player?.stop()
} catch (e: RuntimeException) {
} finally {
player?.reset()
player?.release()
player = null
}
}
player = MediaPlayer()
try {
val streamType =
if (inCommunication) AudioManager.STREAM_VOICE_CALL
else AudioManager.STREAM_MUSIC
player?.setDataSource(dataSource)
player?.setAudioAttributes(AudioAttributes.Builder()
.setLegacyStreamType(streamType)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build())
player?.prepare()
player?.start()
} catch (e: java.lang.Exception) {}
}
Надеюсь это поможет:)
PS Обратите внимание, что я использовал MODE_IN_CALL
вместо того MODE_IN_COMMUNICATION