Monitor local media state changes with MediaEventsListener. This listener provides callbacks for your own audio/video state changes, recording events, screen sharing, audio mode changes, and camera facing changes.
Prerequisites
Register Listener
Register a MediaEventsListener to receive media event callbacks:
val callSession = CallSession. getInstance ()
callSession. addMediaEventsListener ( this , object : MediaEventsListener () {
override fun onAudioMuted () {
Log. d (TAG, "Audio muted" )
}
override fun onAudioUnMuted () {
Log. d (TAG, "Audio unmuted" )
}
override fun onVideoPaused () {
Log. d (TAG, "Video paused" )
}
override fun onVideoResumed () {
Log. d (TAG, "Video resumed" )
}
// Additional callbacks...
})
CallSession callSession = CallSession . getInstance ();
callSession . addMediaEventsListener ( this , new MediaEventsListener () {
@ Override
public void onAudioMuted () {
Log . d (TAG, "Audio muted" );
}
@ Override
public void onAudioUnMuted () {
Log . d (TAG, "Audio unmuted" );
}
@ Override
public void onVideoPaused () {
Log . d (TAG, "Video paused" );
}
@ Override
public void onVideoResumed () {
Log . d (TAG, "Video resumed" );
}
// Additional callbacks...
});
The listener is automatically removed when the LifecycleOwner (Activity/Fragment) is destroyed, preventing memory leaks.
Callbacks
onAudioMuted
Triggered when your local audio is muted.
override fun onAudioMuted () {
Log. d (TAG, "Audio muted" )
// Update mute button UI state
updateMuteButtonState (isMuted = true )
}
@ Override
public void onAudioMuted () {
Log . d (TAG, "Audio muted" );
// Update mute button UI state
updateMuteButtonState ( true );
}
Use Cases:
Update mute button icon/state
Show muted indicator in UI
Sync UI with actual audio state
onAudioUnMuted
Triggered when your local audio is unmuted.
override fun onAudioUnMuted () {
Log. d (TAG, "Audio unmuted" )
// Update mute button UI state
updateMuteButtonState (isMuted = false )
}
@ Override
public void onAudioUnMuted () {
Log . d (TAG, "Audio unmuted" );
// Update mute button UI state
updateMuteButtonState ( false );
}
Use Cases:
Update mute button icon/state
Hide muted indicator
Sync UI with actual audio state
onVideoPaused
Triggered when your local video is paused.
override fun onVideoPaused () {
Log. d (TAG, "Video paused" )
// Update video button UI state
updateVideoButtonState (isPaused = true )
// Show avatar instead of video preview
}
@ Override
public void onVideoPaused () {
Log . d (TAG, "Video paused" );
// Update video button UI state
updateVideoButtonState ( true );
// Show avatar instead of video preview
}
Use Cases:
Update video toggle button state
Show avatar/placeholder in local preview
Sync UI with actual video state
onVideoResumed
Triggered when your local video is resumed.
override fun onVideoResumed () {
Log. d (TAG, "Video resumed" )
// Update video button UI state
updateVideoButtonState (isPaused = false )
// Show video preview
}
@ Override
public void onVideoResumed () {
Log . d (TAG, "Video resumed" );
// Update video button UI state
updateVideoButtonState ( false );
// Show video preview
}
Use Cases:
Update video toggle button state
Show local video preview
Sync UI with actual video state
onRecordingStarted
Triggered when session recording starts.
override fun onRecordingStarted () {
Log. d (TAG, "Recording started" )
// Show recording indicator
showRecordingIndicator ( true )
// Notify user that recording is active
}
@ Override
public void onRecordingStarted () {
Log . d (TAG, "Recording started" );
// Show recording indicator
showRecordingIndicator ( true );
// Notify user that recording is active
}
Use Cases:
Display recording indicator (red dot)
Update recording button state
Show notification to participants
onRecordingStopped
Triggered when session recording stops.
override fun onRecordingStopped () {
Log. d (TAG, "Recording stopped" )
// Hide recording indicator
showRecordingIndicator ( false )
}
@ Override
public void onRecordingStopped () {
Log . d (TAG, "Recording stopped" );
// Hide recording indicator
showRecordingIndicator ( false );
}
Use Cases:
Hide recording indicator
Update recording button state
Show recording saved notification
onScreenShareStarted
Triggered when you start sharing your screen.
override fun onScreenShareStarted () {
Log. d (TAG, "Screen sharing started" )
// Update screen share button state
updateScreenShareButtonState (isSharing = true )
// Show screen share preview
}
@ Override
public void onScreenShareStarted () {
Log . d (TAG, "Screen sharing started" );
// Update screen share button state
updateScreenShareButtonState ( true );
// Show screen share preview
}
Use Cases:
Update screen share button state
Show “You are sharing” indicator
Minimize local video preview
onScreenShareStopped
Triggered when you stop sharing your screen.
override fun onScreenShareStopped () {
Log. d (TAG, "Screen sharing stopped" )
// Update screen share button state
updateScreenShareButtonState (isSharing = false )
// Restore normal view
}
@ Override
public void onScreenShareStopped () {
Log . d (TAG, "Screen sharing stopped" );
// Update screen share button state
updateScreenShareButtonState ( false );
// Restore normal view
}
Use Cases:
Update screen share button state
Hide “You are sharing” indicator
Restore local video preview
onAudioModeChanged
Triggered when the audio output mode changes (speaker, earpiece, bluetooth).
override fun onAudioModeChanged (audioMode: AudioMode ) {
Log. d (TAG, "Audio mode changed to: $audioMode " )
// Update audio mode button/icon
when (audioMode) {
AudioMode.SPEAKER -> updateAudioModeIcon (R.drawable.ic_speaker)
AudioMode.EARPIECE -> updateAudioModeIcon (R.drawable.ic_earpiece)
AudioMode.BLUETOOTH -> updateAudioModeIcon (R.drawable.ic_bluetooth)
}
}
@ Override
public void onAudioModeChanged ( AudioMode audioMode) {
Log . d (TAG, "Audio mode changed to: " + audioMode);
// Update audio mode button/icon
switch (audioMode) {
case SPEAKER :
updateAudioModeIcon ( R . drawable . ic_speaker );
break ;
case EARPIECE :
updateAudioModeIcon ( R . drawable . ic_earpiece );
break ;
case BLUETOOTH :
updateAudioModeIcon ( R . drawable . ic_bluetooth );
break ;
}
}
AudioMode Values:
Value Description SPEAKERAudio output through device speaker EARPIECEAudio output through earpiece BLUETOOTHAudio output through connected Bluetooth device
Use Cases:
Update audio mode button icon
Show current audio output device
Handle Bluetooth connection/disconnection
onCameraFacingChanged
Triggered when the camera facing changes (front/back).
override fun onCameraFacingChanged (facing: CameraFacing ) {
Log. d (TAG, "Camera facing changed to: $facing " )
// Update camera switch button state
when (facing) {
CameraFacing.FRONT -> updateCameraIcon (R.drawable.ic_camera_front)
CameraFacing.BACK -> updateCameraIcon (R.drawable.ic_camera_back)
}
}
@ Override
public void onCameraFacingChanged ( CameraFacing facing) {
Log . d (TAG, "Camera facing changed to: " + facing);
// Update camera switch button state
switch (facing) {
case FRONT :
updateCameraIcon ( R . drawable . ic_camera_front );
break ;
case BACK :
updateCameraIcon ( R . drawable . ic_camera_back );
break ;
}
}
CameraFacing Values:
Value Description FRONTFront-facing camera (selfie camera) BACKBack-facing camera (main camera)
Use Cases:
Update camera switch button icon
Adjust UI for mirrored/non-mirrored preview
Track camera state
Complete Example
Here’s a complete example handling all media events:
class CallActivity : AppCompatActivity () {
private lateinit var callSession: CallSession
private lateinit var muteButton: ImageButton
private lateinit var videoButton: ImageButton
private lateinit var screenShareButton: ImageButton
private lateinit var audioModeButton: ImageButton
private lateinit var recordingIndicator: View
override fun onCreate (savedInstanceState: Bundle ?) {
super . onCreate (savedInstanceState)
setContentView (R.layout.activity_call)
initViews ()
callSession = CallSession. getInstance ()
setupMediaEventsListener ()
}
private fun initViews () {
muteButton = findViewById (R.id.muteButton)
videoButton = findViewById (R.id.videoButton)
screenShareButton = findViewById (R.id.screenShareButton)
audioModeButton = findViewById (R.id.audioModeButton)
recordingIndicator = findViewById (R.id.recordingIndicator)
}
private fun setupMediaEventsListener () {
callSession. addMediaEventsListener ( this , object : MediaEventsListener () {
override fun onAudioMuted () {
runOnUiThread {
muteButton. setImageResource (R.drawable.ic_mic_off)
muteButton.isSelected = true
}
}
override fun onAudioUnMuted () {
runOnUiThread {
muteButton. setImageResource (R.drawable.ic_mic_on)
muteButton.isSelected = false
}
}
override fun onVideoPaused () {
runOnUiThread {
videoButton. setImageResource (R.drawable.ic_videocam_off)
videoButton.isSelected = true
}
}
override fun onVideoResumed () {
runOnUiThread {
videoButton. setImageResource (R.drawable.ic_videocam_on)
videoButton.isSelected = false
}
}
override fun onRecordingStarted () {
runOnUiThread {
recordingIndicator.visibility = View.VISIBLE
Toast. makeText (
this@CallActivity ,
"Recording started" ,
Toast.LENGTH_SHORT
). show ()
}
}
override fun onRecordingStopped () {
runOnUiThread {
recordingIndicator.visibility = View.GONE
Toast. makeText (
this@CallActivity ,
"Recording stopped" ,
Toast.LENGTH_SHORT
). show ()
}
}
override fun onScreenShareStarted () {
runOnUiThread {
screenShareButton.isSelected = true
Toast. makeText (
this@CallActivity ,
"You are sharing your screen" ,
Toast.LENGTH_SHORT
). show ()
}
}
override fun onScreenShareStopped () {
runOnUiThread {
screenShareButton.isSelected = false
}
}
override fun onAudioModeChanged (audioMode: AudioMode ) {
runOnUiThread {
val iconRes = when (audioMode) {
AudioMode.SPEAKER -> R.drawable.ic_volume_up
AudioMode.EARPIECE -> R.drawable.ic_phone_in_talk
AudioMode.BLUETOOTH -> R.drawable.ic_bluetooth_audio
}
audioModeButton. setImageResource (iconRes)
}
}
override fun onCameraFacingChanged (facing: CameraFacing ) {
runOnUiThread {
Log. d (TAG, "Camera switched to: $facing " )
}
}
})
}
companion object {
private const val TAG = "CallActivity"
}
}
public class CallActivity extends AppCompatActivity {
private static final String TAG = "CallActivity" ;
private CallSession callSession ;
private ImageButton muteButton ;
private ImageButton videoButton ;
private ImageButton screenShareButton ;
private ImageButton audioModeButton ;
private View recordingIndicator ;
@ Override
protected void onCreate ( Bundle savedInstanceState ) {
super . onCreate (savedInstanceState);
setContentView ( R . layout . activity_call );
initViews ();
callSession = CallSession . getInstance ();
setupMediaEventsListener ();
}
private void initViews () {
muteButton = findViewById ( R . id . muteButton );
videoButton = findViewById ( R . id . videoButton );
screenShareButton = findViewById ( R . id . screenShareButton );
audioModeButton = findViewById ( R . id . audioModeButton );
recordingIndicator = findViewById ( R . id . recordingIndicator );
}
private void setupMediaEventsListener () {
callSession . addMediaEventsListener ( this , new MediaEventsListener () {
@ Override
public void onAudioMuted () {
runOnUiThread (() -> {
muteButton . setImageResource ( R . drawable . ic_mic_off );
muteButton . setSelected ( true );
});
}
@ Override
public void onAudioUnMuted () {
runOnUiThread (() -> {
muteButton . setImageResource ( R . drawable . ic_mic_on );
muteButton . setSelected ( false );
});
}
@ Override
public void onVideoPaused () {
runOnUiThread (() -> {
videoButton . setImageResource ( R . drawable . ic_videocam_off );
videoButton . setSelected ( true );
});
}
@ Override
public void onVideoResumed () {
runOnUiThread (() -> {
videoButton . setImageResource ( R . drawable . ic_videocam_on );
videoButton . setSelected ( false );
});
}
@ Override
public void onRecordingStarted () {
runOnUiThread (() -> {
recordingIndicator . setVisibility ( View . VISIBLE );
Toast . makeText (
CallActivity . this ,
"Recording started" ,
Toast . LENGTH_SHORT
). show ();
});
}
@ Override
public void onRecordingStopped () {
runOnUiThread (() -> {
recordingIndicator . setVisibility ( View . GONE );
Toast . makeText (
CallActivity . this ,
"Recording stopped" ,
Toast . LENGTH_SHORT
). show ();
});
}
@ Override
public void onScreenShareStarted () {
runOnUiThread (() -> {
screenShareButton . setSelected ( true );
Toast . makeText (
CallActivity . this ,
"You are sharing your screen" ,
Toast . LENGTH_SHORT
). show ();
});
}
@ Override
public void onScreenShareStopped () {
runOnUiThread (() -> screenShareButton . setSelected ( false ));
}
@ Override
public void onAudioModeChanged ( AudioMode audioMode ) {
runOnUiThread (() -> {
int iconRes ;
switch (audioMode) {
case SPEAKER :
iconRes = R . drawable . ic_volume_up ;
break ;
case EARPIECE :
iconRes = R . drawable . ic_phone_in_talk ;
break ;
case BLUETOOTH :
iconRes = R . drawable . ic_bluetooth_audio ;
break ;
default:
iconRes = R . drawable . ic_volume_up ;
}
audioModeButton . setImageResource (iconRes);
});
}
@ Override
public void onCameraFacingChanged ( CameraFacing facing ) {
runOnUiThread (() -> Log . d (TAG, "Camera switched to: " + facing));
}
});
}
}
Callbacks Summary
Callback Parameter Description onAudioMuted- Local audio was muted onAudioUnMuted- Local audio was unmuted onVideoPaused- Local video was paused onVideoResumed- Local video was resumed onRecordingStarted- Session recording started onRecordingStopped- Session recording stopped onScreenShareStarted- Local screen sharing started onScreenShareStopped- Local screen sharing stopped onAudioModeChangedAudioModeAudio output mode changed onCameraFacingChangedCameraFacingCamera facing changed
Next Steps
Button Click Listener Handle UI button click events
Audio Controls Control audio programmatically