Handle call session events to build responsive UIs. The SDK provides five event listener interfaces to monitor session status, participant activities, media changes, button clicks, and layout changes. Unlike Android, Flutter listeners are not lifecycle-aware and must be manually removed in dispose() to prevent memory leaks.
Get CallSession Instance
The CallSession is a singleton that manages the active call. All event listener registrations and session control methods are accessed through this instance.
CallSession ? callSession = CallSession . getInstance ();
Flutter listeners are not lifecycle-aware. You must manually remove all listeners in your widget’s dispose() method to prevent memory leaks. Failing to do so may cause callbacks to fire on disposed widgets.
Session Events
Monitor the call session lifecycle including join/leave events and connection status.
final sessionStatusListener = SessionStatusListener (
onSessionJoined : () {
// Successfully connected to the session
},
onSessionLeft : () {
// Navigate away
},
onSessionTimedOut : () {
// Session ended due to inactivity
},
onConnectionLost : () {
// Network interrupted, attempting reconnection
},
onConnectionRestored : () {
// Connection restored after being lost
},
onConnectionClosed : () {
// Connection permanently closed
},
);
CallSession . getInstance () ? . addSessionStatusListener (sessionStatusListener);
Event Description onSessionJoinedSuccessfully connected and joined the session onSessionLeftLeft the session via leaveSession() or was removed onSessionTimedOutSession ended due to inactivity timeout onConnectionLostNetwork interrupted, SDK attempting reconnection onConnectionRestoredConnection restored after being lost onConnectionClosedConnection permanently closed, cannot reconnect
Remove the listener when no longer needed:
@override
void dispose () {
CallSession . getInstance () ? . removeSessionStatusListener (sessionStatusListener);
super . dispose ();
}
Participant Events
Monitor participant activities including join/leave, audio/video state, hand raise, screen sharing, and recording.
final participantEventListener = ParticipantEventListener (
onParticipantJoined : ( Participant participant) {
// A participant joined the call
},
onParticipantLeft : ( Participant participant) {
// A participant left the call
},
onParticipantListChanged : ( List < Participant > participants) {
// Participant list updated
},
onParticipantAudioMuted : ( Participant participant) {},
onParticipantAudioUnmuted : ( Participant participant) {},
onParticipantVideoPaused : ( Participant participant) {},
onParticipantVideoResumed : ( Participant participant) {},
onParticipantHandRaised : ( Participant participant) {},
onParticipantHandLowered : ( Participant participant) {},
onParticipantStartedScreenShare : ( Participant participant) {},
onParticipantStoppedScreenShare : ( Participant participant) {},
onParticipantStartedRecording : ( Participant participant) {},
onParticipantStoppedRecording : ( Participant participant) {},
onDominantSpeakerChanged : ( Participant participant) {},
);
CallSession . getInstance () ? . addParticipantEventListener (participantEventListener);
Event Parameter Description onParticipantJoinedParticipantA participant connected to the call onParticipantLeftParticipantA participant disconnected from the call onParticipantListChangedList<Participant>Participant list updated onParticipantAudioMutedParticipantA participant muted their microphone onParticipantAudioUnmutedParticipantA participant unmuted their microphone onParticipantVideoPausedParticipantA participant turned off their camera onParticipantVideoResumedParticipantA participant turned on their camera 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 active speaker changed
Remove the listener when no longer needed:
@override
void dispose () {
CallSession . getInstance () ? . removeParticipantEventListener (participantEventListener);
super . dispose ();
}
Monitor your local media state changes including audio/video status, recording, and device changes.
final mediaEventsListener = MediaEventsListener (
onAudioMuted : () {
// Your microphone was muted
},
onAudioUnMuted : () {
// Your microphone was unmuted
},
onVideoPaused : () {
// Your camera was turned off
},
onVideoResumed : () {
// Your camera was turned on
},
onRecordingStarted : () {
// Call recording started
},
onRecordingStopped : () {
// Call recording stopped
},
onScreenShareStarted : () {
// You started screen sharing
},
onScreenShareStopped : () {
// You stopped screen sharing
},
onAudioModeChanged : ( AudioMode audioMode) {
// Audio output device changed
},
onCameraFacingChanged : ( CameraFacing facing) {
// Camera switched between front and rear
},
);
CallSession . getInstance () ? . addMediaEventsListener (mediaEventsListener);
Event Parameter Description onAudioMuted- Your microphone was muted onAudioUnMuted- Your microphone was unmuted onVideoPaused- Your camera was turned off onVideoResumed- Your camera was turned on onRecordingStarted- Call recording started onRecordingStopped- Call recording stopped onScreenShareStarted- You started screen sharing onScreenShareStopped- You stopped screen sharing onAudioModeChangedAudioModeAudio output device changed onCameraFacingChangedCameraFacingCamera switched between front and rear
Value Description AudioMode.speakerAudio routed through device loudspeaker AudioMode.earpieceAudio routed through phone earpiece AudioMode.bluetoothAudio routed through connected Bluetooth device
Value Description CameraFacing.frontFront-facing (selfie) camera is active CameraFacing.rearRear-facing (main) camera is active
Remove the listener when no longer needed:
@override
void dispose () {
CallSession . getInstance () ? . removeMediaEventsListener (mediaEventsListener);
super . dispose ();
}
Intercept UI button clicks from the default call interface to add custom behavior or analytics.
final buttonClickListener = ButtonClickListener (
onLeaveSessionButtonClicked : () {
// Leave button tapped
},
onToggleAudioButtonClicked : () {
// Mute/unmute button tapped
},
onToggleVideoButtonClicked : () {
// Video on/off button tapped
},
onSwitchCameraButtonClicked : () {},
onRaiseHandButtonClicked : () {},
onShareInviteButtonClicked : () {},
onChangeLayoutButtonClicked : () {},
onParticipantListButtonClicked : () {},
onChatButtonClicked : () {},
onRecordingToggleButtonClicked : () {},
);
CallSession . getInstance () ? . addButtonClickListener (buttonClickListener);
Event Description onLeaveSessionButtonClickedLeave/end call button was tapped onToggleAudioButtonClickedMute/unmute button was tapped onToggleVideoButtonClickedVideo on/off button was tapped onSwitchCameraButtonClickedCamera switch button was tapped onRaiseHandButtonClickedRaise hand button was tapped onShareInviteButtonClickedShare/invite button was tapped onChangeLayoutButtonClickedLayout change button was tapped onParticipantListButtonClickedParticipant list button was tapped onChatButtonClickedIn-call chat button was tapped onRecordingToggleButtonClickedRecording toggle button was tapped
Button click events fire before the SDK’s default action executes. Use these to add custom logic alongside default behavior.
Remove the listener when no longer needed:
@override
void dispose () {
CallSession . getInstance () ? . removeButtonClickListener (buttonClickListener);
super . dispose ();
}
Layout Events
Monitor layout changes including layout type switches and Picture-in-Picture mode transitions.
final layoutListener = LayoutListener (
onCallLayoutChanged : ( LayoutType layoutType) {
// Layout changed (tile, spotlight)
},
onParticipantListVisible : () {
// Participant list panel opened
},
onParticipantListHidden : () {
// Participant list panel closed
},
onPictureInPictureLayoutEnabled : () {
// Entered PiP mode
},
onPictureInPictureLayoutDisabled : () {
// Exited PiP mode
},
);
CallSession . getInstance () ? . addLayoutListener (layoutListener);
Event Parameter Description onCallLayoutChangedLayoutTypeCall layout changed onParticipantListVisible- Participant list panel was opened onParticipantListHidden- Participant list panel was closed onPictureInPictureLayoutEnabled- Call entered Picture-in-Picture mode onPictureInPictureLayoutDisabled- Call exited Picture-in-Picture mode
Value Description Best For LayoutType.tileGrid layout with equally-sized tiles Group discussions, team meetings LayoutType.spotlightLarge view for active speaker, small tiles for others Presentations, one-on-one calls
Remove the listener when no longer needed:
@override
void dispose () {
CallSession . getInstance () ? . removeLayoutListener (layoutListener);
super . dispose ();
}