AudioManager 在 setMode(MODE_IN_COMMUNICATION) 中引入延迟

问题描述 投票:0回答:2

即使耳机打开,我也试图在扬声器上播放声音,但是如果背景音乐在播放,我希望在播放声音之前在耳机上播放音乐。

所以我要采取后续步骤:

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

奇怪的是它取决于设备,在某些设备上这是可以的,但是在设置

MODE_COMMUNICATION
后的Nexus 6P(华为)设备上有延迟3-4秒才能播放声音。如果我没有延迟地播放声音,它既不会播放到扬声器也不会播放到耳机。

问题

我怎么知道在播放声音之前要设置多少延迟?有没有我可以附加的监听器,所以可以通知我设置后

MODE_COMMUNICATION
声音可以播放了吗?

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

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

P.S:我是用

AudioTrack
播放声音,但我也试过
MediaPlayer
(设置
setAudioStreamType(MODE_IN_COMMUNICATION)
),但没有成功,延迟仍然存在!

有什么建议吗?

java android android-mediaplayer android-audiomanager audiotrack
2个回答
0
投票

万一有人偶然发现这篇文章,对我有用的是调用

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


0
投票

如果设备支持 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
© www.soinside.com 2019 - 2024. All rights reserved.