npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cometchat/push-notifications-react-native

v1.0.0

Published

Drop-in push notifications and VoIP calling for CometChat React Native apps. JS-first: a native display engine (FCM/notifications + CallKit/PushKit) drives the OS UI; all CometChat actions run through your existing chat-sdk-react-native — no second native

Readme

CometChat Push Notifications — React Native

Drop-in push notifications and VoIP calling for CometChat React Native apps.

JS-first design. A small native "display engine" (our own Kotlin + Swift) shows the notification and rings the system call UI (FCM + notifications on Android; PushKit + CallKit on iOS) and captures push tokens. Every CometChat action — registering the token, accepting/rejecting a call — runs in JavaScript through the @cometchat/chat-sdk-react-native your app already ships. There is no second, native Chat SDK, so there is nothing to version-align (the same approach the CometChat Flutter plugin uses).

No @react-native-firebase, Notifee, CallKeep, or voip-push in this package. The only native dependency is firebase-messaging (the FCM transport on Android). Already using @react-native-firebase/messaging? See Coexisting with another FCM service.

Installation

npm install @cometchat/push-notifications-react-native
cd ios && pod install

Requires React Native 0.78 or later and @cometchat/chat-sdk-react-native 4.0.10 or later (already in your app), used at runtime for all CometChat calls. Apps with calls also need @cometchat/calls-sdk-react-native, an optional peer.

One-time native setup

Android needs no app-side native code — the library ships its own FCM service and call UI. You only add google-services.json and apply the com.google.gms.google-services plugin (standard FCM setup). Before publishing, read Android: calls, permissions and Google Play.

iOS needs a few lines in your app:

  1. Enable the Push Notifications capability, and Background Modes with Voice over IP, Remote notifications and Audio.

  2. Add NSMicrophoneUsageDescription and NSCameraUsageDescription to Info.plist.

  3. In AppDelegate, start the package's PushKit registry before React Native starts, and forward the APNs token:

    import react_native_cometchat_push_notifications
    
    // in application(_:didFinishLaunchingWithOptions:), before factory.startReactNative(...)
    CometChatPushNotificationsAppDelegate.registerForVoIPPushes()
    
    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
      CometChatPushNotificationsAppDelegate.didRegisterAPNsToken(deviceToken)
    }

    The package owns PushKit, so don't create a PKPushRegistry of your own. If another library already owns one, skip registerForVoIPPushes() and forward that registry's token and pushes to didUpdateVoIPToken / didReceiveIncomingVoIPPush instead.

    Chat-only apps skip registerForVoIPPushes() and the Voice over IP and Audio background modes, and pass voip: false to init().

The full AppDelegate code is in the React Native push notifications guide for iOS.

Usage

In index.js, at module scope (never inside a component), so a fully killed Android app can reject a call declined from its notification — without it the caller keeps ringing:

import { registerBackgroundCallTask } from "@cometchat/push-notifications-react-native";

registerBackgroundCallTask();

Then in your app:

import {
  CometChatPNHelper,
  CometChatPushNotifications,
} from "@cometchat/push-notifications-react-native";

// 1. after every login (and a session restored on launch) — AFTER CometChat.init(...).
//    Ask for permissions first: without the notification permission, Android 13+ shows
//    no notifications at all. A rejection means the OS couldn't ask; init() still runs.
await CometChatPNHelper.requestNotificationPermission().catch(() => false);
await CometChatPNHelper.requestCallPermissions(); // Android mic + camera, before a call connects

// Tokens register automatically, for this login session.
await CometChatPushNotifications.init({
  fcmProviderId: "your-fcm-provider",
  apnsProviderId: "your-apns-provider",
  // ringInForeground: false — only if your app shows its own incoming-call screen while
  // it is open (the CometChat UI Kit does). By default calls ring with CallKit / the
  // Android ringing screen in every app state.
});

// 2. navigate when a chat notification is tapped
CometChatPushNotifications.onNotificationTap(({ sender, receiver, receiverType, parentMessageId }) => {
  // resolve User/Group via the Chat SDK and navigate
});

// 3. a call answered from the system UI is already accepted (CometChat.acceptCall
//    ran for you) — just open your ongoing-call screen
CometChatPushNotifications.onCallAccepted(({ sessionId, callType }) => {
  navigate("OngoingCall", { sessionId, callType });
});

// 4. log out: unregister FIRST — it needs the session, so after logout it fails and the
//    device keeps receiving this user's notifications
async function logout(): Promise<boolean> {
  try {
    await CometChatPushNotifications.unregister();
  } catch {
    return false; // e.g. offline — stay logged in so the user can retry
  }
  await CometChat.logout();
  return true;
}

That's it — no token plumbing. The native engine hands the token to JS and the package calls CometChatNotifications.registerPushToken(...) on your Chat SDK.

API

