Skip to main content

Overview

This section explains how to implement a complete calling workflow with ringing functionality, including incoming/outgoing call UI, call acceptance, rejection, and cancellation. Previously known as Default Calling.
After the call is accepted, you need to start the call session. See the Call Session guide for details on starting and managing the actual call.
Call Flow:
  1. Caller initiates a call using initiateCall()
  2. Receiver gets notified via onIncomingCallReceived() callback
  3. Receiver can either:
    • Accept the call using acceptCall()
    • Reject the call using rejectCall() with status CALL_STATUS_REJECTED
  4. Caller can cancel the call using rejectCall() with status CALL_STATUS_CANCELLED
  5. Once accepted, both participants call startSession() to join the call

Initiate Call

The initiateCall() method sends a call request to a user or a group. On success, the receiver gets an onIncomingCallReceived() callback.
// User call
String receiverID = "UID";
String receiverType = CometChatConstants.RECEIVER_TYPE_USER;
String callType = CometChatConstants.CALL_TYPE_VIDEO;

Call call = Call(
  receiverUid: receiverID,
  receiverType: receiverType,
  type: callType,
);

CometChat.initiateCall(
  call,
  onSuccess: (Call call) {
    debugPrint("Call initiated: ${call.sessionId}");
    // Show outgoing call UI
    // Store call.sessionId for later use
  },
  onError: (CometChatException e) {
    debugPrint("Call initiation failed: $e");
  },
);
// Group call
String receiverID = "GUID";
String receiverType = CometChatConstants.RECEIVER_TYPE_GROUP;
String callType = CometChatConstants.CALL_TYPE_VIDEO;

Call call = Call(
  receiverUid: receiverID,
  receiverType: receiverType,
  type: callType,
);

CometChat.initiateCall(
  call,
  onSuccess: (Call call) {
    debugPrint("Call initiated: ${call.sessionId}");
    // Show outgoing call UI
  },
  onError: (CometChatException e) {
    debugPrint("Call initiation failed: $e");
  },
);
ParameterDescription
receiverIDThe UID or GUID of the recipient
receiverTypeThe type of the receiver: CometChatConstants.RECEIVER_TYPE_USER or CometChatConstants.RECEIVER_TYPE_GROUP
callTypeThe type of the call: CometChatConstants.CALL_TYPE_AUDIO or CometChatConstants.CALL_TYPE_VIDEO
On success, a Call object is returned containing the call details including a unique sessionId required for starting the call session.

Call Listeners

Register the CallListener to receive real-time call events. Each listener requires a unique listenerId string to prevent duplicate registrations and enable targeted removal.
String listenerId = "UNIQUE_LISTENER_ID";

class YourClassName extends State<YourScreen> with CallListener {
  @override
  void initState() {
    super.initState();
    CometChat.addCallListener(listenerId, this);
  }

  @override
  void dispose() {
    super.dispose();
    CometChat.removeCallListener(listenerId);
  }

  @override
  void onIncomingCallReceived(Call call) {
    debugPrint("Incoming call from: ${call.sender?.name}");
    // Show incoming call UI
  }

  @override
  void onOutgoingCallAccepted(Call call) {
    debugPrint("Outgoing call accepted");
    // Receiver accepted, start the call session
  }

  @override
  void onOutgoingCallRejected(Call call) {
    debugPrint("Outgoing call rejected");
    // Receiver rejected, dismiss outgoing call UI
  }

  @override
  void onIncomingCallCancelled(Call call) {
    debugPrint("Incoming call cancelled");
    // Caller cancelled, dismiss incoming call UI
  }

  @override
  void onCallEndedMessageReceived(Call call) {
    debugPrint("Call ended message received");
    // Call ended by remote participant
  }
}

Events

EventDescription
onIncomingCallReceived(Call call)Invoked when an incoming call is received. The call contains caller details, session ID, and call type. Display incoming call UI here.
onOutgoingCallAccepted(Call call)Invoked on the caller’s device when the receiver accepts. Generate call token and start the session here.
onOutgoingCallRejected(Call call)Invoked on the caller’s device when the receiver rejects the call. Dismiss outgoing call UI here.
onIncomingCallCancelled(Call call)Invoked on the receiver’s device when the caller cancels before answering. Dismiss incoming call UI here.
onCallEndedMessageReceived(Call call)Invoked when a call ends. The call contains final status and duration. Update call history here.

