davidliu
Committed by GitHub

Turn off audio routing for non communication audio modes (#261)

* Turn off audio routing for non communication audio modes

* update audioswitch commit

* update audioswitch
... ... @@ -140,7 +140,7 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0'
api 'io.github.webrtc-sdk:android:104.5112.10'
api "com.squareup.okhttp3:okhttp:4.10.0"
api 'com.github.davidliu:audioswitch:7b55cec426227a75be25b0d7ad8537d4aede2a2a'
api 'com.github.davidliu:audioswitch:d18e3e31d427c27f1593030e024b370bf24480fd'
implementation "androidx.annotation:annotation:1.4.0"
implementation "androidx.core:core:${versions.androidx_core}"
implementation "com.google.protobuf:protobuf-javalite:${versions.protobuf}"
... ...
... ... @@ -58,13 +58,16 @@ class AudioOptions(
* This affects the audio routing and how the audio is handled. Default is [AudioType.CallAudioType].
*
* Note: if [audioHandler] is also passed, the values from [audioOutputType] will not be reflected in it,
* and must be set manually.
* and must be set yourself.
*/
val audioOutputType: AudioType? = null,
/**
* Override the default [AudioHandler].
*
* Use [NoAudioHandler] to turn off automatic audio handling.
* Default is [AudioSwitchHandler].
*
* Use [NoAudioHandler] to turn off automatic audio handling or
* [AudioFocusHandler] to get simple audio focus handling.
*/
val audioHandler: AudioHandler? = null,
... ... @@ -81,20 +84,22 @@ class AudioOptions(
val javaAudioDeviceModuleCustomizer: ((builder: JavaAudioDeviceModule.Builder) -> Unit)? = null,
)
sealed class AudioType(val audioMode: Int, val audioAttributes: AudioAttributes, val audioStreamType: Int) {
sealed class AudioType(
val audioMode: Int,
val audioAttributes: AudioAttributes,
val audioStreamType: Int
) {
/**
* An audio type for general media playback usage (i.e. listener-only use cases).
*
* Audio routing is handled automatically by the system in normal media mode,
* and bluetooth microphones may not work on some devices.
*
* The default [AudioHandler] for this type is [AudioFocusHandler].
*/
class MediaAudioType : AudioType(
AudioManager.MODE_NORMAL,
AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
.build(),
AudioManager.STREAM_MUSIC
)
... ... @@ -103,8 +108,6 @@ sealed class AudioType(val audioMode: Int, val audioAttributes: AudioAttributes,
* An audio type for calls (i.e. participating in the call or publishing local microphone).
*
* Audio routing can be manually controlled.
*
* The default [AudioHandler] for this type is [AudioSwitchHandler].
*/
class CallAudioType : AudioType(
AudioManager.MODE_IN_COMMUNICATION,
... ... @@ -117,8 +120,6 @@ sealed class AudioType(val audioMode: Int, val audioAttributes: AudioAttributes,
/**
* An audio type that takes in a user-defined [AudioAttributes] and audio stream type.
*
* The default [AudioHandler] for this type is [AudioFocusHandler].
*/
class CustomAudioType(audioMode: Int, audioAttributes: AudioAttributes, audioStreamType: Int) :
AudioType(audioMode, audioAttributes, audioStreamType)
... ...
... ... @@ -35,6 +35,7 @@ import javax.inject.Singleton
class AudioSwitchHandler
@Inject
constructor(private val context: Context) : AudioHandler {
/**
* Toggle whether logging is enabled for [AudioSwitch]. By default, this is set to false.
*/
... ... @@ -124,6 +125,15 @@ constructor(private val context: Context) : AudioHandler {
*/
var audioAttributeContentType: Int = AudioAttributes.CONTENT_TYPE_SPEECH
/**
* On certain Android devices, audio routing does not function properly and bluetooth microphones will not work
* unless audio mode is set to [AudioManager.MODE_IN_COMMUNICATION] or [AudioManager.MODE_IN_CALL].
*
* AudioSwitchHandler by default will not handle audio routing in those cases to avoid audio issues.
*
* If this set to true, AudioSwitchHandler will attempt to do audio routing, though behavior is undefined.
*/
var forceHandleAudioRouting = false
private var audioSwitch: AbstractAudioSwitch? = null
... ... @@ -156,6 +166,7 @@ constructor(private val context: Context) : AudioHandler {
switch.audioStreamType = audioStreamType
switch.audioAttributeUsageType = audioAttributeUsageType
switch.audioAttributeContentType = audioAttributeContentType
switch.forceHandleAudioRouting = forceHandleAudioRouting
audioSwitch = switch
switch.start(audioDeviceChangeListener ?: defaultAudioDeviceChangeListener)
... ...
... ... @@ -20,7 +20,6 @@ import android.media.AudioAttributes
import dagger.Module
import dagger.Provides
import io.livekit.android.AudioType
import io.livekit.android.audio.AudioFocusHandler
import io.livekit.android.audio.AudioHandler
import io.livekit.android.audio.AudioSwitchHandler
import javax.inject.Named
... ... @@ -49,25 +48,15 @@ object AudioHandlerModule {
@Singleton
fun audioHandler(
audioSwitchHandler: Provider<AudioSwitchHandler>,
audioFocusHandler: Provider<AudioFocusHandler>,
@Named(InjectionNames.OVERRIDE_AUDIO_HANDLER)
audioHandlerOverride: AudioHandler?,
audioOutputType: AudioType,
): AudioHandler {
return audioHandlerOverride ?: when (audioOutputType) {
is AudioType.CallAudioType -> {
audioSwitchHandler.get().apply {
audioMode = audioOutputType.audioMode
audioAttributeContentType = audioOutputType.audioAttributes.contentType
audioAttributeUsageType = audioOutputType.audioAttributes.usage
audioStreamType = audioOutputType.audioStreamType
}
}
is AudioType.MediaAudioType,
is AudioType.CustomAudioType -> {
audioFocusHandler.get()
}
return audioHandlerOverride ?: audioSwitchHandler.get().apply {
audioMode = audioOutputType.audioMode
audioAttributeContentType = audioOutputType.audioAttributes.contentType
audioAttributeUsageType = audioOutputType.audioAttributes.usage
audioStreamType = audioOutputType.audioStreamType
}
}
}
\ No newline at end of file
... ...