即使耳机打开,我也试图在扬声器上播放声音,但是如果背景音乐在播放,我希望在播放声音之前在耳机上播放音乐。
所以我要采取后续步骤:
MODE_COMMUNICATION
设置为
AudioManager,因此可以在扬声器上播放声音。 MODE_NORMAL
AudioManager
,所以背景音乐可以在耳机上继续播放。奇怪的是它取决于设备,在某些设备上这是可以的,但是在设置
MODE_COMMUNICATION
后的Nexus 6P(华为)设备上有延迟3-4秒才能播放声音。如果我没有延迟地播放声音,它既不会播放到扬声器也不会播放到耳机。
问题
我怎么知道在播放声音之前要设置多少延迟?有没有我可以附加的监听器,所以可以通知我设置后
MODE_COMMUNICATION
声音可以播放了吗?
我不想设置延迟,即使没有必要!
解决方案是不在类的构造函数中设置模式(跳过延迟),因为我需要在特定时刻在扬声器上播放声音!
P.S:我是用
AudioTrack
播放声音,但我也试过MediaPlayer
(设置setAudioStreamType(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) {}
}
希望这有帮助:)
附言请注意,我使用了
MODE_IN_CALL
而不是 MODE_IN_COMMUNICATION
如果设备支持 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