I have a single activity application set up to use a Self-managed Connection Service since we are using audio and video and wanted to be able to leverage the system. HOWEVER, something about the way that we are closing the connection or perhaps changing the audio stream is causing an issue that I will try to describe to the best of my ability here.
When I start our application's call, everything works the way we want it to, it starts in speakerphone but reacts well to the button presses of the speakerphone button and audio works great! When the call ends, however, my phone is stuck in a mode where any notifications do not play out through the speaker but rather come through the earpiece, meaning that all my notifications are rather quiet. I believe this to be because we are not properly resetting the audio stream. I'm not sure if that's meant to happen in the destroy() of the Connection object or rather in the Activity where we request audio focus etc... Below is the code I believe to be the culprit
This method initialize audio is called from onResume() of the single Activity. We go down two different requesting paths depending on the Build version of the user's device
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)
}
}
}
So here is the AudioFocusRequest for newer versions
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")
}
And here is the more dated 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()
}
}
}
Finally, we have our tearDownAudio() method that is called from onPause() in the Activity
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)
}
}
My guess is the issue is somewhere in the tearDownAudio() method because the audio on the device works great to start and during the call but is not returning to the normal stream after the call ends.
It is also possible that the issue exists within the ConnectionService implementation since we are using a self managed Connection Service but my first instinct is that the above code is the problem.