当前位置: 首页 > 知识库问答 >
问题:

Android通话应用未重置音频流

廖弘量
2023-03-14

我有一个活动应用程序设置为使用自我管理的连接服务,因为我们正在使用音频和视频,并且希望能够利用系统。然而,关于我们关闭连接或可能更改音频流的方式的一些事情正在引起一个问题,我将尽我所能在这里描述。

当我开始我们的应用程序的通话时,一切都按照我们想要的方式工作,它在免提电话中启动,但对免提电话按钮的按钮按下反应良好,音频效果很好!然而,当通话结束时,我的手机陷入了一种模式,任何通知都不会通过扬声器播放,而是通过耳机播放,这意味着我所有的通知都相当安静。我认为这是因为我们没有正确地重置音频流。我不确定这是否意味着在Connection对象的破坏()中发生,或者更确切地说,在我们请求音频焦点等的活动中发生...下面是我认为是罪魁祸首的代码

此方法初始化音频是从单个活动的onResume()调用的。根据用户设备的构建版本,我们沿着两条不同的请求路径

private fun initializeAudio() {
    if (!audioManager.isInCall()) {
        volumeControlStream = AudioManager.STREAM_VOICE_CALL
        // Request audio focus for playback
        val result: Int = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
            audioManager.requestAudioFocus(focusRequest)
        } else {
            @Suppress("DEPRECATION")
            audioManager.requestAudioFocus(
                afChangeListener,
                AudioManager.STREAM_VOICE_CALL,
                AudioManager.AUDIOFOCUS_GAIN
            )
        }

        if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            StreemLog.logError(TAG, "Audio focus request denied", sendBreadcrumb = true)
        }
    }
}

所以这是音频焦点对较新版本的要求

private val focusRequest: AudioFocusRequest by lazy {
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
        AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
            setAudioAttributes(
                AudioAttributes.Builder().run {
                    setLegacyStreamType(AudioManager.STREAM_VOICE_CALL)
                    setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                    build()
                }
            )
            setOnAudioFocusChangeListener(afChangeListener)
            build()
        }
    } else throw IllegalStateException("Trying to use AudioFocusRequest below minimum API 26")
}

这是一个更为过时的OnAudioFocusChangeListener

private val afChangeListener: AudioManager.OnAudioFocusChangeListener =
    AudioManager.OnAudioFocusChangeListener { focusChange ->
        when (focusChange) {
            AudioManager.AUDIOFOCUS_LOSS -> {
                tearDownAudio()
            }
            AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
                // noop
            }
            AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
                // noop
            }
            AudioManager.AUDIOFOCUS_GAIN -> {
                initializeAudio()
            }
        }
    }

最后,我们有我们的tearDownAudio()方法,该方法在活动中从onPance()调用

private fun tearDownAudio() {
    volumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
        audioManager.abandonAudioFocusRequest(focusRequest)
    } else {
        @Suppress("DEPRECATION")
        audioManager.abandonAudioFocus(afChangeListener)
    }
}

我猜问题出在tearDownAudio()方法的某个地方,因为设备上的音频在开始和通话过程中工作得很好,但在通话结束后没有返回到正常流。

问题也可能存在于ConnectionService实现中,因为我们正在使用自我管理的连接服务,但是我的第一直觉是上面的代码就是问题所在。

共有1个答案

拓拔阎宝
2023-03-14

我的一位团队成员发现了这个问题!经过大量的调试...

当呼叫结束时,我们只关闭了本地参与者的WebRTCPeer连接,而不是所有参与者。所以只剩下一个WebRtcAudioTrack对象在运行。对它们调用close会释放音频资源,并且所有流路由都会恢复到正确的状态。

所以,这个故事的寓意是确保在结束通话时关闭所有连接!

 类似资料:
  • 我正试图创建一个呼叫录音机应用程序,然而,我的音频来源时,它的麦克风工作正常,但它不能捕捉第二个声音。 如果我更改为VOICE_CALL,我的应用程序关闭。 我在PlayStore上看到了数百个类似的应用程序,并想知道它们能够记录通话双方的秘密是什么。

  • 问题内容: 我想通知任何传入和传出语音呼叫的代码。我需要掌握以下所有内容: 如果是来电或去电 拨打的号码或来电显示的电话号码 通话时长,或者如果错过了通话 如果电话号码与电话的联系人列表中的某人匹配,如果我可以获得更多的联系信息,特别是联系人姓名,那也将是一件很圆滑的事。 通话结束后,我需要我的代码来获取这些信息。也许我只是没有在寻找正确的术语,但是我很难找到如何实现此目标的任何示例。 如果有人可

  • 我一直无法让应用程序录制音频,同时让iPhone音乐应用程序通过蓝牙扬声器播放。 例如,如果我这样做: 然后音乐应用程序将开始通过iPhone内置的扬声器播放音乐,而不是通过蓝牙。换句话说,似乎没有办法在应用程序中录制音频的同时还允许通过蓝牙播放音乐。 如果我删除AVAudioSessionColloryOptionDefaultToSpeaker,那么音频路由将切换到接收器。这比让它通过iPho

  • null 提前感谢您的任何帮助:)

  • 我在android上使用APPRTCdemo应用程序。我试着让它播放来自另一个同龄人的声音,音量与Android设置中设置的音量一样大。因此,如果用户将设备静音,则不会听到音频。我几乎尝试了每一个Android API调用,但似乎对音量没有任何影响。以下是我尝试过的东西:AudioManager AudioManager=(AudioManager)_context.getSystemServic

  • 我已经尝试了很多和VOIP电话是工作很好,但我想添加一个可编程的消息,当接收者将接受呼叫。 我在后端使用了上面的代码,我的VOIP呼叫工作正常,但我想添加一个可编程的消息,当接收者接受呼叫时