Monitor the call session lifecycle with SessionStatusListeners. This listener provides callbacks for session join/leave events, connection status changes, and session timeouts.
Prerequisites
Register Listener
Register a SessionStatusListeners to receive session status callbacks:
final callSession = CallSession . getInstance ();
callSession ? . addSessionStatusListener ( SessionStatusListeners (
onSessionJoined : () {
debugPrint ( "Successfully joined the session" );
},
onSessionLeft : () {
debugPrint ( "Left the session" );
},
onSessionTimedOut : () {
debugPrint ( "Session timed out" );
},
onConnectionLost : () {
debugPrint ( "Connection lost" );
},
onConnectionRestored : () {
debugPrint ( "Connection restored" );
},
onConnectionClosed : () {
debugPrint ( "Connection closed" );
},
));
Flutter listeners are not lifecycle-aware. You must manually remove listeners in your widget’s dispose() method to prevent memory leaks.
Callbacks
onSessionJoined
Triggered when you successfully join a call session.
onSessionJoined : () {
debugPrint ( "Successfully joined the session" );
// Update UI to show call screen
setState (() {
_isInCall = true ;
});
}
Use Cases:
Update UI to display the call interface
Start foreground service for ongoing call notification
Initialize call-related features
onSessionLeft
Triggered when you leave the call session (either by calling leaveSession() or being removed).
onSessionLeft : () {
debugPrint ( "Left the session" );
// Clean up resources
// Navigate back to previous screen
Navigator . of (context). pop ();
}
Use Cases:
Clean up call-related resources
Stop foreground service
Navigate away from call screen
onSessionTimedOut
Triggered when the session times out due to inactivity (e.g., being alone in the call for too long).
onSessionTimedOut : () {
debugPrint ( "Session timed out due to inactivity" );
// Show timeout message to user
ScaffoldMessenger . of (context). showSnackBar (
const SnackBar (content : Text ( "Call ended due to inactivity" )),
);
Navigator . of (context). pop ();
}
Configure the timeout period using setIdleTimeoutPeriod() in SessionSettings . Default is 300 seconds (5 minutes).
Use Cases:
Display timeout notification to user
Clean up resources and navigate away
Log analytics event
onConnectionLost
Triggered when the connection to the call server is lost (e.g., network issues).
onConnectionLost : () {
debugPrint ( "Connection lost - attempting to reconnect" );
// Show reconnecting indicator
setState (() {
_isReconnecting = true ;
});
}
Use Cases:
Display “Reconnecting…” indicator
Disable call controls temporarily
Log connection issue for debugging
onConnectionRestored
Triggered when the connection is restored after being lost.
onConnectionRestored : () {
debugPrint ( "Connection restored" );
// Hide reconnecting indicator
setState (() {
_isReconnecting = false ;
});
}
Use Cases:
Hide reconnecting indicator
Re-enable call controls
Show success notification
onConnectionClosed
Triggered when the connection is permanently closed (cannot be restored).
onConnectionClosed : () {
debugPrint ( "Connection closed permanently" );
// Show error message
ScaffoldMessenger . of (context). showSnackBar (
const SnackBar (content : Text ( "Call connection lost" )),
);
// Clean up and exit
Navigator . of (context). pop ();
}
Use Cases:
Display error message to user
Clean up resources
Navigate away from call screen
Complete Example
Here’s a complete example handling all session status events:
import 'package:cometchat_calls_sdk/cometchat_calls_sdk.dart' ;
import 'package:flutter/material.dart' ;
class CallScreen extends StatefulWidget {
const CallScreen ({ super .key});
@override
State < CallScreen > createState () => _CallScreenState ();
}
class _CallScreenState extends State < CallScreen > {
CallSession ? _callSession;
SessionStatusListeners ? _sessionStatusListener;
bool _isReconnecting = false ;
@override
void initState () {
super . initState ();
_callSession = CallSession . getInstance ();
_setupSessionStatusListener ();
}
void _setupSessionStatusListener () {
_sessionStatusListener = SessionStatusListeners (
onSessionJoined : () {
debugPrint ( "Session joined" );
// Start ongoing call service (Android only)
CometChatOngoingCallService . launch ();
},
onSessionLeft : () {
debugPrint ( "Session left" );
CometChatOngoingCallService . abort ();
if (mounted) Navigator . of (context). pop ();
},
onSessionTimedOut : () {
debugPrint ( "Session timed out" );
if (mounted) {
ScaffoldMessenger . of (context). showSnackBar (
const SnackBar (
content : Text ( "Call ended due to inactivity" ),
),
);
CometChatOngoingCallService . abort ();
Navigator . of (context). pop ();
}
},
onConnectionLost : () {
debugPrint ( "Connection lost" );
if (mounted) {
setState (() {
_isReconnecting = true ;
});
}
},
onConnectionRestored : () {
debugPrint ( "Connection restored" );
if (mounted) {
setState (() {
_isReconnecting = false ;
});
}
},
onConnectionClosed : () {
debugPrint ( "Connection closed" );
if (mounted) {
ScaffoldMessenger . of (context). showSnackBar (
const SnackBar (
content : Text ( "Connection lost. Please try again." ),
),
);
CometChatOngoingCallService . abort ();
Navigator . of (context). pop ();
}
},
);
_callSession ? . addSessionStatusListener (_sessionStatusListener ! );
}
@override
void dispose () {
// Must manually remove listener to prevent memory leaks
if (_sessionStatusListener != null ) {
_callSession ? . removeSessionStatusListener (_sessionStatusListener ! );
}
super . dispose ();
}
@override
Widget build ( BuildContext context) {
return Scaffold (
body : Stack (
children : [
// Call UI content here
if (_isReconnecting)
const Center (
child : Card (
child : Padding (
padding : EdgeInsets . all ( 16 ),
child : Row (
mainAxisSize : MainAxisSize .min,
children : [
CircularProgressIndicator (),
SizedBox (width : 16 ),
Text ( "Reconnecting..." ),
],
),
),
),
),
],
),
);
}
}
Remove Listener
Remove the listener in your widget’s dispose() method to prevent memory leaks:
@override
void dispose () {
if (_sessionStatusListener != null ) {
_callSession ? . removeSessionStatusListener (_sessionStatusListener ! );
}
super . dispose ();
}
Callbacks Summary
Callback Description onSessionJoinedSuccessfully joined the call session onSessionLeftLeft the call session onSessionTimedOutSession ended due to inactivity timeout onConnectionLostConnection to server lost (reconnecting) onConnectionRestoredConnection restored after being lost onConnectionClosedConnection permanently closed
Next Steps
Participant Event Listener Handle participant join/leave and state changes
Media Events Listener Handle recording, screen share, and media state changes