AudioManager在setMode中引入延迟(MODE_IN_COMMUNICATION)

时间:2017-12-06 14:41:35

标签: java android android-mediaplayer android-audiomanager audiotrack

即使耳机开启,我也试图在扬声器上播放声音,但如果背景中有音乐播放,我希望音乐在耳机上播放,直到播放声音。

所以我正在采取下一步措施:

  • 在播放声音之前,我获得了audioFocus所以所有背景音乐都是
  • 获得audioFocus后,我将MODE_COMMUNICATION设置为 AudioManager,因此声音可以在扬声器上播放。
  • 声音结束后,我放弃了音频聚焦并将MODE_NORMAL设置为 AudioManager,因此背景音乐可以继续在耳机上播放。

奇怪的是,它取决于设备,在某些设备上可以, 但是在设置MODE_COMMUNICATION后在Nexus 6P(华为)设备上有延迟3-4秒在播放声音之前。如果我没有延迟播放声音,它既不会播放到扬声器也不播放到耳机。

问题

如何知道在播放声音之前要设置多少延迟?有没有可以附加的听众,所以可以通知我,设置MODE_COMMUNICATION之后声音已经准备好了吗?

即使没有必要,我也不想设置延迟!

解决方法是不将模式设置为类的构造函数(跳过延迟),因为我需要在特定时刻在扬声器上播放声音!

PS:我正在使用AudioTrack播放声音,但我也尝试使用MediaPlayer(设置setAudioStreamType(MODE_IN_COMMUNICATION)),但没有成功,延迟仍在那里!

那么有什么建议吗?

1 个答案:

答案 0 :(得分:0)

万一有人偶然发现这篇文章,对我有用的是调用AudioManager.setMode(),然后重新创建我的MediaPlayer(通过构造函数,而不是create())并使用setAudioAttributes()更改输出源。

科特琳片段:

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) {}
}

希望这会有所帮助:)

P.S。请注意,我使用的是MODE_IN_CALL而不是MODE_IN_COMMUNICATION