Skip to main content
Monitor participant activities with ParticipantEventListener. This listener provides callbacks for participant join/leave events, audio/video state changes, hand raise actions, screen sharing, recording, and more.

Prerequisites

Register Listener

Register a ParticipantEventListener to receive participant event callbacks:
val callSession = CallSession.getInstance()

callSession.addParticipantEventListener(this, object : ParticipantEventListener() {
    override fun onParticipantJoined(participant: Participant) {
        Log.d(TAG, "${participant.name} joined the call")
    }

    override fun onParticipantLeft(participant: Participant) {
        Log.d(TAG, "${participant.name} left the call")
    }

    override fun onParticipantListChanged(participants: List<Participant>) {
        Log.d(TAG, "Participant list updated: ${participants.size} participants")
    }

    // Additional callbacks...
})
The listener is automatically removed when the LifecycleOwner (Activity/Fragment) is destroyed, preventing memory leaks.

Participant Object

The Participant object contains information about a call participant:
PropertyTypeDescription
uidStringUnique identifier of the participant
nameStringDisplay name of the participant
avatarStringAvatar URL of the participant
isAudioMutedBooleanWhether audio is muted
isVideoPausedBooleanWhether video is paused
isHandRaisedBooleanWhether hand is raised
isScreenSharingBooleanWhether screen is being shared

Callbacks

onParticipantJoined

Triggered when a new participant joins the call.
override fun onParticipantJoined(participant: Participant) {
    Log.d(TAG, "${participant.name} joined the call")
    // Show join notification
    // Update participant grid
}
Use Cases:
  • Display join notification/toast
  • Update participant count
  • Play join sound

onParticipantLeft

Triggered when a participant leaves the call.
override fun onParticipantLeft(participant: Participant) {
    Log.d(TAG, "${participant.name} left the call")
    // Show leave notification
    // Update participant grid
}
Use Cases:
  • Display leave notification
  • Update participant count
  • Play leave sound

onParticipantListChanged

Triggered when the participant list changes (join, leave, or any update).
override fun onParticipantListChanged(participants: List<Participant>) {
    Log.d(TAG, "Participants: ${participants.size}")
    // Update participant list UI
    updateParticipantGrid(participants)
}
Use Cases:
  • Refresh participant list/grid
  • Update participant count badge
  • Sync local state with server

onParticipantAudioMuted

Triggered when a participant mutes their audio.
override fun onParticipantAudioMuted(participant: Participant) {
    Log.d(TAG, "${participant.name} muted their audio")
    // Show muted indicator on participant tile
}

onParticipantAudioUnmuted

Triggered when a participant unmutes their audio.
override fun onParticipantAudioUnmuted(participant: Participant) {
    Log.d(TAG, "${participant.name} unmuted their audio")
    // Hide muted indicator on participant tile
}

onParticipantVideoPaused

Triggered when a participant pauses their video.
override fun onParticipantVideoPaused(participant: Participant) {
    Log.d(TAG, "${participant.name} paused their video")
    // Show avatar or placeholder instead of video
}

onParticipantVideoResumed

Triggered when a participant resumes their video.
override fun onParticipantVideoResumed(participant: Participant) {
    Log.d(TAG, "${participant.name} resumed their video")
    // Show video stream
}

onParticipantHandRaised

Triggered when a participant raises their hand.
override fun onParticipantHandRaised(participant: Participant) {
    Log.d(TAG, "${participant.name} raised their hand")
    // Show hand raised indicator
    // Optionally play notification sound
}

onParticipantHandLowered

Triggered when a participant lowers their hand.
override fun onParticipantHandLowered(participant: Participant) {
    Log.d(TAG, "${participant.name} lowered their hand")
    // Hide hand raised indicator
}

onParticipantStartedScreenShare

Triggered when a participant starts sharing their screen.
override fun onParticipantStartedScreenShare(participant: Participant) {
    Log.d(TAG, "${participant.name} started screen sharing")
    // Switch to screen share view
    // Show screen share indicator
}

onParticipantStoppedScreenShare

Triggered when a participant stops sharing their screen.
override fun onParticipantStoppedScreenShare(participant: Participant) {
    Log.d(TAG, "${participant.name} stopped screen sharing")
    // Switch back to normal view
    // Hide screen share indicator
}

onParticipantStartedRecording

Triggered when a participant starts recording the session.
override fun onParticipantStartedRecording(participant: Participant) {
    Log.d(TAG, "${participant.name} started recording")
    // Show recording indicator
    // Notify other participants
}

onParticipantStoppedRecording

Triggered when a participant stops recording the session.
override fun onParticipantStoppedRecording(participant: Participant) {
    Log.d(TAG, "${participant.name} stopped recording")
    // Hide recording indicator
}

