Committed by
GitHub
Route AudioSwitch calls through main thread (#120)
正在显示
2 个修改的文件
包含
26 行增加
和
14 行删除
| @@ -2,6 +2,8 @@ package io.livekit.android.audio | @@ -2,6 +2,8 @@ package io.livekit.android.audio | ||
| 2 | 2 | ||
| 3 | import android.content.Context | 3 | import android.content.Context |
| 4 | import android.media.AudioManager | 4 | import android.media.AudioManager |
| 5 | +import android.os.Handler | ||
| 6 | +import android.os.Looper | ||
| 5 | import com.twilio.audioswitch.AudioDevice | 7 | import com.twilio.audioswitch.AudioDevice |
| 6 | import com.twilio.audioswitch.AudioDeviceChangeListener | 8 | import com.twilio.audioswitch.AudioDeviceChangeListener |
| 7 | import com.twilio.audioswitch.AudioSwitch | 9 | import com.twilio.audioswitch.AudioSwitch |
| @@ -19,23 +21,32 @@ constructor(private val context: Context) : AudioHandler { | @@ -19,23 +21,32 @@ constructor(private val context: Context) : AudioHandler { | ||
| 19 | 21 | ||
| 20 | private var audioSwitch: AudioSwitch? = null | 22 | private var audioSwitch: AudioSwitch? = null |
| 21 | 23 | ||
| 24 | + // AudioSwitch is not threadsafe, so all calls should be done on the main thread. | ||
| 25 | + private val handler = Handler(Looper.getMainLooper()) | ||
| 26 | + | ||
| 22 | override fun start() { | 27 | override fun start() { |
| 23 | if (audioSwitch == null) { | 28 | if (audioSwitch == null) { |
| 24 | - val switch = AudioSwitch( | ||
| 25 | - context = context, | ||
| 26 | - loggingEnabled = loggingEnabled, | ||
| 27 | - audioFocusChangeListener = onAudioFocusChangeListener ?: defaultOnAudioFocusChangeListener, | ||
| 28 | - preferredDeviceList = preferredDeviceList ?: defaultPreferredDeviceList | ||
| 29 | - ) | ||
| 30 | - audioSwitch = switch | ||
| 31 | - switch.start(audioDeviceChangeListener ?: defaultAudioDeviceChangeListener) | ||
| 32 | - switch.activate() | 29 | + handler.removeCallbacksAndMessages(null) |
| 30 | + handler.post { | ||
| 31 | + val switch = AudioSwitch( | ||
| 32 | + context = context, | ||
| 33 | + loggingEnabled = loggingEnabled, | ||
| 34 | + audioFocusChangeListener = onAudioFocusChangeListener ?: defaultOnAudioFocusChangeListener, | ||
| 35 | + preferredDeviceList = preferredDeviceList ?: defaultPreferredDeviceList | ||
| 36 | + ) | ||
| 37 | + audioSwitch = switch | ||
| 38 | + switch.start(audioDeviceChangeListener ?: defaultAudioDeviceChangeListener) | ||
| 39 | + switch.activate() | ||
| 40 | + } | ||
| 33 | } | 41 | } |
| 34 | } | 42 | } |
| 35 | 43 | ||
| 36 | override fun stop() { | 44 | override fun stop() { |
| 37 | - audioSwitch?.stop() | ||
| 38 | - audioSwitch = null | 45 | + handler.removeCallbacksAndMessages(null) |
| 46 | + handler.post { | ||
| 47 | + audioSwitch?.stop() | ||
| 48 | + audioSwitch = null | ||
| 49 | + } | ||
| 39 | } | 50 | } |
| 40 | 51 | ||
| 41 | val selectedAudioDevice: AudioDevice? | 52 | val selectedAudioDevice: AudioDevice? |
| @@ -19,21 +19,23 @@ import io.livekit.android.room.participant.Participant | @@ -19,21 +19,23 @@ import io.livekit.android.room.participant.Participant | ||
| 19 | import io.livekit.android.room.participant.RemoteParticipant | 19 | import io.livekit.android.room.participant.RemoteParticipant |
| 20 | import io.livekit.android.room.track.* | 20 | import io.livekit.android.room.track.* |
| 21 | import io.livekit.android.util.flow | 21 | import io.livekit.android.util.flow |
| 22 | -import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
| 23 | import kotlinx.coroutines.flow.* | 22 | import kotlinx.coroutines.flow.* |
| 24 | import kotlinx.coroutines.launch | 23 | import kotlinx.coroutines.launch |
| 25 | import livekit.LivekitRtc | 24 | import livekit.LivekitRtc |
| 26 | 25 | ||
| 27 | -@OptIn(ExperimentalCoroutinesApi::class) | ||
| 28 | class CallViewModel( | 26 | class CallViewModel( |
| 29 | val url: String, | 27 | val url: String, |
| 30 | val token: String, | 28 | val token: String, |
| 31 | application: Application | 29 | application: Application |
| 32 | ) : AndroidViewModel(application) { | 30 | ) : AndroidViewModel(application) { |
| 33 | 31 | ||
| 32 | + val audioHandler = AudioSwitchHandler(application) | ||
| 34 | val room = LiveKit.create( | 33 | val room = LiveKit.create( |
| 35 | appContext = application, | 34 | appContext = application, |
| 36 | options = RoomOptions(adaptiveStream = true, dynacast = true), | 35 | options = RoomOptions(adaptiveStream = true, dynacast = true), |
| 36 | + overrides = LiveKitOverrides( | ||
| 37 | + audioHandler = audioHandler | ||
| 38 | + ) | ||
| 37 | ) | 39 | ) |
| 38 | 40 | ||
| 39 | val participants = room::remoteParticipants.flow | 41 | val participants = room::remoteParticipants.flow |
| @@ -73,7 +75,6 @@ class CallViewModel( | @@ -73,7 +75,6 @@ class CallViewModel( | ||
| 73 | private val mutablePermissionAllowed = MutableStateFlow(true) | 75 | private val mutablePermissionAllowed = MutableStateFlow(true) |
| 74 | val permissionAllowed = mutablePermissionAllowed.hide() | 76 | val permissionAllowed = mutablePermissionAllowed.hide() |
| 75 | 77 | ||
| 76 | - val audioHandler = AudioSwitchHandler(application) | ||
| 77 | init { | 78 | init { |
| 78 | viewModelScope.launch { | 79 | viewModelScope.launch { |
| 79 | launch { | 80 | launch { |
-
请 注册 或 登录 后发表评论