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...
})
CallSession callSession = CallSession.getInstance();
callSession.addParticipantEventListener(this, new ParticipantEventListener() {
@Override
public void onParticipantJoined(Participant participant) {
Log.d(TAG, participant.getName() + " joined the call");
}
@Override
public void onParticipantLeft(Participant participant) {
Log.d(TAG, participant.getName() + " left the call");
}
@Override
public void onParticipantListChanged(List<Participant> participants) {
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:
| Property | Type | Description |
|---|
uid | String | Unique identifier of the participant |
name | String | Display name of the participant |
avatar | String | Avatar URL of the participant |
isAudioMuted | Boolean | Whether audio is muted |
isVideoPaused | Boolean | Whether video is paused |
isHandRaised | Boolean | Whether hand is raised |
isScreenSharing | Boolean | Whether 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
}
@Override
public void onParticipantJoined(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantLeft(Participant participant) {
Log.d(TAG, participant.getName() + " 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)
}
@Override
public void onParticipantListChanged(List<Participant> participants) {
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
}
@Override
public void onParticipantAudioMuted(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantAudioUnmuted(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantVideoPaused(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantVideoResumed(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantHandRaised(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantHandLowered(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantStartedScreenShare(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantStoppedScreenShare(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantStartedRecording(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onParticipantStoppedRecording(Participant participant) {
Log.d(TAG, participant.getName() + " 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
}
@Override
public void onDominantSpeakerChanged(Participant participant) {
Log.d(TAG, participant.getName() + " 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"
}
}
public class CallActivity extends AppCompatActivity {
private static final String TAG = "CallActivity";
private CallSession callSession;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call);
callSession = CallSession.getInstance();
setupParticipantEventListener();
}
private void setupParticipantEventListener() {
callSession.addParticipantEventListener(this, new ParticipantEventListener() {
@Override
public void onParticipantJoined(Participant participant) {
runOnUiThread(() -> showToast(participant.getName() + " joined"));
}
@Override
public void onParticipantLeft(Participant participant) {
runOnUiThread(() -> showToast(participant.getName() + " left"));
}
@Override
public void onParticipantListChanged(List<Participant> participants) {
runOnUiThread(() -> updateParticipantCount(participants.size()));
}
@Override
public void onParticipantAudioMuted(Participant participant) {
runOnUiThread(() ->
updateParticipantAudioState(participant.getUid(), true));
}
@Override
public void onParticipantAudioUnmuted(Participant participant) {
runOnUiThread(() ->
updateParticipantAudioState(participant.getUid(), false));
}
@Override
public void onParticipantVideoPaused(Participant participant) {
runOnUiThread(() ->
updateParticipantVideoState(participant.getUid(), true));
}
@Override
public void onParticipantVideoResumed(Participant participant) {
runOnUiThread(() ->
updateParticipantVideoState(participant.getUid(), false));
}
@Override
public void onParticipantHandRaised(Participant participant) {
runOnUiThread(() ->
showHandRaisedIndicator(participant.getUid(), true));
}
@Override
public void onParticipantHandLowered(Participant participant) {
runOnUiThread(() ->
showHandRaisedIndicator(participant.getUid(), false));
}
@Override
public void onParticipantStartedScreenShare(Participant participant) {
runOnUiThread(() -> showScreenShareView(participant));
}
@Override
public void onParticipantStoppedScreenShare(Participant participant) {
runOnUiThread(() -> hideScreenShareView());
}
@Override
public void onParticipantStartedRecording(Participant participant) {
runOnUiThread(() -> showRecordingIndicator(true));
}
@Override
public void onParticipantStoppedRecording(Participant participant) {
runOnUiThread(() -> showRecordingIndicator(false));
}
@Override
public void onDominantSpeakerChanged(Participant participant) {
runOnUiThread(() -> highlightDominantSpeaker(participant.getUid()));
}
});
}
// UI helper methods
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
private void updateParticipantCount(int count) { /* ... */ }
private void updateParticipantAudioState(String uid, boolean isMuted) { /* ... */ }
private void updateParticipantVideoState(String uid, boolean isPaused) { /* ... */ }
private void showHandRaisedIndicator(String uid, boolean isRaised) { /* ... */ }
private void showScreenShareView(Participant participant) { /* ... */ }
private void hideScreenShareView() { /* ... */ }
private void showRecordingIndicator(boolean show) { /* ... */ }
private void highlightDominantSpeaker(String uid) { /* ... */ }
}
Callbacks Summary
| Callback | Parameter | Description |
|---|
onParticipantJoined | Participant | A participant joined the call |
onParticipantLeft | Participant | A participant left the call |
onParticipantListChanged | List<Participant> | Participant list was updated |
onParticipantAudioMuted | Participant | A participant muted their audio |
onParticipantAudioUnmuted | Participant | A participant unmuted their audio |
onParticipantVideoPaused | Participant | A participant paused their video |
onParticipantVideoResumed | Participant | A participant resumed their video |
onParticipantHandRaised | Participant | A participant raised their hand |
onParticipantHandLowered | Participant | A participant lowered their hand |
onParticipantStartedScreenShare | Participant | A participant started screen sharing |
onParticipantStoppedScreenShare | Participant | A participant stopped screen sharing |
onParticipantStartedRecording | Participant | A participant started recording |
onParticipantStoppedRecording | Participant | A participant stopped recording |
onDominantSpeakerChanged | Participant | The dominant speaker changed |
Next Steps