steep-balloon-41261
05/27/2026, 7:11 AMtall-airline-16756
05/27/2026, 7:11 AMtall-airline-16756
05/27/2026, 7:11 AMLocalAudioTrack (create, publish, setEnabled() to mute/unmute, setVolume() to adjust).
• Handle audio routing (speaker, earpiece, Bluetooth) via the SDK’s audio switching helper (AudioSwitchHandler) which manages device changes and transitions.
• Manage audio focus and interruptions by integrating with Android’s AudioManager (the SDK integrates with audio focus handling; ensure your app responds on focus loss/gain).
• Request and declare RECORD_AUDIO permission at runtime.
• Control background behavior by using a foreground service if you need audio while the app is backgrounded and by handling lifecycle events (`onPause`/`onResume`) appropriately.
• Opus DTX (silence suppression) is enabled by default to reduce bitrate; it can be changed at track publish time if needed.
Basic example (conceptual Kotlin)
1. Create & publish microphone track:
val localAudioTrack = LocalAudioTrack.createMicrophoneTrack(context, "mic")
localParticipant.publishAudioTrack(localAudioTrack)
1. Mute/unmute:
localAudioTrack.setEnabled(false) // mute
localAudioTrack.setEnabled(true) // unmute
1. Adjust volume:
localAudioTrack.setVolume(0.5f)
Routing & focus notes
• Use the SDK’s audio switch handler to let users select Bluetooth/speaker/earpiece and to handle automatic device changes.
• Make sure your app requests audio focus via AudioManager and responds to focus changes (pause or duck as appropriate).
• For background audio, run a foreground service with a notification if you need to keep the microphone or playback active when the app is not visible.
If you’d like, I can:
• Share a full code sample for integrating AudioSwitchHandler and audio focus handling.
• Walk through implementing a simple audio device selection UI.
Which of those would you prefer?
Sources: Bringing Zoom's end-to-end optimizations to WebRTC | LiveKit | Bringing Zoom's end-to-end optimizations to WebRTC | LiveKit, with interactive elementsbig-article-66702
05/27/2026, 7:13 AMtall-airline-16756
05/27/2026, 7:14 AMTrackSubscribed) and get a RemoteAudioTrack.
• Control local playback volume for each remote track with remoteAudioTrack.setVolume(float).
• Detect remote mute/unmute via track events (trackMuted, trackUnmuted) and update UI or play indicators.
• Unsubscribe from a remote publication to stop receiving audio and save bandwidth with remoteTrackPublication.setSubscribed(false).
• Let the SDK manage audio routing (speaker, earpiece, Bluetooth) via the AudioSwitchHandler so remote playback follows the device’s current audio route.
• Rely on participant lifecycle events (ParticipantConnected, ParticipantDisconnected, TrackUnsubscribed) to keep state in sync.
Quick conceptual Kotlin snippets
1. Handle track subscription:
// inside room event handler
if (event is RoomEvent.TrackSubscribed && event.track is RemoteAudioTrack) {
val remoteAudio = event.track as RemoteAudioTrack
// store and control this track
remoteAudio.setVolume(1.0f)
}
1. Detect mute/unmute:
if (event is RoomEvent.TrackMuted) { /* update UI */ }
if (event is RoomEvent.TrackUnmuted) { /* update UI */ }
1. Unsubscribe:
remoteTrackPublication.setSubscribed(false)
Would you like a full sample that wires Room event handling, a per-participant volume UI, and audio device selection with AudioSwitchHandler?
, with interactive elementsbig-article-66702
05/27/2026, 7:15 AMtall-airline-16756
05/27/2026, 7:15 AMval room = Room(options) // create Room per your app setup
room.connect(url, token)
2) Start local microphone and publish
// create mic track and publish
val localAudioTrack = LocalAudioTrack.createMicrophoneTrack(context, "mic")
room.localParticipant?.publishTrack(localAudioTrack)
3) Mute/unmute local mic
// toggle mic
localAudioTrack.setEnabled(false) // mute
localAudioTrack.setEnabled(true) // unmute
4) Initialize AudioSwitchHandler (device selection + routing)
val audioSwitchHandler = AudioSwitchHandler(context)
// start monitoring available devices (call during call start)
audioSwitchHandler.start { selectedDevice ->
// SDK will route audio to selectedDevice (SPEAKER, EARPIECE, BLUETOOTH, etc.)
// update UI to reflect selected device
}
// stop when call ends
audioSwitchHandler.stop()
5) Room event handling: subscribe to remote tracks and maintain map of remote audio tracks
val remoteAudioTracks = mutableMapOf<String, RemoteAudioTrack>() // key by track sid or participant id
room.addListener { event ->
when (event) {
is RoomEvent.TrackSubscribed -> {
val track = event.track
if (track is RemoteAudioTrack) {
remoteAudioTracks[event.trackSid] = track
// start playback (SDK handles rendering) and set default volume
track.setVolume(1.0f)
}
}
is RoomEvent.TrackUnsubscribed -> {
remoteAudioTracks.remove(event.trackSid)
}
is RoomEvent.TrackMuted -> {
// update UI to show muted state for event.trackSid
}
is RoomEvent.TrackUnmuted -> {
// update UI to show unmuted state
}
is RoomEvent.ParticipantConnected -> { /* update participant list */ }
is RoomEvent.ParticipantDisconnected -> {
// remove all tracks for that participant
}
}
}
6) Per-participant volume UI control
// Example: user moves a slider for participant with trackSid
fun onVolumeSliderChanged(trackSid: String, value: Float) {
remoteAudioTracks[trackSid]?.setVolume(value) // value 0.0 - 1.0
}
7) Unsubscribe from a remote track to save bandwidth
// get the publication object (example assumes you have it)
remoteTrackPublication.setSubscribed(false)
8) Handle audio focus and lifecycle
• Request audio focus via Android AudioManager when starting the call and abandon on end.
• Pause or duck audio on focus loss as appropriate.
• Use a foreground service with notification if you must keep audio active while backgrounded.
9) Permissions
• Request RECORD_AUDIO at runtime before creating microphone track.
Notes and tips
• The SDK handles native rendering and routing when you use AudioSwitchHandler — you only need to start it and react to device selection.
• Use room events (`TrackMuted`/`TrackUnmuted`) to reflect remote participants’ mute state in your UI.
• Adjust RemoteAudioTrack.setVolume per participant for local playback levels without affecting sender.
Would you like a full runnable sample project (Activity + layout + AudioSwitchHandler wiring) or a focused snippet for the device-selection UI?
, with interactive elements