Skip to main content
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...
})
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)
}
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)
}
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
}
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
}
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
}
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)
}
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
}
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
}
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)
    }
}
AudioMode Values:
ValueDescription
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)
    }
}
CameraFacing Values:
ValueDescription
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"
    }
}

Callbacks Summary

CallbackParameterDescription
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