Skip to main content

Overview

This section demonstrates how to start a call session in a Flutter application. Previously known as Direct Calling. Before you begin, we strongly recommend you read the calling setup guide.
If you want to implement a complete calling experience with ringing functionality (incoming/outgoing call UI), follow the Ringing guide first. Once the call is accepted, return here to start the call session.

Generate Call Token

A call token is required for secure access to a call session. Each token is unique to a specific session and user combination, ensuring that only authorized users can join the call. You can generate the token just before starting the call, or generate and store it ahead of time based on your use case. Use the generateToken() method to create a call token:
String sessionId = "SESSION_ID"; // Random or from Call object in ringing flow
String userAuthToken = await CometChat.getUserAuthToken(); // Logged in user auth token

CometChatCalls.generateToken(
  sessionId,
  userAuthToken,
  onSuccess: (GenerateToken generateToken) {
    debugPrint("Call token generated: ${generateToken.token}");
    // Use generateToken to start the session
  },
  onError: (CometChatCallsException e) {
    debugPrint("Token generation failed: $e");
  },
);
ParameterDescription
sessionIdThe unique random session ID. In case you are using the ringing flow, the session ID is available in the Call object.
userAuthTokenThe user auth token is the logged-in user auth token which you can get by calling CometChat.getUserAuthToken()

Start Call Session

Use the startSession() method to join a call session. This method requires a call token (generated in the previous step) and a CallSettings object that configures the call UI and behavior.
String generatedToken = ""; // Token from generateToken() onSuccess

CallSettings callSettings = (CallSettingsBuilder()
  ..defaultLayout = true
  ..setAudioOnlyCall = false
  ..listener = this // CometChatCallsEventsListener
).build();

CometChatCalls.startSession(
  generatedToken,
  callSettings,
  onSuccess: (Widget? callingWidget) {
    debugPrint("Call session started");
    // Display the callingWidget in your UI
  },
  onError: (CometChatCallsException e) {
    debugPrint("Start session failed: $e");
  },
);

Call Settings

Configure the call experience using the following CallSettingsBuilder properties:
PropertyDescription
defaultLayoutEnables or disables the default call UI layout with built-in controls. true shows the default layout. false hides the button layout. Default: true
setAudioOnlyCallSets whether the call is audio-only or audio-video. true for audio-only, false for audio-video. Default: false
listenerSets the CometChatCallsEventsListener to receive call events. See Call Listeners.
setModeSets the call UI layout mode. Available: Mode.MODE_DEFAULT, Mode.MODE_SPOTLIGHT, Mode.MODE_SINGLE. Default: Mode.MODE_SPOTLIGHT
setAvatarModeSets how avatars are displayed when video is off. Available: AvatarModes.AVATAR_MODE_CIRCLE, AvatarModes.AVATAR_MODE_SQUARE, AvatarModes.AVATAR_MODE_FULLSCREEN. Default: AVATAR_MODE_CIRCLE
setDefaultAudioModeSets the initial audio output device. Available: AudioModes.AUDIO_MODE_SPEAKER, AudioModes.AUDIO_MODE_EARPIECE, AudioModes.AUDIO_MODE_BLUETOOTH, AudioModes.AUDIO_MODE_HEADPHONES
startWithAudioMutedStarts the call with the microphone muted. Default: false
startWithVideoMutedStarts the call with the camera turned off. Default: false
showEndCallButtonShows or hides the end call button in the default layout. Default: true
showSwitchCameraButtonShows or hides the switch camera button (front/back). Default: true
showMuteAudioButtonShows or hides the mute audio button. Default: true
showPauseVideoButtonShows or hides the pause video button. Default: true
showAudioModeButtonShows or hides the audio mode selection button. Default: true
showSwitchToVideoCallButtonShows or hides the button to upgrade an audio call to video. Default: true
showCallRecordButtonShows or hides the recording button. Default: false
startRecordingOnCallStartAutomatically starts recording when the call begins. Default: false
enableVideoTileClickEnables or disables click interactions on video tiles in Spotlight mode. Default: true
enableVideoTileDragEnables or disables drag functionality for video tiles in Spotlight mode. Default: true
setMainVideoContainerSettingCustomizes the main video container. See Video View Customization.
setIdleTimeoutPeriodSets idle timeout in seconds. Warning appears 60 seconds before auto-termination. Default: 180 seconds. v4.1.0+

Call Listeners

The CometChatCallsEventsListener provides real-time callbacks for call session events, including participant changes, call state updates, and error conditions. Each listener requires a unique listenerId string. This ID is used to:
  • Prevent duplicate registrations — Re-registering with the same ID replaces the existing listener
  • Enable targeted removal — Remove specific listeners without affecting others
