CometChat.initiateCall created the call, a CallListener on the WebSocket told the callee, acceptCall and rejectCall answered, and the app rang the device itself — usually with react-native-callkeep and react-native-voip-push-notification wired up by hand. Ringing now runs on the Calls SDK and the Push Notifications SDK’s VoIP package. The Chat SDK’s calling methods are deprecated.
This page is the diff. For the full description of the current flow see Ringing; for the push side see Push ringing.
Before you start
Ringing with the Calls SDK is opt-in on the client: moving your app to the Calls SDK 5.1 and Push Notifications SDK 2.0 APIs below is the migration. While some of your users are still on legacy ringing, one dashboard setting lets the two flows call each other; see While some users are still on legacy ringing. If you use the CometChat UI Kit, keep its calling as it is: the Kit’s call components still use the Chat SDK (CometChat.initiateCall, CometChat.acceptCall), so installing these packages doesn’t move them to this flow. This guide applies to your own calling screens and handlers. See Calling integration.
Why it changed
Before and after
Step 1: Update dependencies
minSdkVersion24 or higher on Android, iOS 15.1+. Below API 26 the ring posts a plain notification rather than the channel-backed, full-screen one.- Keep
google-services.json.@react-native-firebase/messagingis optional: if you keep it, forward pushes to the package as in section 4.5 of the Android push guide. - Remove
react-native-callkeepandreact-native-voip-push-notificationif nothing else uses them; the VoIP package registers with PushKit and CallKit itself.
Step 2: Replace the push configuration
- Before (Push SDK 1.0)
- After (Push SDK 2.0)
clientHost. Otherwise the push token registers on the default host and no push ever arrives.
Step 3: Make init() the first thing you await
init() — a stored-credentials read, a remote config fetch, a login — spends that window, and the call is lost before the ring is wired up.
Step 4: Register the background task and delete the token code
index.js
unregister() before you log out (see Step 7). Remove:
messaging().getToken()+registerPushToken(...)after loginVoipPushNotification.addEventListener('register', …)and the APNs VoIP token plumbingunregisterPushToken(...)before logout — replaced byCometChatPushNotifications.unregister(), which must run beforelogout()
Step 5: Delete the app-side ringing
Everything in this list is now done by the Push SDK. Remove it, or it will fight the SDK’s ring (two ringtones, two screens, a busy reject sent on top of the SDK’s).CometChat.addCallListener(...)and itsonIncomingCallReceivedhandler- The incoming-call modal, overlay or screen you rendered from it
- Your own ringtone or sound player for incoming calls
- The “already in a call → reject with busy” check
RNCallKeep.setup,displayIncomingCall,answerCall/endCallevent wiring,VoipPushNotificationhandlers, and theREAD_PHONE_STATE/MANAGE_OWN_CALLS/ANSWER_PHONE_CALLSpermission chain- Any foreground check around call pushes
NSMicrophoneUsageDescription, NSCameraUsageDescription and the voip background mode in Info.plist — those are your app’s own and nothing merges them in. You can drop RECORD_AUDIO, CAMERA and POST_NOTIFICATIONS from your Android manifest: the push package declares POST_NOTIFICATIONS, the VoIP package declares the other two, and the manifest merger adds them for you. (An app that installs only the push package gets no call permissions at all — that is the point of the split.)
Step 6: Rewrite the call code
Caller screen, before and after
- Before
- After
Callee screen, before and after
- Before
- After
Step 7: Change the logout
- Before
- After
unregister() after logout() cannot authenticate the delete, so the token stays registered and the device goes on receiving the departed user’s call pushes. Logging out of the Chat SDK alone leaves the Calls SDK signed in, so a ring keeps playing for the old user.
If you drew your own incoming-call screen
You can keep it. Subscribe toonCallRinging instead of CallListener.onIncomingCallReceived, close it from onRingEnded, and answer and decline through CometChatVoipNotifications.answerCall / declineCall. Tell the SDK your screen is up with notifyCallScreenOpen(sessionId) so it does not also show its own. See Your own incoming-call screen.
This replaces the in-app screen only. A push that arrives while your app is killed still rings with the SDK’s native screen on Android and CallKit on iOS — neither can be drawn from JavaScript that is not running.
While some users are still on legacy ringing
Your users don’t all update at once, so during the rollout one CometChat app has devices on both flows. A device’s flow comes from its push registration: a device on the Calls SDK 5.1 and Push Notifications SDK 2.0 receives only the call-initiated push, and a device still on legacy ringing keeps receiving the legacy call events. To let users on the two flows call each other, turn on Connect legacy ringing in the CometChat dashboard under Voice & Video Calls → Settings. CometChat then also sends calls made on this flow as legacy call events, so devices on either flow ring for calls from the other.- Turn it on before the first users update, and leave it on while any version of your app still in use rings the legacy way.
- It can’t be turned off from the dashboard.
- The six legacy call events (ongoing, cancelled, rejected, unanswered, busy and ended) are under Show legacy in Notifications → Settings → Call Preferences. They only reach devices on legacy ringing.
This is a server-side bridge, so it needs no code on either side. A device that has been updated does not need the legacy
CallListener back — keep it deleted.What users will notice
- Calls now ring with the app killed, and from the lock screen.
- The caller sees “Ringing…” once the callee’s device has actually been reached, and a reason when a call ends.
- A second call rings over a live one instead of being silently rejected.
- Missed calls appear as their own notifications.
Checklist
- Calls SDK 5.1, Push SDK 2.0 core and VoIP packages installed; CallKeep and VoIP-push libraries removed
-
CometChatVoipNotifications.init()is the firstawaiton startup, and the chat app passes it no config -
registerBackgroundCallTask()called at module scope inindex.js - All
CometChat.addCallListenercall handling, app-side ringtones and busy checks deleted - Caller listens on the prepared session for
onParticipantConnected/onParticipantJoined -
onCallAcceptedandonCallEndedrepointed fromCometChatPushNotificationstoCometChatVoipNotifications, and subscribed before the first call can arrive - Hang-up uses
session.leave(), cancel usesendCall(sessionId, 'cancelled') - Logout unregisters push first, then clears the identity, then logs out
-
requestCallPermissions()called after sign-in;ensureRingReady()checked;NSMicrophoneUsageDescriptionpresent - Staging or dedicated host passed to the Push SDK as well
- Connect legacy ringing turned on in the dashboard before the first users update, if any of your app versions still ring the legacy way
- All three packages installed: Calls SDK 5.1 and both Push Notifications packages at 2.0