| Method / event | Purpose | | --- | --- | | init(config) | Wire the native display engine + auto-register tokens, after each login. Options: provider IDs, voip, ringInForeground, showInForeground, Android icon and channel. | | onNotificationTap(cb) | User tapped a chat notification. cb returns an unsubscribe fn. | | onCallAccepted(cb) | A call was answered and accepted via the Chat SDK — open your call screen. | | onCallEnded(cb) | A ringing call was cancelled / declined / ended, or rang out unanswered (45s). | | onMessageReceived(cb) | A data push arrived (e.g. to markAsDelivered via the Chat SDK). | | registerToken(platform, token) | Manual token registration (rarely needed). | | unregister() | Unregister this device's token. Call it before logout — it needs the session. | | dispose() | Detach the native listeners (init() does this itself before re-wiring). | | registerBackgroundCallTask(handler?) | Android: lets a killed app reject a declined call. Module scope in index.js. | | CometChatPNHelper.isCometChatNotification(data) | Route only CometChat pushes. | | CometChatPNHelper.requestNotificationPermission() / hasNotificationPermission() | OS notification permission. | | CometChatPNHelper.requestCallPermissions() | Android microphone + camera, needed before a call connects (no-op on iOS). |

Android: calls, permissions and Google Play

The package's manifest adds what calls need to your app: USE_FULL_SCREEN_INTENT, FOREGROUND_SERVICE_PHONE_CALL, MANAGE_OWN_CALLS, RECORD_AUDIO, CAMERA and BLUETOOTH_CONNECT, plus the incoming-call service and ringing screen. Camera and microphone hardware are declared optional, so Google Play doesn't hide the app from devices without them.

Apps with calls. For apps targeting Android 14+, Google Play requires two declarations in Play Console under App content (Play Console Help):

  • Full-screen intent permission — declare calling as core functionality. Without it Play revokes USE_FULL_SCREEN_INTENT, and calls ring only as a heads-up notification (the package logs a warning when that happens).
  • Foreground service permissions — declare the Phone call type.

Chat-only apps. Pass voip: false to init() so call pushes never ring, skip requestCallPermissions() and registerBackgroundCallTask(), and remove the call permissions and components in your app's android/app/src/main/AndroidManifest.xml (with xmlns:tools="http://schemas.android.com/tools" on <manifest>):

<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" tools:node="remove" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" tools:node="remove" />
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" tools:node="remove" />
<uses-permission android:name="android.permission.RECORD_AUDIO" tools:node="remove" />
<uses-permission android:name="android.permission.CAMERA" tools:node="remove" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" tools:node="remove" />

<application>
  <service android:name="com.cometchat.pushnotification.reactnative.IncomingCallService" tools:node="remove" />
  <activity android:name="com.cometchat.pushnotification.reactnative.CallRingingActivity" tools:node="remove" />
</application>

tools:node="remove" drops an entry whichever library declared it — keep any permission another part of your app still uses.

Coexisting with another FCM service

Android delivers FCM messages and token refreshes to only one FirebaseMessagingService. If your app has another — its own, or the one in @react-native-firebase/messaging — it is undefined which one receives them, and the other silently gets nothing. Replace both with one service of your own that forwards to each:

  1. In android/app/src/main/AndroidManifest.xml:

    <application>
      <service android:name="com.cometchat.pushnotification.reactnative.CometChatFcmService" tools:node="remove" />
      <service android:name="io.invertase.firebase.messaging.ReactNativeFirebaseMessagingService" tools:node="remove" />
      <service android:name=".AppMessagingService" android:exported="false">
        <intent-filter>
          <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
      </service>
    </application>
  2. In android/app/build.gradle, add Firebase Messaging so your service can extend it (use the BOM version your other Firebase libraries use):

    dependencies {
      implementation platform("com.google.firebase:firebase-bom:33.16.0")
      implementation "com.google.firebase:firebase-messaging"
    }
  3. Add the service next to MainApplication.kt:

    package com.yourapp // your app's package
    
    import com.cometchat.pushnotification.reactnative.CometChatFcmService
    import com.google.firebase.messaging.RemoteMessage
    import io.invertase.firebase.messaging.ReactNativeFirebaseMessagingService
    
    class AppMessagingService : ReactNativeFirebaseMessagingService() {
      override fun onMessageReceived(message: RemoteMessage) {
        // CometChat's pushes are shown by this package; anything else goes on.
        if (!CometChatFcmService.handleMessage(this, message)) super.onMessageReceived(message)
      }
    
      override fun onNewToken(token: String) {
        CometChatFcmService.handleNewToken(this, token)
        super.onNewToken(token)
      }
    }

    Without React Native Firebase, extend FirebaseMessagingService and run your own handling where this calls super.

  4. React Native Firebase also hands every push to its JavaScript handlers. Skip CometChat's there, in onMessage and setBackgroundMessageHandler:

    messaging().onMessage(async (remoteMessage) => {
      if (CometChatPNHelper.isCometChatNotification(remoteMessage.data)) return; // shown by this package
      // your handling
    });

How it works

 Push arrives ─▶ native display engine (Kotlin / Swift)
                   • shows notification / rings CallKit   ← OS-level, must be native
                   • captures FCM / APNs / VoIP token
                   • emits an event to JS
 JS (this package) ─▶ your @cometchat/chat-sdk-react-native
                   • registerPushToken(token, platform, providerId)
                   • acceptCall(sessionId) / rejectCall(sessionId)

The native side never touches the CometChat SDK; JavaScript does all of it, through the one SDK instance your app is already logged into.

Documentation

Full setup for Android and iOS, notification taps, calls, logout and troubleshooting: React Native push notifications guides for Android and iOS.

License

See LICENSE.md.