Accept Call

When an incoming call is received via onIncomingCallReceived(), use acceptCall() to accept it. On success, start the call session.
String sessionId = call.sessionId!; // From onIncomingCallReceived

CometChat.acceptCall(
  sessionId,
  onSuccess: (Call call) {
    debugPrint("Call accepted");
    // Call accepted, now start the call session
    // Generate token and call startSession()
  },
  onError: (CometChatException e) {
    debugPrint("Accept call failed: $e");
  },
);

Reject Call

Use rejectCall() to reject an incoming call. Set the status to CALL_STATUS_REJECTED.
String sessionId = call.sessionId!;
String status = CometChatConstants.CALL_STATUS_REJECTED;

CometChat.rejectCall(
  sessionId,
  status,
  onSuccess: (Call call) {
    debugPrint("Call rejected");
    // Dismiss incoming call UI
  },
  onError: (CometChatException e) {
    debugPrint("Reject call failed: $e");
  },
);

Cancel Call

The caller can cancel an outgoing call before it’s answered using rejectCall() with status CALL_STATUS_CANCELLED.
String sessionId = call.sessionId!;
String status = CometChatConstants.CALL_STATUS_CANCELLED;

CometChat.rejectCall(
  sessionId,
  status,
  onSuccess: (Call call) {
    debugPrint("Call cancelled");
    // Dismiss outgoing call UI
  },
  onError: (CometChatException e) {
    debugPrint("Cancel call failed: $e");
  },
);

Start Call Session

Once the call is accepted, both participants need to start the call session. Caller flow: In the onOutgoingCallAccepted() callback, generate a token and start the session. Receiver flow: In the acceptCall() success callback, generate a token and start the session.
String sessionId = call.sessionId!;
String userAuthToken = await CometChat.getUserAuthToken();

// Step 1: Generate call token
CometChatCalls.generateToken(
  sessionId,
  userAuthToken,
  onSuccess: (GenerateToken generateToken) {
    // Step 2: Configure call settings with listeners
    CallSettings callSettings = (CallSettingsBuilder()
      ..defaultLayout = true
      ..setAudioOnlyCall = false
      ..listener = CallEventsHandler(sessionId) // Your listener implementation
    ).build();

    // Step 3: Start the session
    CometChatCalls.startSession(
      generateToken.token!,
      callSettings,
      onSuccess: (Widget? callingWidget) {
        debugPrint("Call session started");
        // Display the callingWidget in your UI
      },
      onError: (CometChatCallsException e) {
        debugPrint("Start session failed: $e");
      },
    );
  },
  onError: (CometChatCallsException e) {
    debugPrint("Token generation failed: $e");
  },
);
For more details on call settings and customization, see the Call Session guide.

End Call

To end an active call in the ringing flow, the process differs based on who ends the call. User who ends the call: When the user presses the end call button, the onCallEndButtonPressed() callback is triggered. Inside this callback, call CometChat.endCall() to 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 onCallEnded() callback):
@override
void onCallEnded() {
  CometChat.clearActiveCall();
  CometChatCalls.endSession(
    onSuccess: (success) {
      debugPrint("Session ended");
      // Close the calling screen
    },
    onError: (e) {
      debugPrint("End session failed: $e");
    },
  );
}
For more details, see the End Call Session guide.

Busy Call Handling

If the receiver is already on another call, you can reject the incoming call with CALL_STATUS_BUSY status.
String sessionId = call.sessionId!;
String status = CometChatConstants.CALL_STATUS_BUSY;

CometChat.rejectCall(
  sessionId,
  status,
  onSuccess: (Call call) {
    debugPrint("Busy status sent");
  },
  onError: (CometChatException e) {
    debugPrint("Busy rejection failed: $e");
  },
);