String listenerId = "UNIQUE_LISTENER_ID";

class YourClassName extends State<YourScreen> with CometChatCallsEventsListener {
  @override
  void initState() {
    super.initState();
    CometChatCalls.addCallsEventListeners(listenerId, this);
  }

  @override
  void dispose() {
    super.dispose();
    CometChatCalls.removeCallsEventListeners(listenerId);
  }

  @override
  void onCallEnded() {
    debugPrint("Call ended");
  }

  @override
  void onCallEndButtonPressed() {
    debugPrint("End call button pressed");
    // Handle end call - see End Call Session section
  }

  @override
  void onSessionTimeout() {
    debugPrint("Session timed out");
  }

  @override
  void onUserJoined(RTCUser user) {
    debugPrint("User joined: ${user.name}");
  }

  @override
  void onUserLeft(RTCUser user) {
    debugPrint("User left: ${user.name}");
  }

  @override
  void onUserListChanged(List<RTCUser> users) {
    debugPrint("User list updated: ${users.length} participants");
  }

  @override
  void onAudioModeChanged(List<AudioMode> devices) {
    debugPrint("Audio modes changed");
  }

  @override
  void onCallSwitchedToVideo(CallSwitchRequestInfo info) {
    debugPrint("Call switched to video");
  }

  @override
  void onUserMuted(RTCMutedUser muteObj) {
    debugPrint("User muted");
  }

  @override
  void onRecordingToggled(RTCRecordingInfo info) {
    debugPrint("Recording toggled");
  }

  @override
  void onError(CometChatCallsException e) {
    debugPrint("Call error: $e");
  }
}

Events

EventDescription
onCallEnded()Invoked when the call session terminates for a 1:1 call. Both participants receive this callback. Only fires for calls with exactly 2 participants.
onSessionTimeout()Invoked when the call is auto-terminated due to inactivity (default: 180 seconds). Warning appears 60 seconds before. v4.1.0+
onCallEndButtonPressed()Invoked when the local user taps the end call button. For ringing flow, call CometChat.endCall(). For standalone, call CometChatCalls.endSession().
onUserJoined(RTCUser user)Invoked when a remote participant joins. The user contains UID, name, and avatar.
onUserLeft(RTCUser user)Invoked when a remote participant leaves the call session.
onUserListChanged(List<RTCUser> users)Invoked whenever the participant list changes (join or leave events).
onAudioModeChanged(List<AudioMode> devices)Invoked when available audio devices change (e.g., Bluetooth connected).
onCallSwitchedToVideo(CallSwitchRequestInfo info)Invoked when an audio call is upgraded to a video call.
onUserMuted(RTCMutedUser muteObj)Invoked when a participant’s mute state changes.
onRecordingToggled(RTCRecordingInfo info)Invoked when call recording starts or stops.
onError(CometChatCallsException e)Invoked when an error occurs during the call session.

End Call Session

Ending a call session properly is essential to release media resources (camera, microphone, network connections) and update call state across all participants. The termination process differs based on whether you’re using the Ringing flow or Session Only flow.

Ringing Flow

When using the Ringing flow, you must coordinate between the CometChat Chat SDK and the Calls SDK to properly terminate the call and notify all participants.
The Ringing flow requires calling methods from both the Chat SDK (CometChat.endCall()) and the Calls SDK (CometChatCalls.endSession()) to ensure proper call termination and participant notification.
User who initiates the end call: When the user presses the end call button in the UI, the onCallEndButtonPressed() callback is triggered. You must call CometChat.endCall() inside this callback to properly terminate the call and notify other participants. On success, call CometChat.clearActiveCall() and CometChatCalls.endSession() to release resources.
@override
void onCallEndButtonPressed() {
  CometChat.endCall(
    sessionId,
    onSuccess: (Call call) {
      debugPrint("Call ended successfully");
      CometChat.clearActiveCall();
      CometChatCalls.endSession(
        onSuccess: (success) {
          debugPrint("Session ended");
          // Close the calling screen
        },
        onError: (e) {
          debugPrint("End session failed: $e");
        },
      );
    },
    onError: (CometChatException e) {
      debugPrint("End call failed: $e");
    },
  );
}
Remote participant (receives the onCallEnded() callback): Call CometChat.clearActiveCall() to clear the local call state, then call CometChatCalls.endSession() to release media resources.
@override
void onCallEnded() {
  CometChat.clearActiveCall();
  CometChatCalls.endSession(
    onSuccess: (success) {
      debugPrint("Session ended");
      // Close the calling screen
    },
    onError: (e) {
      debugPrint("End session failed: $e");
    },
  );
}

