【问题标题】:How to play audio through earpiece in android 12?如何在android 12中通过听筒播放音频?
【发布时间】:2021-11-05 06:38:16
【问题描述】:

我正在使用 PeerJS 和 WebView 为 android 开发语音通话应用程序。我希望音频通过听筒播放。这是我的代码,

private fun initAudio(){
  am = getSystemService(AUDIO_SERVICE) as AudioManager
  volumeControlStream = AudioManager.STREAM_VOICE_CALL
  am.mode = AudioManager.MODE_IN_COMMUNICATION
  am.isSpeakerphoneOn = false//<= not working in android 12
}

private fun toggleSpeakerMode(){
  am.isSpeakerphoneOn = !am.isSpeakerphoneOn // <= final value is always true in android 12
}

上面的代码在旧版本的 android 上运行良好,但在 android 12(模拟器)上不行。 am.isSpeakerphoneOn 在 android 12 中总是正确的。我在这里做错了吗?还是模拟器的bug?

更新

只有在 WebView 上启动 webRTC 流后才会出现此问题(我能够在流之前切换扬声器)。

【问题讨论】:

  • 运气好吗?我面临着类似的问题:第一次设置 MODE_IN_COMMUNICATIONisSpeakerphoneOn = false 工作正常,但切换到 MODE_NORMAL/isSpeakerphoneOn = true 并再次尝试切换到第一个提到的设置对导致模式切换,但扬声器仍然是在。在这种情况下,我什至尝试循环强制isSpeakerphoneOn = false,但这不会被尊重
  • 还没有解决方案

标签: android android-audiomanager


【解决方案1】:

在 Android 12/S/API 31 中有一个新的 API 调用,setCommunicationDevice(AudioDeviceInfo)。现在我们可以使用在扬声器和内置耳机之间切换:

ArrayList<Integer> targetTypes = new ArrayList<>();
if (earpieceMode) {
    targetTypes.add(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE);
} else { // play out loud
    targetTypes.add(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
}
// more targetTypes may be added in some cases
// set up will pick and first available, so order matters

List<AudioDeviceInfo> devices = audioManager.getAvailableCommunicationDevices();
outer:
for (Integer targetType : targetTypes) {
    for (AudioDeviceInfo device : devices) {
        if (device.getType() == targetType) {
            boolean result = audioManager.setCommunicationDevice(device);
            Log.i("AUDIO_MANAGER", "setCommunicationDevice type:" + targetType + " result:" + result);
            if (result) break outer;
        }
    }
}

不需要更改模式(但强烈建议用于 voip 通话),我的流是 AudioManager.STREAM_VOICE_CALL 类型(如果适用)

【讨论】:

  • 它仍然通过免提电话播放。我猜是因为模拟器没有任何听筒硬件。
  • 您可以使用getAvailableCommunicationDevices() 列出它。这段代码对我来说非常好用(Pixel,即将推出更多测试/设备),但我没有WebView 音频源,我有MediaPlayerExoPlayerAudioTrack,所有本地人(也有问题与SoundPool,现在也是MediaPlayer)。我可以为其中任何一个设置AudioManager.STREAM_VOICE_CALL 类型,然后在扬声器和内置耳机之间切换。 afaik WebView 没有这样的选项,它可能是 AudioManager.STREAM_MUSIC always
【解决方案2】:

默认情况下,webrtc 使用耳机进行语音播放。 但是,您也可以调用 AudioManager.java 类中定义的setSpeakerphoneOn(false)

只要在这个函数参数中传入false,它就会在通话中禁用免提电话并使用听筒。 我还在 android 12 手机上测试过,效果很好。

如果问题仍然存在,那么您的模拟器中存在一些错误。

【讨论】:

  • 我在 webView 上使用 peerJS javascript 库进行调用(不是 webRTC android 库)。而且我可以在流开始之前使用听筒(用于铃声)。但是当我们接收到流时,它总是通过扬声器播放。表示setSpeakerphoneOn(false) 无效,am.isSpeakerphoneOn 在流式传输时始终返回true
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-07
  • 2021-11-18
  • 1970-01-01
  • 2017-02-16
  • 1970-01-01
  • 2016-07-23
  • 1970-01-01
相关资源
最近更新 更多