Skip to main content
Version: 3.x.x

Manage Audio and Video Devices - Android

This feature allows hosts to switch their microphone, speaker, or camera devices during a live stream. Audience members (in RECV_ONLY mode) don't publish media, but they can still use changeMic() to pick the speaker, earpiece, wired headset or Bluetooth device they listen on.

Changing Input/Output Audio Device​

getMics()​
  • The getMics() method of the VideoSDK class provides all available audio devices, which can be shown in a dropdown for selection.

  • It returns a List of MicrophoneDeviceInfo. These are audio routes (SPEAKER_PHONE, EARPIECE, WIRED_HEADSET, BLUETOOTH): 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.

changeMic()​
  • A participant can change the audio device using changeMic(deviceId: String?) method of Room class. 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(), wrapping around.

  • To switch to a microphone track you created with VideoSDK.createMicrophoneAudioTrack(), pass the track: changeMic(customMicrophoneTrack). It unmutes the mic if it was muted, so only a host can do this. For an audience member, it throws VideoSDKException with 3066 (ERROR_ACTION_NOT_SUPPORTED_IN_MODE).

  • It throws VideoSDKException with 3059 (ERROR_NO_MICROPHONE_DEVICE_FOUND) when the device is not in VideoSDK.getMics(). That error is also reported on onError.

  • Called before the live stream is joined, or while it is reconnecting, it reports 3035 (ERROR_ACTION_PERFORMED_BEFORE_ROOM_JOINED) or 3065 (ERROR_ROOM_RECONNECTING) on onError and also throws it.

  • The deviceId values that can be passed to changeMic are

    Device IDUsage
    BLUETOOTHFor Bluetooth Device.
    WIRED_HEADSETFor Wired Headset Device.
    SPEAKER_PHONEFor Inbuilt - Speaker Device
    EARPIECEFor Earpiece Device
  • To route audio to a device without restarting a live mic, call setAudioDevice() on the Room with a MicrophoneDeviceInfo from VideoSDK.getMics(). It works before the join too. It throws VideoSDKException with 3059 (ERROR_NO_MICROPHONE_DEVICE_FOUND), also reported on onError, when the device is not one of the routes VideoSDK.getMics() lists right now. The audio routing is then left as it was.

  • When the participant changes the mic, or an audio device is connected or removed, the AudioDeviceChangeEvent you set on the Room with setAudioDeviceChangeListener() is called. It is also called once right away with the current device. selectedAudioDevice is null only when no audio device is available.

  • 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 getMics(): List<MicrophoneDeviceInfo> {
val mics = VideoSDK.getMics()
return mics // returns all connected mics
}

btnChangeMic!!.setOnClickListener { _: View? ->
// Change Mic during the live stream
lifecycleScope.launch {
try {
liveStream!!.changeMic("BLUETOOTH")
} catch (e: VideoSDKException) {
Log.e("VideoSDK", "Mic change failed: ${e.code} ${e.name}")
}
}
}

private fun setAudioDeviceListeners() {
liveStream!!.setAudioDeviceChangeListener { selectedAudioDevice, availableAudioDevices ->
when (selectedAudioDevice?.deviceId) {
"BLUETOOTH" ->
Toast.makeText(this@MainActivity, "Selected AudioDevice: BLUETOOTH", Toast.LENGTH_SHORT).show()

"WIRED_HEADSET" ->
Toast.makeText(this@MainActivity, "Selected AudioDevice: WIRED_HEADSET", Toast.LENGTH_SHORT).show()

"SPEAKER_PHONE" ->
Toast.makeText(this@MainActivity, "Selected AudioDevice: SPEAKER_PHONE", Toast.LENGTH_SHORT).show()

"EARPIECE" ->
Toast.makeText(this@MainActivity, "Selected AudioDevice: EARPIECE", Toast.LENGTH_SHORT).show()

else -> Unit
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
// ...
setAudioDeviceListeners()
}
  • To use a 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()​
  • To change the camera device of the host, you need to call changeCam() method.

  • 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 camera whose facingMode is FacingMode.back.

  • If the camera is on, it is turned off and on again on the new camera, so onStreamDisabled and then onStreamEnabled fire for every participant. A camera 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. Before the join, or while reconnecting, it reports and throws 3035 or 3065, like changeMic().

  • To switch to a camera track you created with VideoSDK.createCameraVideoTrack(), pass the track: changeCam(customCameraTrack). It turns the camera on if it was off, so for an audience member it throws 3066 (ERROR_ACTION_NOT_SUPPORTED_IN_MODE).

Example​

btnWebcam!!.setOnClickListener {
lifecycleScope.launch {
try {
// Change camera during liveStream
liveStream!!.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) {
liveStream!!.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