Session Only Flow

When using the Session Only flow (direct call without ringing), you only need to call the Calls SDK method to end the session. There’s no need to notify the Chat SDK since no call signaling was involved. Call CometChatCalls.endSession() in the onCallEndButtonPressed() callback to release all media resources and disconnect from the call session.
@override
void onCallEndButtonPressed() {
  CometChatCalls.endSession(
    onSuccess: (success) {
      debugPrint("Session ended");
      // Close the calling screen
    },
    onError: (e) {
      debugPrint("End session failed: $e");
    },
  );
}

Methods

These methods are available for performing custom actions during an active call session. Use them to build custom UI controls or implement specific behaviors based on your use case.
These methods can only be called when a call session is active.

Switch Camera

Toggles between the front and rear camera during a video call. Useful for allowing users to switch their camera view without leaving the call.
CometChatCalls.switchCamera(
  onSuccess: (success) {
    debugPrint("Camera switched");
  },
  onError: (e) {
    debugPrint("Switch camera failed: $e");
  },
);

Mute Audio

Controls the local audio stream transmission. When muted, other participants cannot hear the local user.
  • true — Mutes the microphone, stops transmitting audio
  • false — Unmutes the microphone, resumes audio transmission
CometChatCalls.muteAudio(
  true,
  onSuccess: (success) {
    debugPrint("Audio muted");
  },
  onError: (e) {
    debugPrint("Mute audio failed: $e");
  },
);

Pause Video

Controls the local video stream transmission. When paused, other participants see a frozen frame or avatar instead of live video.
  • true — Pauses the camera, stops transmitting video
  • false — Resumes the camera, continues video transmission
CometChatCalls.pauseVideo(
  true,
  onSuccess: (success) {
    debugPrint("Video paused");
  },
  onError: (e) {
    debugPrint("Pause video failed: $e");
  },
);

Set Audio Mode

Routes the audio output to a specific device. Use this to let users choose between speaker, earpiece, or connected audio devices. Available modes:
  • AudioModes.AUDIO_MODE_SPEAKER — Device speaker (loudspeaker)
  • AudioModes.AUDIO_MODE_EARPIECE — Phone earpiece
  • AudioModes.AUDIO_MODE_BLUETOOTH — Connected Bluetooth device
  • AudioModes.AUDIO_MODE_HEADPHONES — Wired headphones
CometChatCalls.setAudioMode(
  AudioModes.AUDIO_MODE_SPEAKER,
  onSuccess: (success) {
    debugPrint("Audio mode set");
  },
  onError: (e) {
    debugPrint("Set audio mode failed: $e");
  },
);

Enter PIP Mode

Enters Picture-in-Picture mode, rendering the call view in a small floating window. This allows users to multitask while staying on the call.
CometChatCalls.enterPIPMode(
  onSuccess: (success) {
    debugPrint("Entered PIP mode");
  },
  onError: (e) {
    debugPrint("Enter PIP failed: $e");
  },
);

Exit PIP Mode

Exits Picture-in-Picture mode and returns the call view to its original full-screen or embedded layout.
CometChatCalls.exitPIPMode(
  onSuccess: (success) {
    debugPrint("Exited PIP mode");
  },
  onError: (e) {
    debugPrint("Exit PIP failed: $e");
  },
);

Switch To Video Call

Upgrades an ongoing audio call to a video call. This enables the camera and starts transmitting video to other participants. The remote participant receives the onCallSwitchedToVideo() callback.
CometChatCalls.switchToVideoCall(
  onSuccess: (success) {
    debugPrint("Switched to video call");
  },
  onError: (e) {
    debugPrint("Switch to video failed: $e");
  },
);

Start Recording

Starts recording the call session. The recording is saved to the CometChat server and can be accessed later. All participants receive the onRecordingToggled() callback when recording starts.
CometChatCalls.startRecording(
  onSuccess: (success) {
    debugPrint("Recording started");
  },
  onError: (e) {
    debugPrint("Start recording failed: $e");
  },
);

Stop Recording

Stops an ongoing call recording. All participants receive the onRecordingToggled() callback when recording stops.
CometChatCalls.stopRecording(
  onSuccess: (success) {
    debugPrint("Recording stopped");
  },
  onError: (e) {
    debugPrint("Stop recording failed: $e");
  },
);

End Call

Terminates the current call session and releases all media resources (camera, microphone, network connections). After calling this method, the call view should be closed.
CometChatCalls.endSession(
  onSuccess: (success) {
    debugPrint("Session ended");
    // Close the calling screen
  },
  onError: (e) {
    debugPrint("End session failed: $e");
  },
);