8
8
package io.element.android.features.call.impl.ui
9
9
10
10
import android.annotation.SuppressLint
11
+ import android.content.Context
12
+ import android.media.AudioDeviceCallback
13
+ import android.media.AudioDeviceInfo
11
14
import android.media.AudioManager
12
15
import android.util.Log
13
16
import android.view.ViewGroup
@@ -22,6 +25,10 @@ import androidx.compose.foundation.layout.fillMaxSize
22
25
import androidx.compose.foundation.layout.padding
23
26
import androidx.compose.material3.ExperimentalMaterial3Api
24
27
import androidx.compose.runtime.Composable
28
+ import androidx.compose.runtime.getValue
29
+ import androidx.compose.runtime.mutableStateOf
30
+ import androidx.compose.runtime.remember
31
+ import androidx.compose.runtime.setValue
25
32
import androidx.compose.ui.Alignment
26
33
import androidx.compose.ui.Modifier
27
34
import androidx.compose.ui.platform.LocalInspectionMode
@@ -151,15 +158,11 @@ private fun CallWebView(
151
158
Text (" WebView - can't be previewed" )
152
159
}
153
160
} else {
161
+ var audioDeviceCallback: AudioDeviceCallback ? by remember { mutableStateOf(null ) }
154
162
AndroidView (
155
163
modifier = modifier,
156
164
factory = { context ->
157
- // Set 'voice call' mode so volume keys actually control the call volume
158
- val audioManager = context.getSystemService<AudioManager >()
159
- audioManager?.mode = AudioManager .MODE_IN_COMMUNICATION
160
-
161
- audioManager?.enableExternalAudioDevice()
162
-
165
+ audioDeviceCallback = context.setupAudioConfiguration()
163
166
WebView (context).apply {
164
167
onWebViewCreate(this )
165
168
setup(userAgent, onPermissionsRequest)
@@ -172,16 +175,40 @@ private fun CallWebView(
172
175
},
173
176
onRelease = { webView ->
174
177
// Reset audio mode
175
- val audioManager = webView.context.getSystemService<AudioManager >()
176
- audioManager?.disableExternalAudioDevice()
177
- audioManager?.mode = AudioManager .MODE_NORMAL
178
-
178
+ webView.context.releaseAudioConfiguration(audioDeviceCallback)
179
179
webView.destroy()
180
180
}
181
181
)
182
182
}
183
183
}
184
184
185
+ private fun Context.setupAudioConfiguration (): AudioDeviceCallback ? {
186
+ val audioManager = getSystemService<AudioManager >() ? : return null
187
+ // Set 'voice call' mode so volume keys actually control the call volume
188
+ audioManager.mode = AudioManager .MODE_IN_COMMUNICATION
189
+ audioManager.enableExternalAudioDevice()
190
+ return object : AudioDeviceCallback () {
191
+ override fun onAudioDevicesAdded (addedDevices : Array <out AudioDeviceInfo >? ) {
192
+ Timber .d(" Audio devices added" )
193
+ audioManager.enableExternalAudioDevice()
194
+ }
195
+
196
+ override fun onAudioDevicesRemoved (removedDevices : Array <out AudioDeviceInfo >? ) {
197
+ Timber .d(" Audio devices removed" )
198
+ audioManager.enableExternalAudioDevice()
199
+ }
200
+ }.also {
201
+ audioManager.registerAudioDeviceCallback(it, null )
202
+ }
203
+ }
204
+
205
+ private fun Context.releaseAudioConfiguration (audioDeviceCallback : AudioDeviceCallback ? ) {
206
+ val audioManager = getSystemService<AudioManager >() ? : return
207
+ audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
208
+ audioManager.disableExternalAudioDevice()
209
+ audioManager.mode = AudioManager .MODE_NORMAL
210
+ }
211
+
185
212
@SuppressLint(" SetJavaScriptEnabled" )
186
213
private fun WebView.setup (
187
214
userAgent : String ,
0 commit comments