mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 18:35:40 +03:00
Call audio device: handle bluetooth headset properly with icon and name
This commit is contained in:
parent
4788630949
commit
1f3da38eb0
8 changed files with 63 additions and 42 deletions
|
@ -21,7 +21,6 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.bottomsheet.bottomSheetActionItem
|
||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||
import im.vector.app.databinding.BottomSheetGenericListBinding
|
||||
|
@ -52,9 +51,14 @@ class CallSoundDeviceChooserBottomSheet : VectorBaseBottomSheetDialogFragment<Bo
|
|||
private fun render(available: Set<CallAudioManager.Device>, current: CallAudioManager.Device) {
|
||||
views.bottomSheetRecyclerView.withModels {
|
||||
available.forEach { device ->
|
||||
val title = when (device) {
|
||||
is CallAudioManager.Device.WirelessHeadset -> device.name ?: getString(device.titleRes)
|
||||
else -> getString(device.titleRes)
|
||||
}
|
||||
|
||||
bottomSheetActionItem {
|
||||
id(device.ordinal)
|
||||
textRes(device.titleRes)
|
||||
id(device.titleRes)
|
||||
text(title)
|
||||
iconRes(device.drawableRes)
|
||||
selected(current == device)
|
||||
listener {
|
||||
|
@ -64,11 +68,11 @@ class CallSoundDeviceChooserBottomSheet : VectorBaseBottomSheetDialogFragment<Bo
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
companion object {
|
||||
fun newInstance(): RoomListQuickActionsBottomSheet {
|
||||
return RoomListQuickActionsBottomSheet()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
|
||||
override fun onAudioDevicesChange() {
|
||||
val currentSoundDevice = callManager.audioManager.selectedDevice ?: return
|
||||
if (currentSoundDevice == CallAudioManager.Device.PHONE) {
|
||||
if (currentSoundDevice == CallAudioManager.Device.Phone) {
|
||||
proximityManager.start()
|
||||
} else {
|
||||
proximityManager.stop()
|
||||
|
@ -184,7 +184,7 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
callManager.addCurrentCallListener(currentCallListener)
|
||||
webRtcCall.addListener(callListener)
|
||||
val currentSoundDevice = callManager.audioManager.selectedDevice
|
||||
if (currentSoundDevice == CallAudioManager.Device.PHONE) {
|
||||
if (currentSoundDevice == CallAudioManager.Device.Phone) {
|
||||
proximityManager.start()
|
||||
}
|
||||
setState {
|
||||
|
@ -194,7 +194,7 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
isVideoCall = webRtcCall.mxCall.isVideoCall,
|
||||
callState = Success(webRtcCall.mxCall.state),
|
||||
callInfo = webRtcCall.extractCallInfo(),
|
||||
device = currentSoundDevice ?: CallAudioManager.Device.PHONE,
|
||||
device = currentSoundDevice ?: CallAudioManager.Device.Phone,
|
||||
isLocalOnHold = webRtcCall.isLocalOnHold,
|
||||
isRemoteOnHold = webRtcCall.isRemoteOnHold,
|
||||
availableDevices = callManager.audioManager.availableDevices,
|
||||
|
|
|
@ -35,7 +35,7 @@ data class VectorCallViewState(
|
|||
val isHD: Boolean = false,
|
||||
val isFrontCamera: Boolean = true,
|
||||
val canSwitchCamera: Boolean = true,
|
||||
val device: CallAudioManager.Device = CallAudioManager.Device.PHONE,
|
||||
val device: CallAudioManager.Device = CallAudioManager.Device.Phone,
|
||||
val availableDevices: Set<CallAudioManager.Device> = emptySet(),
|
||||
val callState: Async<CallState> = Uninitialized,
|
||||
val otherKnownCallInfo: CallInfo? = null,
|
||||
|
|
|
@ -50,13 +50,17 @@ internal class API21AudioDeviceDetector(private val context: Context,
|
|||
|
||||
private fun getAvailableSoundDevices(): Set<CallAudioManager.Device> {
|
||||
return HashSet<CallAudioManager.Device>().apply {
|
||||
if (isBluetoothHeadsetOn()) add(CallAudioManager.Device.WIRELESS_HEADSET)
|
||||
if (isWiredHeadsetOn()) {
|
||||
add(CallAudioManager.Device.HEADSET)
|
||||
} else {
|
||||
add(CallAudioManager.Device.PHONE)
|
||||
if (isBluetoothHeadsetOn()) {
|
||||
connectedBlueToothHeadset?.connectedDevices?.forEach {
|
||||
add(CallAudioManager.Device.WirelessHeadset(it.name))
|
||||
}
|
||||
add(CallAudioManager.Device.SPEAKER)
|
||||
}
|
||||
if (isWiredHeadsetOn()) {
|
||||
add(CallAudioManager.Device.Headset)
|
||||
} else {
|
||||
add(CallAudioManager.Device.Phone)
|
||||
}
|
||||
add(CallAudioManager.Device.Speaker)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,10 +33,10 @@ internal class API23AudioDeviceDetector(private val audioManager: AudioManager,
|
|||
val deviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)
|
||||
for (info in deviceInfos) {
|
||||
when (info.type) {
|
||||
AudioDeviceInfo.TYPE_BLUETOOTH_SCO -> devices.add(CallAudioManager.Device.WIRELESS_HEADSET)
|
||||
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> devices.add(CallAudioManager.Device.PHONE)
|
||||
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> devices.add(CallAudioManager.Device.SPEAKER)
|
||||
AudioDeviceInfo.TYPE_WIRED_HEADPHONES, AudioDeviceInfo.TYPE_WIRED_HEADSET, TYPE_USB_HEADSET -> devices.add(CallAudioManager.Device.HEADSET)
|
||||
AudioDeviceInfo.TYPE_BLUETOOTH_SCO -> devices.add(CallAudioManager.Device.WirelessHeadset(info.productName.toString()))
|
||||
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> devices.add(CallAudioManager.Device.Phone)
|
||||
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> devices.add(CallAudioManager.Device.Speaker)
|
||||
AudioDeviceInfo.TYPE_WIRED_HEADPHONES, AudioDeviceInfo.TYPE_WIRED_HEADSET, TYPE_USB_HEADSET -> devices.add(CallAudioManager.Device.Headset)
|
||||
}
|
||||
}
|
||||
callAudioManager.replaceDevices(devices)
|
||||
|
|
|
@ -23,6 +23,7 @@ import androidx.annotation.DrawableRes
|
|||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.getSystemService
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import timber.log.Timber
|
||||
import java.util.HashSet
|
||||
|
@ -34,11 +35,11 @@ class CallAudioManager(private val context: Context, val configChange: (() -> Un
|
|||
private var audioDeviceDetector: AudioDeviceDetector? = null
|
||||
private var audioDeviceRouter: AudioDeviceRouter? = null
|
||||
|
||||
enum class Device(@StringRes val titleRes: Int, @DrawableRes val drawableRes: Int) {
|
||||
PHONE(R.string.sound_device_phone,R.drawable.ic_sound_device_phone),
|
||||
SPEAKER(R.string.sound_device_speaker,R.drawable.ic_sound_device_speaker),
|
||||
HEADSET(R.string.sound_device_headset,R.drawable.ic_sound_device_headphone),
|
||||
WIRELESS_HEADSET(R.string.sound_device_wireless_headset,R.drawable.ic_sound_device_headphone)
|
||||
sealed class Device(@StringRes val titleRes: Int, @DrawableRes val drawableRes: Int) {
|
||||
object Phone : Device(R.string.sound_device_phone, R.drawable.ic_sound_device_phone)
|
||||
object Speaker : Device(R.string.sound_device_speaker, R.drawable.ic_sound_device_speaker)
|
||||
object Headset : Device(R.string.sound_device_headset, R.drawable.ic_sound_device_headphone)
|
||||
data class WirelessHeadset(val name: String?) : Device(R.string.sound_device_wireless_headset, R.drawable.ic_sound_device_wireless)
|
||||
}
|
||||
|
||||
enum class Mode {
|
||||
|
@ -136,19 +137,19 @@ class CallAudioManager(private val context: Context, val configChange: (() -> Un
|
|||
userSelectedDevice = null
|
||||
return true
|
||||
}
|
||||
val bluetoothAvailable = _availableDevices.contains(Device.WIRELESS_HEADSET)
|
||||
val headsetAvailable = _availableDevices.contains(Device.HEADSET)
|
||||
val availableBluetoothDevice = _availableDevices.firstOrNull { it is Device.WirelessHeadset }
|
||||
val headsetAvailable = _availableDevices.contains(Device.Headset)
|
||||
|
||||
// Pick the desired device based on what's available and the mode.
|
||||
var audioDevice: Device
|
||||
audioDevice = if (bluetoothAvailable) {
|
||||
Device.WIRELESS_HEADSET
|
||||
audioDevice = if (availableBluetoothDevice != null) {
|
||||
availableBluetoothDevice
|
||||
} else if (headsetAvailable) {
|
||||
Device.HEADSET
|
||||
Device.Headset
|
||||
} else if (mode == Mode.VIDEO_CALL) {
|
||||
Device.SPEAKER
|
||||
Device.Speaker
|
||||
} else {
|
||||
Device.PHONE
|
||||
Device.Phone
|
||||
}
|
||||
// Consider the user's selection
|
||||
if (userSelectedDevice != null && _availableDevices.contains(userSelectedDevice)) {
|
||||
|
|
|
@ -31,8 +31,8 @@ class DefaultAudioDeviceRouter(private val audioManager: AudioManager,
|
|||
private var focusRequestCompat: AudioFocusRequestCompat? = null
|
||||
|
||||
override fun setAudioRoute(device: CallAudioManager.Device) {
|
||||
audioManager.isSpeakerphoneOn = device === CallAudioManager.Device.SPEAKER
|
||||
setBluetoothAudioRoute(device === CallAudioManager.Device.WIRELESS_HEADSET)
|
||||
audioManager.isSpeakerphoneOn = device is CallAudioManager.Device.Speaker
|
||||
setBluetoothAudioRoute(device is CallAudioManager.Device.WirelessHeadset)
|
||||
}
|
||||
|
||||
override fun setMode(mode: CallAudioManager.Mode): Boolean {
|
||||
|
|
12
vector/src/main/res/drawable/ic_sound_device_wireless.xml
Normal file
12
vector/src/main/res/drawable/ic_sound_device_wireless.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M10.8817,3.1593L5.4545,7.682L1.3636,7.682C0.6105,7.682 0,8.2925 0,9.0456V15.0456C0,15.7987 0.6105,16.4092 1.3636,16.4092L5.4545,16.4092L10.8817,20.9318C11.3258,21.3019 12,20.9861 12,20.4081V3.6831C12,3.1051 11.3258,2.7893 10.8817,3.1593Z"
|
||||
android:fillColor="#737D8C"/>
|
||||
<path
|
||||
android:pathData="M23.6656,7.8241L20.0887,4.2472C19.5634,3.7219 18.6629,4.0888 18.6629,4.8309V9.9836L15.4195,6.7402C15.0943,6.415 14.5691,6.415 14.2439,6.7402C13.9187,7.0654 13.9187,7.5907 14.2439,7.9159L18.3211,11.993L14.2439,16.0703C13.9187,16.3954 13.9187,16.9207 14.2439,17.2459C14.5691,17.5711 15.0943,17.5711 15.4195,17.2459L18.6629,14.0025V19.1553C18.6629,19.8973 19.5634,20.2725 20.0887,19.7472L23.6656,16.162C23.9908,15.8368 23.9908,15.3115 23.6656,14.9863L20.6724,11.993L23.6656,9.0081C23.9908,8.6829 23.9908,8.1493 23.6656,7.8241ZM20.3305,6.8486L21.898,8.4161L20.3305,9.9836V6.8486ZM21.898,15.57L20.3305,17.1375V14.0025L21.898,15.57Z"
|
||||
android:fillColor="#737D8C"/>
|
||||
</vector>
|
Loading…
Reference in a new issue