onDominantSpeakerChanged

Triggered when the dominant speaker changes (the participant currently speaking the loudest).
override fun onDominantSpeakerChanged(participant: Participant) {
    Log.d(TAG, "${participant.name} is now the dominant speaker")
    // Highlight the dominant speaker's tile
    // Auto-focus on dominant speaker in spotlight mode
}
Use Cases:
  • Highlight active speaker in UI
  • Auto-switch spotlight to dominant speaker
  • Show speaking indicator animation

Complete Example

Here’s a complete example handling all participant events:
class CallActivity : AppCompatActivity() {
    private lateinit var callSession: CallSession

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_call)

        callSession = CallSession.getInstance()
        setupParticipantEventListener()
    }

    private fun setupParticipantEventListener() {
        callSession.addParticipantEventListener(this, object : ParticipantEventListener() {
            override fun onParticipantJoined(participant: Participant) {
                runOnUiThread {
                    showToast("${participant.name} joined")
                }
            }

            override fun onParticipantLeft(participant: Participant) {
                runOnUiThread {
                    showToast("${participant.name} left")
                }
            }

            override fun onParticipantListChanged(participants: List<Participant>) {
                runOnUiThread {
                    updateParticipantCount(participants.size)
                }
            }

            override fun onParticipantAudioMuted(participant: Participant) {
                runOnUiThread {
                    updateParticipantAudioState(participant.uid, isMuted = true)
                }
            }

            override fun onParticipantAudioUnmuted(participant: Participant) {
                runOnUiThread {
                    updateParticipantAudioState(participant.uid, isMuted = false)
                }
            }

            override fun onParticipantVideoPaused(participant: Participant) {
                runOnUiThread {
                    updateParticipantVideoState(participant.uid, isPaused = true)
                }
            }

            override fun onParticipantVideoResumed(participant: Participant) {
                runOnUiThread {
                    updateParticipantVideoState(participant.uid, isPaused = false)
                }
            }

            override fun onParticipantHandRaised(participant: Participant) {
                runOnUiThread {
                    showHandRaisedIndicator(participant.uid, isRaised = true)
                }
            }

            override fun onParticipantHandLowered(participant: Participant) {
                runOnUiThread {
                    showHandRaisedIndicator(participant.uid, isRaised = false)
                }
            }

            override fun onParticipantStartedScreenShare(participant: Participant) {
                runOnUiThread {
                    showScreenShareView(participant)
                }
            }

            override fun onParticipantStoppedScreenShare(participant: Participant) {
                runOnUiThread {
                    hideScreenShareView()
                }
            }

            override fun onParticipantStartedRecording(participant: Participant) {
                runOnUiThread {
                    showRecordingIndicator(true)
                }
            }

            override fun onParticipantStoppedRecording(participant: Participant) {
                runOnUiThread {
                    showRecordingIndicator(false)
                }
            }

            override fun onDominantSpeakerChanged(participant: Participant) {
                runOnUiThread {
                    highlightDominantSpeaker(participant.uid)
                }
            }
        })
    }

    // UI helper methods
    private fun showToast(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }

    private fun updateParticipantCount(count: Int) { /* ... */ }
    private fun updateParticipantAudioState(uid: String, isMuted: Boolean) { /* ... */ }
    private fun updateParticipantVideoState(uid: String, isPaused: Boolean) { /* ... */ }
    private fun showHandRaisedIndicator(uid: String, isRaised: Boolean) { /* ... */ }
    private fun showScreenShareView(participant: Participant) { /* ... */ }
    private fun hideScreenShareView() { /* ... */ }
    private fun showRecordingIndicator(show: Boolean) { /* ... */ }
    private fun highlightDominantSpeaker(uid: String) { /* ... */ }

    companion object {
        private const val TAG = "CallActivity"
    }
}

Callbacks Summary

CallbackParameterDescription
onParticipantJoinedParticipantA participant joined the call
onParticipantLeftParticipantA participant left the call
onParticipantListChangedList<Participant>Participant list was updated
onParticipantAudioMutedParticipantA participant muted their audio
onParticipantAudioUnmutedParticipantA participant unmuted their audio
onParticipantVideoPausedParticipantA participant paused their video
onParticipantVideoResumedParticipantA participant resumed their video
onParticipantHandRaisedParticipantA participant raised their hand
onParticipantHandLoweredParticipantA participant lowered their hand
onParticipantStartedScreenShareParticipantA participant started screen sharing
onParticipantStoppedScreenShareParticipantA participant stopped screen sharing
onParticipantStartedRecordingParticipantA participant started recording
onParticipantStoppedRecordingParticipantA participant stopped recording
onDominantSpeakerChangedParticipantThe dominant speaker changed

Next Steps