| name | cometchat-flutter-calls |
| description | Use when implementing voice calls, video calls, or call UI with CometChat Flutter UIKit v6. Covers CometChatCallButtons, CometChatIncomingCall, CometChatOutgoingCall, CometChatOngoingCall, CometChatCallLogs, CometChatUIKitCalls, CallingConfiguration, CallButtonsBloc, IncomingCallBloc, OutgoingCallBloc, OngoingCallBloc, CallLogsBloc, CallEventService, CallOperationsServiceLocator, call_operations, call_settings, SessionSettingsBuilder, CallAppSettings, initiateCall, acceptCall, rejectCall, endSession, startSession, generateToken, CallNavigationContext, CometChatDisplayIncomingCallOverlay, CallScreenOverlay, native_call_kit, call permissions, audio call, video call, group call, call logs, call history, incoming call screen, outgoing call screen, ongoing call screen, call bubble, or "add calling to my app". Also use when seeing errors like "CallManager not found", "startSession null", "call token null", "session already started", or call-related crashes.
|
| license | MIT |
| compatibility | cometchat_chat_uikit ^6.0.0 |
| allowed-tools | executeBash, readFile, readCode, fileSearch, listDirectory, grepSearch |
| metadata | {"author":"CometChat","version":"1.0.0","tags":"cometchat flutter calls voice video calling incoming outgoing ongoing call-logs"} |
CometChat Flutter UIKit ā Calls
Voice and video calling for 1:1 and group conversations. Call functionality is built into cometchat_chat_uikit ā no separate package needed.
Import
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
import 'package:cometchat_chat_uikit/cometchat_calls_uikit.dart';
The first import gives you chat components. The second gives you call-specific types.
Rule: CALLS_INIT_AFTER_CHAT_INIT
CometChatUIKitCalls.init() MUST be called after CometChatUIKit.init() completes. The calls SDK needs the chat SDK's auth context.
// ā
CORRECT ā calls init after chat init
CometChatUIKit.init(
uiKitSettings: settings,
onSuccess: (_) {
CometChatUIKitCalls.init(appId, region,
onSuccess: (_) => debugPrint('Calls SDK ready'),
onError: (e) => debugPrint('Calls init failed: ${e.message}'),
);
},
);
// ā WRONG ā parallel init causes auth token null
CometChatUIKit.init(uiKitSettings: settings);
CometChatUIKitCalls.init(appId, region); // Race condition
Rule: SINGLE_CALLS_INIT
CometChatUIKitCalls.init() must be called exactly once per app lifecycle. Calling it again after logout + re-login can cause "session already started" errors.
Rule: CALLS_REINIT_AFTER_LOGOUT
After CometChatUIKit.logout(), the calls SDK session is invalidated. On the next login, CometChatUIKitCalls.init() must be called again.
Architecture
call_ui/src/
āāā call_buttons/ # Voice/video call buttons (CallButtonsBloc)
āāā incoming_call/ # Incoming call screen (IncomingCallBloc)
āāā outgoing_call/ # Outgoing call screen (OutgoingCallBloc)
āāā ongoing_call/ # Active call screen ā WebRTC (OngoingCallBloc)
āāā call_logs/ # Call history list (CallLogsBloc + Clean Arch)
āāā call_operations/ # Shared clean architecture (DI, use cases, repos)
āāā call_bubble/ # Call message bubble in chat
āāā call_settings/ # CometChatUIKitCalls, CallNavigationContext
āāā native_call_kit/ # iOS CallKit / Android ConnectionService
āāā utils/ # CallUtils, CallStateService, CallPermissions
āāā call_event_service.dart # Centralized call event handling
āāā calling_configuration.dart # Top-level config object
Components
CometChatCallButtons
Voice and video call buttons. Typically placed in CometChatMessageHeader's trailing view or standalone.
CometChatCallButtons(
user: user, // For 1:1 calls
group: group, // For group calls (meetings)
hideVoiceCallButton: false,
hideVideoCallButton: false,
voiceCallIcon: Icon(Icons.call),
videoCallIcon: Icon(Icons.videocam),
callButtonsStyle: CometChatCallButtonsStyle(
voiceCallIconColor: colorPalette.iconPrimary,
videoCallIconColor: colorPalette.iconPrimary,
),
outgoingCallConfiguration: CometChatOutgoingCallConfiguration(
outgoingCallStyle: CometChatOutgoingCallStyle(...),
),
)
Call buttons are built into CometChatMessageHeader by default:
CometChatMessageHeader(
user: user,
group: group,
hideVoiceCallButton: false,
hideVideoCallButton: false,
)
CometChatIncomingCall
Displays when the logged-in user receives a call. Supports accept/decline with custom views.
CometChatIncomingCall(
call: call, // Required ā the active Call object
user: callerUser, // Caller info for display
onAccept: (ctx, call) { },
onDecline: (ctx, call) { },
disableSoundForCalls: false,
customSoundForCalls: 'assets/ringtone.mp3',
incomingCallStyle: CometChatIncomingCallStyle(
backgroundColor: colorPalette.background3,
acceptButtonColor: colorPalette.success,
declineButtonColor: colorPalette.error,
),
// Custom view slots
titleView: (ctx, call) => Text('Custom Title'),
subTitleView: (ctx, call) => Text('Custom Subtitle'),
leadingView: (ctx, call) => Icon(Icons.call),
trailingView: (ctx, call) => CometChatAvatar(image: user.avatar),
)
CometChatOutgoingCall
Displays when the logged-in user initiates a call.
CometChatOutgoingCall(
call: call,
user: receiverUser,
outgoingCallStyle: CometChatOutgoingCallStyle(
backgroundColor: colorPalette.background1,
),
)
CometChatOngoingCall
The active call screen with WebRTC video/audio. Rendered after a call is accepted.
CometChatOngoingCall(
callSettingsBuilder: sessionSettingsBuilder,
sessionId: call.sessionId,
callWorkFlow: CallWorkFlow.directCalling,
)
CometChatCallLogs
Scrollable list of call history. Clean Architecture + BLoC with CallLogsServiceLocator.
CometChatCallLogs(
onItemClick: (callLog) { /* Navigate or initiate call */ },
callLogsStyle: CallLogsStyle(backgroundColor: colorPalette.background1),
)
CometChatCallBubble
Message bubble for call events in the message list. Automatically rendered for call-type messages.
CallingConfiguration
Top-level configuration object bundling all call component configs:
CallingConfiguration(
outgoingCallConfiguration: CometChatOutgoingCallConfiguration(...),
incomingCallConfiguration: CometChatIncomingCallConfiguration(...),
callButtonsConfiguration: CallButtonsConfiguration(...),
groupSessionSettingsBuilder: sessionSettingsBuilder,
)
CometChatUIKitCalls API
| Method | Purpose |
|---|
CometChatUIKitCalls.init(appId, region) | Initialize calls SDK |
CometChatUIKitCalls.initiateCall(call) | Start a call |
CometChatUIKitCalls.acceptCall(sessionId) | Accept incoming call |
CometChatUIKitCalls.rejectCall(sessionId, status) | Reject/cancel call |
CometChatUIKitCalls.generateToken(sessionId) | Generate call token |
CometChatUIKitCalls.startSession(sessionId, settings) | Start WebRTC session |
CometChatUIKitCalls.endSession() | End active call session |
Call Flow ā 1:1 Direct Call
Caller Receiver
|-- CometChatCallButtons tap ------->|
|-- initiateCall(Call) ------------->|
|-- CometChatOutgoingCall shown ---->|
| |-- CometChatIncomingCall shown
| |-- acceptCall(sessionId)
|<-- onOutgoingCallAccepted ---------|
|-- generateToken(sessionId) ------->|
|-- startSession(token, settings) -->|
|-- CometChatOngoingCall shown ----->|-- CometChatOngoingCall shown
|-- endSession() ------------------>|-- endSession()
Golden Path ā Messages Screen with Calls
Scaffold(
resizeToAvoidBottomInset: false,
appBar: CometChatMessageHeader(
user: user,
group: group,
onBack: () => Navigator.pop(context),
hideVoiceCallButton: false,
hideVideoCallButton: false,
),
body: Column(
children: [
Expanded(child: CometChatMessageList(user: user, group: group)),
CometChatMessageComposer(user: user, group: group),
],
),
)
BLoC Events
CallButtonsBloc
| Event | Purpose |
|---|
InitiateVoiceCall | Start audio call |
InitiateVideoCall | Start video call |
IncomingCallBloc
| Event | Purpose |
|---|
AcceptCall | Accept the incoming call |
RejectCall | Decline the incoming call |
OutgoingCallBloc
| Event | Purpose |
|---|
CancelCall | Cancel the outgoing call |
CallAccepted(call) | Receiver accepted |
CallRejected(call) | Receiver rejected |
OngoingCallBloc
| Event | Purpose |
|---|
StartSession(sessionId, settings) | Begin WebRTC session |
EndSession | End the call |
CallLogsBloc
| Event | Purpose |
|---|
LoadCallLogs | Initial load |
LoadMoreCallLogs | Pagination |
Gotchas
CometChatUIKitCalls.init() must happen AFTER CometChatUIKit.init() ā parallel init causes "auth token null".
- After logout, the calls SDK session is invalidated. Re-init required on next login.
startSession on Android can return null with a 5-second timeout and no error feedback. Known platform issue.
SessionType.audio is ignored on Android in some SDK versions ā always opens with video. Known external SDK bug.
- Group calls use
CometChat.Group not CometChat.User on CometChatCallButtons.
- Incoming call handling must be global (mounted at app root level) so calls ring on every screen.
CallOperationsServiceLocator must be initialized before using call BLoCs directly. UIKit widgets handle this automatically.
- After logout, call
CallOperationsServiceLocator.instance.reset() to clean up.
- On iOS, CallKit integration via
native_call_kit shows the native call UI. Ensure Info.plist has the voip background mode.
- On Android, the ongoing call foreground service shows a notification during active calls. Launched automatically by
startSession.
Anti-Patterns
// ā WRONG ā init calls SDK before chat SDK
CometChatUIKitCalls.init(appId, region);
CometChatUIKit.init(uiKitSettings: settings);
// ā
CORRECT ā calls init in chat init's onSuccess
CometChatUIKit.init(
uiKitSettings: settings,
onSuccess: (_) {
CometChatUIKitCalls.init(appId, region);
},
);
// ā WRONG ā not handling incoming calls globally
CometChatIncomingCall(call: call, user: user) // Only on messages screen
// ā
CORRECT ā mount incoming call overlay at app root
MaterialApp(
builder: (context, child) {
return Stack(children: [child!, /* Global incoming call listener */]);
},
)
Checklist