davidliu
Committed by GitHub

Add audio/focus options to AudioSwitchHandler (#246)

Also changed the default audio mode to MODE_NORMAL and focus mode to AUDIOFOCUS_GAIN, and the default input audio source to DEFAULT
@@ -140,7 +140,7 @@ dependencies { @@ -140,7 +140,7 @@ dependencies {
140 implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0' 140 implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0'
141 api 'io.github.webrtc-sdk:android:104.5112.10' 141 api 'io.github.webrtc-sdk:android:104.5112.10'
142 api "com.squareup.okhttp3:okhttp:4.10.0" 142 api "com.squareup.okhttp3:okhttp:4.10.0"
143 - api 'com.github.davidliu:audioswitch:8edf84ee46cdbc84c2b7725aa8f8d66363e19876' 143 + api 'com.github.davidliu:audioswitch:fb33b237aa50b3d1d2dea0e0695ecb7b38a98971'
144 implementation "androidx.annotation:annotation:1.4.0" 144 implementation "androidx.annotation:annotation:1.4.0"
145 implementation "androidx.core:core:${versions.androidx_core}" 145 implementation "androidx.core:core:${versions.androidx_core}"
146 implementation "com.google.protobuf:protobuf-javalite:${versions.protobuf}" 146 implementation "com.google.protobuf:protobuf-javalite:${versions.protobuf}"
1 package io.livekit.android.audio 1 package io.livekit.android.audio
2 2
3 import android.content.Context 3 import android.content.Context
4 -import android.media.AudioDeviceInfo  
5 import android.media.AudioManager 4 import android.media.AudioManager
6 import android.os.Build 5 import android.os.Build
7 import android.os.Handler 6 import android.os.Handler
@@ -49,6 +48,20 @@ constructor(private val context: Context) : AudioHandler { @@ -49,6 +48,20 @@ constructor(private val context: Context) : AudioHandler {
49 */ 48 */
50 var preferredDeviceList: List<Class<out AudioDevice>>? = null 49 var preferredDeviceList: List<Class<out AudioDevice>>? = null
51 50
  51 + /**
  52 + * The audio mode to use while started.
  53 + *
  54 + * Defaults to [AudioManager.MODE_NORMAL].
  55 + */
  56 + var audioMode: Int = AudioManager.MODE_NORMAL
  57 +
  58 + /**
  59 + * The audio focus mode to use while started.
  60 + *
  61 + * Defaults to [AudioManager.AUDIOFOCUS_GAIN].
  62 + */
  63 + var focusMode: Int = AudioManager.AUDIOFOCUS_GAIN
  64 +
52 private var audioSwitch: AbstractAudioSwitch? = null 65 private var audioSwitch: AbstractAudioSwitch? = null
53 66
54 // AudioSwitch is not threadsafe, so all calls should be done on the main thread. 67 // AudioSwitch is not threadsafe, so all calls should be done on the main thread.
@@ -74,55 +87,10 @@ constructor(private val context: Context) : AudioHandler { @@ -74,55 +87,10 @@ constructor(private val context: Context) : AudioHandler {
74 preferredDeviceList = preferredDeviceList ?: defaultPreferredDeviceList 87 preferredDeviceList = preferredDeviceList ?: defaultPreferredDeviceList
75 ) 88 )
76 } 89 }
  90 + switch.audioMode = audioMode
  91 + switch.focusMode = focusMode
77 audioSwitch = switch 92 audioSwitch = switch
78 - switch.start { audioDevices: List<AudioDevice>, selectedAudioDevice: AudioDevice? ->  
79 -  
80 - // On >S, some devices don't properly use bluetooth mic if no audio tracks.  
81 - // Using the new communication devices api fixes this.  
82 - // TODO: Move into AudioSwitch itself  
83 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {  
84 - val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager  
85 - val commDevices = audioManager.availableCommunicationDevices  
86 -  
87 - val audioDeviceInfo = when (selectedAudioDevice) {  
88 - is AudioDevice.BluetoothHeadset -> {  
89 - commDevices.firstOrNull { info ->  
90 - info.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO || info.type == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP  
91 - }  
92 - }  
93 -  
94 - is AudioDevice.Earpiece -> {  
95 - commDevices.firstOrNull { info ->  
96 - info.type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE  
97 - }  
98 - }  
99 -  
100 - is AudioDevice.Speakerphone -> {  
101 - commDevices.firstOrNull { info ->  
102 - info.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER  
103 - }  
104 - }  
105 -  
106 - is AudioDevice.WiredHeadset -> {  
107 - commDevices.firstOrNull { info ->  
108 - info.type == AudioDeviceInfo.TYPE_WIRED_HEADSET || info.type == AudioDeviceInfo.TYPE_WIRED_HEADPHONES  
109 - }  
110 - }  
111 -  
112 - else -> {  
113 - null  
114 - }  
115 - }  
116 -  
117 - if (audioDeviceInfo != null) {  
118 - audioManager.setCommunicationDevice(audioDeviceInfo)  
119 - } else {  
120 - audioManager.clearCommunicationDevice()  
121 - }  
122 - }  
123 -  
124 - audioDeviceChangeListener?.invoke(audioDevices, selectedAudioDevice)  
125 - } 93 + switch.start(audioDeviceChangeListener ?: defaultAudioDeviceChangeListener)
126 switch.activate() 94 switch.activate()
127 } 95 }
128 } 96 }
1 package io.livekit.android.dagger 1 package io.livekit.android.dagger
2 2
3 import android.content.Context 3 import android.content.Context
  4 +import android.media.MediaRecorder
4 import android.os.Build 5 import android.os.Build
5 import androidx.annotation.Nullable 6 import androidx.annotation.Nullable
6 import dagger.Module 7 import dagger.Module
@@ -103,6 +104,7 @@ object RTCModule { @@ -103,6 +104,7 @@ object RTCModule {
103 .setAudioTrackErrorCallback(audioTrackErrorCallback) 104 .setAudioTrackErrorCallback(audioTrackErrorCallback)
104 .setAudioRecordStateCallback(audioRecordStateCallback) 105 .setAudioRecordStateCallback(audioRecordStateCallback)
105 .setAudioTrackStateCallback(audioTrackStateCallback) 106 .setAudioTrackStateCallback(audioTrackStateCallback)
  107 + .setAudioSource(MediaRecorder.AudioSource.DEFAULT)
106 108
107 moduleCustomizer?.invoke(builder) 109 moduleCustomizer?.invoke(builder)
108 return builder.createAudioDeviceModule() 110 return builder.createAudioDeviceModule()