Skip to main content

What this guide covers

  • Adding the @cometchat/push-notifications-react-native package and initializing it.
  • Platform wiring: Firebase/google-services.json on Android, the setup CLI + PushKit forwarding on iOS.
  • Requesting permission and registering tokens (FCM on Android, APNs + VoIP on iOS) after login.
  • Receiving pushes and letting the package render chat notifications and full-screen / CallKit calls.
  • Handling notification taps (including thread deep-links), incoming-call navigation, and Android OEM permissions.
  • Testing and troubleshooting.
The @cometchat/push-notifications-react-native package replaces the previous approach of copying the sample app’s notifications stack and hand-wiring @react-native-firebase/messaging, notifee, react-native-callkeep, and react-native-voip-push-notification. Token registration, foreground presentation, notification taps, and the full incoming-call experience (the Android lock-screen call activity and iOS CallKit) are handled inside the package — the design is JS-first: native code only shows the UI and captures tokens, while every CometChat action (register token, accept/reject/end call) runs in JavaScript through the Chat SDK your app already ships.

How it works

  • Android (FCM): Firebase issues the registration token and delivers the CometChat payload as a data message. The package ships its own FirebaseMessagingService, so it receives the message and shows the notification or full-screen call itself — you write no FCM handling code.
  • iOS (APNs + PushKit): Apple issues the APNs device token (chat alerts) and the VoIP token (calls). APNs alerts are shown by the system; VoIP pushes are presented through CallKit by the package. Your AppDelegate forwards the tokens and incoming VoIP pushes to the package (the setup CLI generates this).
  • CometChat’s role: The providers you add in the dashboard bind your registered tokens to the logged-in user so CometChat can route pushes on your behalf.
  • The package’s role: it retrieves the tokens, registers them with CometChat, parses payloads, drives the call UI, and calls the Chat SDK to accept/reject/end. It requires @cometchat/chat-sdk-react-native as a peer dependency — the one Chat SDK your app already uses, so there is no second SDK to version-align.

Prerequisites

  • The providers, Firebase project, and Apple/APNs credentials from Getting Started (this guide assumes those are done).
  • React Native 0.65+, and an app already initializing and logging in with @cometchat/chat-sdk-react-native (or the UI Kit).
  • Android: google-services.json in android/app/, the com.google.gms.google-services plugin, minSdkVersion 24+.
  • iOS: iOS 13.0+ (set the Podfile platform to 14.0 for VoIP/CallKit).
  • A physical device — background delivery, full-screen calls, and VoIP pushes are unreliable on emulators/simulators.
Complete the Getting Started guide first — enable Push Notifications, add your providers (FCM for Android, APNs + APNs VoIP for iOS), and finish the Firebase/Apple setup. This guide covers only the React Native app wiring.

1. Store your credentials

Keep the values from Getting Started somewhere your app can read them. Only the fields for the platforms you ship are needed:

2. Add the package and configure the platform

Install the package (the Chat SDK peer is already in your app):
With google-services.json already in android/app/ (from Getting Started):
  1. Apply the Google Services plugin and Firebase Messaging in your Gradle files:
  1. Keep minSdkVersion 24 or higher.
You do not need to add notification, call, full-screen-intent, or lock-screen permissions to your AndroidManifest.xml, and you write no FCM/JS message-handling code. The package’s library manifest contributes everything it needs — the FirebaseMessagingService, the incoming-call foreground service, the full-screen lock-screen CallRingingActivity, the notification trampoline/decline receiver, and POST_NOTIFICATIONS — and Gradle merges them into your app automatically.

3. Initialize the SDK

Register the killed-state background task at module scope in index.js (before any component renders), then initialize the package after the user logs in.
init wires the native events to the Chat SDK, auto-registers the device tokens, and drains any cold-start tap/call the app was launched from. It is safe to call again on re-login. init also accepts: voip (default true), notificationSmallIcon, androidChannelId, and androidChannelName.

4. Request permission and register tokens

Permission is requested via CometChatPNHelper (call it before pushes/calls arrive):
Token registration is automaticinit() registers the FCM token (Android) and the APNs device + VoIP tokens (iOS) with CometChat, and re-registers on refresh. You rarely need to do it by hand, but you can:
On logout, unsubscribe your handlers and unregister the token so the device stops receiving pushes for that user:
Not unsubscribing on logout leaves the callbacks registered, so a logout → login cycle would fire each handler twice (e.g. navigating to a tapped message twice).

5. Notification taps and call events

Subscribe once (in setupPush above). Each subscribe returns an unsubscribe function. Notification tap — open the conversation, or the thread when the push is a thread reply:
Call accepted — the package has already accepted the call via the Chat SDK; just open your call screen:
Call ended — a ringing call was cancelled/declined/ended, or the user ended the call from the iOS CallKit UI. The Calls SDK’s own listener doesn’t see a CallKit-initiated end, so tear the call down here:
Cold-start VoIP handling (iOS): when the app is killed and a VoIP push arrives, the package presents CallKit natively via PushKit before React Native is ready. When the user answers, the app cold-starts, init() replays the accepted call, onCallAccepted fires, and the package has already called CometChat.acceptCall — set up your call session/screen there. (This path is why the PKPushRegistry must be on a background queue — see step 2.)

6. Android: OEM permissions for lock-screen calls

The package declares the standard permissions and uses the correct setShowWhenLocked / setTurnScreenOn flags, so full-screen calls over the lock screen work out of the box on stock Android (including Android 14+). OEM skins (MIUI/Redmi/POCO, Oppo, Vivo) additionally gate background-launched full-screen activities behind their own toggles — without them, a locked/killed call shows only a heads-up notification (with ringtone), and the full-screen screen appears only after unlock. Guide users to grant, on those devices:
  • Autostart — Settings → Apps → your app → Autostart (or the Security app).
  • Display pop-up windows while running in background — Settings → Apps → your app → Other permissions.
  • Show on lock screen — same “Other permissions” screen.
  • Disable battery optimization for the app.
These OEM settings cannot be granted programmatically (the OS blocks it); open the app’s settings page so the user can toggle them:

7. Badge count

CometChat’s Enhanced Push payload includes an unreadMessageCount field (total unread across conversations).
With APNs the badge is handled server-side: CometChat sets aps.badge in the payload and iOS updates the app icon automatically — no client code required.

8. Testing checklist

  1. Run on a physical device. Grant notification, microphone, and camera permissions when prompted (Android 13+ requires POST_NOTIFICATIONS).
  2. Send a message from another user:
    • Foreground: no system banner (with showInForeground: false); your in-app UI shows it.
    • Background: a notification appears; tapping opens the right conversation via onNotificationTap (and the thread, for a thread reply).
  3. Force-quit the app, send another message, tap the notification, and confirm it cold-starts to the conversation.
  4. Trigger an incoming CometChat call and confirm:
    • The full-screen call UI (Android) / CallKit (iOS) shows the caller with Accept/Decline, even on the lock screen.
    • Accept joins the call (audio works both ways) and the screen tears down when the call ends.
    • Decline rejects the call promptly on the caller side — including from a killed state.
    • Caller cancels while it’s ringing → the callee ring dismisses.
  5. On an OEM device (MIUI/Oppo/Vivo), grant the section-6 permissions and re-check locked/killed calls.

9. Troubleshooting

Resources

@cometchat/push-notifications-react-native

The drop-in push & VoIP package on npm.

@cometchat/chat-sdk-react-native

The peer Chat SDK the package registers tokens and drives calls through.