Skip to main content
Version: 3.x.x

Change Input/Output Device - Android

A participant can switch their audio or video device at any point in the room using the methods below.

Changing Input/Output Audio Device​

getMics()​

  • VideoSDK.getMics() returns the audio devices you can switch to right now.

  • It is a List of MicrophoneDeviceInfo. Each entry has a label to show in a picker and a deviceId: SPEAKER_PHONE, EARPIECE, WIRED_HEADSET or BLUETOOTH.

  • These are audio routes. Android has no separate list of microphones, so switching to a wired headset or Bluetooth device switches the microphone too.

  • It is empty until VideoSDK.initialize() has run.

private fun getMics(): List<MicrophoneDeviceInfo> {
val mics = VideoSDK.getMics()
return mics // the audio routes available right now
}

changeMic()​

  • Call room.changeMic(deviceId) to switch the audio device. Pass the deviceId of a device from VideoSDK.getMics().

  • changeMic() is a suspend function. Call it from a coroutine, such as lifecycleScope.launch (from androidx.lifecycle:lifecycle-runtime-ktx).

  • If the mic is on, it is turned off and on again on the new device, so onStreamDisabled and then onStreamEnabled fire for every participant. A muted mic stays muted, and the next unmuteMic() uses the new device.

  • With no argument, changeMic() moves to the next device in VideoSDK.getMics().

  • To switch to a microphone track you created with VideoSDK.createMicrophoneAudioTrack(), pass the track: changeMic(customMicrophoneTrack). It unmutes the mic if it was muted.

  • It throws VideoSDKException with 3059 (ERROR_NO_MICROPHONE_DEVICE_FOUND) when the device is not one of the devices VideoSDK.getMics() lists right now, for example a headset that was unplugged. That error is also reported on onError, and nothing changes.

  • The deviceId values that can be passed to changeMic are

    deviceIdUsage
    BLUETOOTHFor Bluetooth Device.
    WIRED_HEADSETFor Wired Headset Device.
    SPEAKER_PHONEFor Inbuilt - Speaker Device
    EARPIECEFor Earpiece Device

setAudioDevice()​

  • setAudioDevice(device: MicrophoneDeviceInfo) of the Room class routes call audio to a device from VideoSDK.getMics().

  • Unlike changeMic(), it does not restart a live microphone. It also works before the room is joined.

  • It throws VideoSDKException with 3059 (ERROR_NO_MICROPHONE_DEVICE_FOUND) when the device is not one of the routes VideoSDK.getMics() lists right now. That error is also reported on onError, and the audio route stays as it was.

setAudioDeviceChangeListener()​

  • When the participant changes the mic, or an audio device is connected or removed, the AudioDeviceChangeEvent listener is called. Set it with setAudioDeviceChangeListener() of the Room class. It is also called once right away with the current device. selectedAudioDevice is null only when no audio device is available, which is always the case before VideoSDK.initialize().

  • AudioDeviceChangeEvent is a fun interface, so you can pass a lambda.

  • The listener is kept for the whole app and stays registered after leave(). Pass null to setAudioDeviceChangeListener() when your screen is destroyed, so the listener doesn't keep your Activity in memory.

Example​

private fun setupAudioButtons() {
btnChangeMic!!.setOnClickListener { _: View? ->
// Change Mic during the room
lifecycleScope.launch {
try {
val bluetooth = VideoSDK.getMics().firstOrNull { it.deviceId == "BLUETOOTH" }
if (bluetooth != null) {
room!!.changeMic(bluetooth.deviceId)
}
} catch (e: VideoSDKException) {
Log.e("VideoSDK", "Mic change failed: ${e.code} ${e.name}")
}
}
}

btnSpeaker!!.setOnClickListener { _: View? ->
val speaker = VideoSDK.getMics().firstOrNull { it.deviceId == "SPEAKER_PHONE" }
if (speaker != null) {
try {
room!!.setAudioDevice(speaker)
} catch (e: VideoSDKException) {
// 3059: the device is no longer available
Log.e("VideoSDK", "Audio device change failed: ${e.code} ${e.name}")
}
}
}
}

private fun setAudioDeviceListeners() {
room!!.setAudioDeviceChangeListener { selectedAudioDevice, audioDevices ->
if (selectedAudioDevice != null) {
Toast.makeText(this@MainActivity, "Selected AudioDevice: ${selectedAudioDevice.label}", Toast.LENGTH_SHORT).show()
}
Log.d("VideoSDK", "Available audio devices: ${audioDevices.map { it.label }}")
}
}

override fun onCreate(savedInstanceState: Bundle?) {
// ...
setupAudioButtons()
setAudioDeviceListeners()
}

override fun onDestroy() {
room?.setAudioDeviceChangeListener(null)
super.onDestroy()
}
  • To use Bluetooth device, you must declare BLUETOOTH permission in AndroidManifest.xml file.
AndroidManifest.xml
<manifest ... >
<!-- ... -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
</manifest>
  • On Android 12 and later, BLUETOOTH_CONNECT is also a runtime permission. Request it before you switch audio to a Bluetooth device, for example with VideoSDK.checkPermissions() and Permission.bluetooth.

Changing Camera Input Device​

changeCam()​

  • Call room.changeCam() to switch the camera during the call, for example between the front and rear camera.

  • changeCam() is a suspend function. Call it from a coroutine.

  • With no argument, it moves to the next camera in VideoSDK.getCameras(), wrapping around. On a phone with one front and one rear camera, this switches between them. To pick a specific camera, pass its deviceId, for example the CameraDeviceInfo whose facingMode is FacingMode.back.

  • If the webcam is on, it is turned off and on again on the new camera, so onStreamDisabled and then onStreamEnabled fire for every participant. A webcam that is off stays off, and the next enableCam() uses the new camera.

  • It throws VideoSDKException with 3051 (ERROR_NO_WEBCAM_DEVICE_FOUND) when no camera has that deviceId. That error is also reported on onError, and nothing changes.

  • To switch to a camera track you created with VideoSDK.createCameraVideoTrack(), pass the track: changeCam(customCameraTrack). It turns the webcam on if it was off.

Example​

btnWebcam!!.setOnClickListener {
lifecycleScope.launch {
try {
// Change camera during the room
room!!.changeCam()
} catch (e: VideoSDKException) {
Log.e("VideoSDK", "Camera change failed: ${e.code} ${e.name}")
}
}
}

To switch to the rear camera:

lifecycleScope.launch {
try {
val backCamera = VideoSDK.getCameras().firstOrNull { it.facingMode == FacingMode.back }
if (backCamera != null) {
room!!.changeCam(backCamera.deviceId)
}
} catch (e: VideoSDKException) {
Log.e("VideoSDK", "Camera change failed: ${e.code} ${e.name}")
}
}

API Reference​

The API references for all the methods and events utilised in this guide are provided below.

Got a Question? Ask us on discord