Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
cometchat avatar

Cometchat Android V5 Push

  • 5 installs
  • 70 repo stars
  • Updated June 23, 2026
  • cometchat/cometchat-skills

Sets up FCM push notifications for CometChat Android v5, covering the CometChatNotifications API, token registration, foreground/background handling, and tap-to-deep-link.

About

This skill covers end-to-end Firebase Cloud Messaging setup for CometChat v5 Android using CometChatNotifications with PushPlatforms.FCM_ANDROID, notification channels, and reply-from-notification. A developer uses it so a backgrounded app wakes on incoming messages and taps deep-link into the chat.

  • CometChatNotifications API with PushPlatforms.FCM_ANDROID token registration
  • Notification channels, reply-from-notification, and tap-to-deep-link

Cometchat Android V5 Push by the numbers

  • 5 all-time installs (skills.sh)
  • Ranked #828 of 1,039 Mobile Development skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cometchat/cometchat-skills --skill cometchat-android-v5-push

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs5
repo stars70
Last updatedJune 23, 2026
Repositorycometchat/cometchat-skills

What it does

Sets up FCM push notifications for CometChat Android v5, covering the CometChatNotifications API, token registration, foreground/background handling, and tap-to-deep-link.

Files

SKILL.mdMarkdownGitHub ↗
Companion skills: cometchat-android-v5-core covers init and login;
cometchat-android-v5-production covers production auth and token security.

Purpose

Push notifications are non-negotiable for production chat. Without them, a backgrounded app never wakes when a message arrives. This skill covers end-to-end FCM setup for CometChat Android v5 — using the correct CometChatNotifications API with PushPlatforms.FCM_ANDROID, notification channels, foreground/background handling, reply-from-notification, and tap-to-deep-link.

Ground truth: sample-app-java+push-notification/src/main/java/com/cometchat/sampleapp/java/fcm/ and sample-app-kotlin+push-notification/src/main/java/com/cometchat/sampleapp/kotlin/fcm/ in the v5 UIKit repository.

---

Use this skill when

  • "Set up push notifications"
  • "Messages don't arrive when app is backgrounded"
  • "How do I handle notification taps?"
  • "FCM token registration with CometChat"
  • "How do I register push token?"
  • "CometChatNotifications API"

Do not use this skill when

  • Setting up init/login → use cometchat-android-v5-core
  • Diagnosing non-push issues → use cometchat-android-v5-troubleshooting
  • Setting up VoIP calls → see VoIP section in this skill, but call UI is in cometchat-android-v5-features

---

1. The moving pieces

FCM (Google) → CometChat Dashboard → CometChat Server → Android Client

When user A sends a message to user B: 1. CometChat server receives the message 2. Looks up B's registered push token (registered via CometChatNotifications.registerPushToken()) 3. Sends push via FCM using the dashboard credentials 4. B's device receives it via FirebaseMessagingService.onMessageReceived() 5. App builds and displays a notification; tap → deep-link to conversation

All five steps must work. A broken step is almost always silent — no log, no error, just no notification.

---

2. FCM setup

2a. Firebase project + google-services.json

1. https://console.firebase.google.com → Add project 2. Project Overview → Add app → Android → enter your applicationId 3. Download google-services.json → place at app/google-services.json

2b. Gradle dependencies

// project-level build.gradle
buildscript {
    dependencies {
        classpath 'com.google.gms:google-services:4.4.2'
    }
}

// app-level build.gradle
apply plugin: 'com.google.gms.google-services'

dependencies {
    implementation 'com.google.firebase:firebase-messaging:24.+'
}

2c. Service account JSON (for CometChat dashboard)

1. Firebase Console → Project Settings → Service accounts 2. Generate new private key → downloads a .json file 3. You'll upload this to the CometChat dashboard in §3

---

3. CometChat dashboard — upload FCM credentials

1. https://app.cometchat.com → your app → NotificationsPush Notifications 2. Add Provider → choose FCM 3. Upload the service account .json file from §2c 4. Save → note the Provider ID (e.g., "Android-CometChat-Team-Messenger")

You'll use this Provider ID in your client code when calling CometChatNotifications.registerPushToken().

---

4. Token registration API — CometChatNotifications

The v5 SDK uses CometChatNotifications.registerPushToken()not the deprecated CometChat.registerTokenForPushNotification().

API reference

MethodSignatureDescription
registerPushTokenCometChatNotifications.registerPushToken(String token, String platform, String providerId, CallbackListener<String>)Register FCM token with CometChat
unregisterPushTokenCometChatNotifications.unregisterPushToken(CallbackListener<String>)Unregister token (call before logout)

PushPlatforms constants

ConstantValueUse for
PushPlatforms.FCM_ANDROID"fcm_android"Android FCM push

Register token after login

Java:

public static void registerFCMToken(CometChat.CallbackListener<String> listener) {
    FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {
        if (task.isSuccessful()) {
            String pushToken = task.getResult();
            CometChatNotifications.registerPushToken(
                pushToken,
                PushPlatforms.FCM_ANDROID,
                "YOUR_PROVIDER_ID",  // from CometChat dashboard §3
                new CometChat.CallbackListener<String>() {
                    @Override
                    public void onSuccess(String s) {
                        listener.onSuccess(s);
                    }

                    @Override
                    public void onError(CometChatException e) {
                        listener.onError(e);
                    }
                }
            );
        } else {
            listener.onError(new CometChatException("ERROR", "Failed to get FCM token"));
        }
    });
}

Kotlin:

fun registerFCMToken(listener: CometChat.CallbackListener<String>) {
    FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val pushToken = task.result
            CometChatNotifications.registerPushToken(
                pushToken,
                PushPlatforms.FCM_ANDROID,
                "YOUR_PROVIDER_ID",  // from CometChat dashboard §3
                object : CometChat.CallbackListener<String?>() {
                    override fun onSuccess(s: String?) {
                        listener.onSuccess(s)
                    }

                    override fun onError(e: CometChatException) {
                        listener.onError(e)
                    }
                }
            )
        } else {
            listener.onError(CometChatException("ERROR", "Failed to get FCM token"))
        }
    }
}

Unregister before logout

Java:

public static void unregisterFCMToken(CometChat.CallbackListener<String> listener) {
    CometChatNotifications.unregisterPushToken(new CometChat.CallbackListener<String>() {
        @Override
        public void onSuccess(String s) {
            listener.onSuccess(s);
        }

        @Override
        public void onError(CometChatException e) {
            listener.onError(e);
        }
    });
}

Kotlin:

fun unregisterFCMToken(listener: CometChat.CallbackListener<String>) {
    CometChatNotifications.unregisterPushToken(object : CometChat.CallbackListener<String?>() {
        override fun onSuccess(s: String?) {
            listener.onSuccess(s)
        }

        override fun onError(e: CometChatException) {
            listener.onError(e)
        }
    })
}

---

5. FirebaseMessagingService implementation

5a. Service class

Java:

public class FCMService extends FirebaseMessagingService {
    private static String fcmToken;

    @Override
    public void onNewToken(@NonNull String token) {
        super.onNewToken(token);
        fcmToken = token;
        // Re-register if user is already logged in
        // (token rotation can happen at any time)
    }

    @Override
    public void onMessageReceived(@NonNull RemoteMessage message) {
        super.onMessageReceived(message);
        if (message.getData().isEmpty()) return;

        String type = message.getData().get("type");
        if ("chat".equalsIgnoreCase(type)) {
            handleChatMessage(message);
        } else if ("call".equalsIgnoreCase(type)) {
            handleCallMessage(message);
        }
    }

    private void handleChatMessage(RemoteMessage message) {
        FCMMessageDTO dto = new Gson().fromJson(
            new Gson().toJson(message.getData()), FCMMessageDTO.class);

        // Mark as delivered
        CometChat.markAsDelivered(
            Long.parseLong(dto.getTag()),
            dto.getSender(),
            dto.getReceiverType(),
            dto.getReceiver()
        );

        // Build and show notification
        Intent clickIntent = new Intent(this, SplashActivity.class);
        FCMMessageNotificationUtils.showNotification(
            this, dto, clickIntent,
            "Reply", NotificationCompat.CATEGORY_MESSAGE
        );
    }
}

Kotlin:

class FCMService : FirebaseMessagingService() {
    companion object {
        var fcmToken: String? = null
            private set
    }

    override fun onNewToken(token: String) {
        super.onNewToken(token)
        fcmToken = token
    }

    override fun onMessageReceived(message: RemoteMessage) {
        super.onMessageReceived(message)
        if (message.data.isEmpty()) return

        when (message.data["type"]?.lowercase()) {
            "chat" -> handleChatMessage(message)
            "call" -> handleCallMessage(message)
        }
    }

    private fun handleChatMessage(message: RemoteMessage) {
        val dto = Gson().fromJson(
            Gson().toJson(message.data), FCMMessageDTO::class.java)

        CometChat.markAsDelivered(
            dto.tag!!.toLong(),
            dto.sender!!,
            dto.receiverType!!,
            dto.receiver!!
        )

        val clickIntent = Intent(this, SplashActivity::class.java)
        FCMMessageNotificationUtils.showNotification(
            this, dto, clickIntent,
            "Reply", NotificationCompat.CATEGORY_MESSAGE
        )
    }
}

5b. Register in AndroidManifest.xml

<service
    android:name=".fcm.FCMService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

---

6. Push payload schema

CometChat sends data-only FCM messages. The payload fields:

Chat message payload (type: "chat")

FieldTypeDescription
typeStringAlways "chat" for messages
senderStringSender UID
senderNameStringSender display name
senderAvatarStringSender avatar URL
receiverStringReceiver UID (user) or GUID (group)
receiverNameStringReceiver display name
receiverTypeString"user" or "group"
receiverAvatarStringReceiver avatar URL
conversationIdStringConversation ID
bodyStringMessage text
titleStringNotification title
tagStringMessage ID (as string)
unreadMessageCountStringUnread count (as string)

Call payload (type: "call")

FieldTypeDescription
typeStringAlways "call"
callActionString"initiated", "cancelled", "unanswered"
sessionIdStringCall session ID
callTypeString"audio" or "video"
sender / receiver / senderName / etc.StringSame as chat payload

DTO classes

Java:

public class FCMMessageDTO {
    @SerializedName("conversationId") private String conversationId;
    @SerializedName("sender") private String sender;
    @SerializedName("receiver") private String receiver;
    @SerializedName("receiverName") private String receiverName;
    @SerializedName("receiverType") private String receiverType;
    @SerializedName("receiverAvatar") private String receiverAvatar;
    @SerializedName("tag") private String tag;
    @SerializedName("body") private String text;
    @SerializedName("type") private String type;
    @SerializedName("title") private String title;
    @SerializedName("senderAvatar") private String senderAvatar;
    @SerializedName("senderName") private String senderName;
    @SerializedName("unreadMessageCount") private String unreadMessageCount;
    // getters and setters
}

Kotlin:

class FCMMessageDTO {
    @SerializedName("conversationId") var conversationId: String? = null
    @SerializedName("sender") var sender: String? = null
    @SerializedName("receiver") var receiver: String? = null
    @SerializedName("receiverName") var receiverName: String? = null
    @SerializedName("receiverType") var receiverType: String? = null
    @SerializedName("receiverAvatar") var receiverAvatar: String? = null
    @SerializedName("tag") var tag: String? = null
    @SerializedName("body") var text: String? = null
    @SerializedName("type") var type: String? = null
    @SerializedName("title") var title: String? = null
    @SerializedName("senderAvatar") var senderAvatar: String? = null
    @SerializedName("senderName") var senderName: String? = null
    @SerializedName("unreadMessageCount") var unreadMessageCount: String? = null
}

Parse from RemoteMessage:

FCMMessageDTO dto = new Gson().fromJson(new Gson().toJson(message.getData()), FCMMessageDTO.class);

---

7. Notification channels (API 26+)

Create channels in your Application.onCreate() or before showing the first notification:

Java:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    NotificationManager manager = getSystemService(NotificationManager.class);

    NotificationChannel messageChannel = new NotificationChannel(
        "Message",                              // channel ID
        "Message notification",                 // channel name
        NotificationManager.IMPORTANCE_HIGH
    );
    manager.createNotificationChannel(messageChannel);

    NotificationChannel callChannel = new NotificationChannel(
        "Call",
        "Call notification",
        NotificationManager.IMPORTANCE_HIGH
    );
    callChannel.setSound(null, null);  // calls use their own ringtone
    manager.createNotificationChannel(callChannel);
}

Kotlin:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    val manager = getSystemService(NotificationManager::class.java)

    val messageChannel = NotificationChannel(
        "Message", "Message notification", NotificationManager.IMPORTANCE_HIGH
    )
    manager.createNotificationChannel(messageChannel)

    val callChannel = NotificationChannel(
        "Call", "Call notification", NotificationManager.IMPORTANCE_HIGH
    ).apply { setSound(null, null) }
    manager.createNotificationChannel(callChannel)
}

---

8. Tap-to-deep-link

The notification click intent routes through SplashActivityHomeActivity → correct fragment/conversation.

Setting up the click intent

Java:

Intent clickIntent = new Intent(context, SplashActivity.class);
clickIntent.putExtra("NOTIFICATION_TYPE", "NOTIFICATION_TYPE_MESSAGE");
clickIntent.putExtra("NOTIFICATION_DATA", new Gson().toJson(fcmMessageDTO));
clickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

PendingIntent pendingIntent = PendingIntent.getActivity(
    context, notificationId, clickIntent,
    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);

Handling in SplashActivity → HomeActivity

// In HomeActivity.onCreate() or onNewIntent()
String notificationType = getIntent().getStringExtra("NOTIFICATION_TYPE");
String notificationPayload = getIntent().getStringExtra("NOTIFICATION_DATA");

if ("NOTIFICATION_TYPE_MESSAGE".equals(notificationType) && notificationPayload != null) {
    FCMMessageDTO dto = new Gson().fromJson(notificationPayload, FCMMessageDTO.class);
    if ("chat".equalsIgnoreCase(dto.getType())) {
        // Navigate to the conversation
        boolean isUser = "user".equals(dto.getReceiverType());
        String uid = isUser ? dto.getSender() : dto.getReceiver();
        // Open MessagesActivity with uid/guid
    }
}

---

9. Reply from notification

The sample apps support inline reply from the notification tray using RemoteInput:

Java:

RemoteInput remoteInput = new RemoteInput.Builder("key_text_reply")
    .setLabel("Reply")
    .build();

NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder(
    R.drawable.ic_reply, "Reply", replyPendingIntent)
    .addRemoteInput(remoteInput)
    .build();

builder.addAction(replyAction);

The reply is received in a BroadcastReceiver:

public class FCMMessageBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
        if (remoteInput != null) {
            CharSequence replyText = remoteInput.getCharSequence("key_text_reply");
            // Send as TextMessage via CometChat.sendMessage()
        }
    }
}

---

10. Permissions

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.INTERNET" />

Request POST_NOTIFICATIONS at runtime on Android 13+:

Java:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, 100);
    }
}

Kotlin:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 100)
    }
}

---

11. Badge count

CometChat sends unreadMessageCount in the payload. Apply it:

String unreadCountStr = message.getData().get("unreadMessageCount");
if (unreadCountStr != null) {
    int count = Integer.parseInt(unreadCountStr);
    ShortcutBadger.applyCount(getApplicationContext(), count);
}

Clear on app open:

ShortcutBadger.removeCount(this);

---

12. Testing the push pipeline

StepHowWhat it verifies
1. FCM aloneFirebase Console → Cloud Messaging → Send test message to your FCM tokenFirebase + google-services.json are correct
2. CometChat → deviceSend a message to the logged-in user from another user (dashboard or another device)Dashboard provider config + token registration
3. Tap deep-linkBackground the app, send a message, tap the notificationPendingIntent routing to correct conversation
4. Reply from notificationPull down notification, type reply, sendBroadcastReceiver + CometChat.sendMessage()
5. Token rotationClear app data, re-open → onNewToken() firesonNewToken() re-registers with CometChat

---

13. Troubleshooting — common silent failures

SymptomLikely causeFix
Token prints but no push arrivesToken registered BEFORE login, or wrong Provider IDCall registerPushToken() AFTER CometChatUIKit.login() resolves. Verify Provider ID matches dashboard.
Foreground: nothing showsNo onMessageReceived() implementation or no notification channelImplement FCMService.onMessageReceived() + create NotificationChannel on API 26+
"Default FirebaseApp is not initialized"google-services.json missing or Gradle plugin not appliedRe-check §2. Clean build: ./gradlew clean
Notification tap doesn't navigatePendingIntent missing extras or wrong ActivityPass NOTIFICATION_TYPE + NOTIFICATION_DATA in Intent extras, handle in target Activity
Works for User A but not User B after logoutunregisterPushToken not called on logoutCall CometChatNotifications.unregisterPushToken() BEFORE CometChatUIKit.logout()
No notifications on Android 13+Missing POST_NOTIFICATIONS runtime permissionRequest at runtime before registering token
Using deprecated registerTokenForPushNotification()Old API from v4Use CometChatNotifications.registerPushToken() with PushPlatforms.FCM_ANDROID
Provider ID mismatchClient uses different Provider ID than dashboardCopy exact Provider ID string from CometChat dashboard → Notifications → Push

---

14. VoIP call push (advanced)

Call pushes (type: "call") require VoIP permissions and CometChatVoIP integration. The flow:

1. onMessageReceived() detects type == "call" 2. Check callAction: "initiated" → show incoming call, "cancelled" / "unanswered" → dismiss 3. Verify VoIP permissions: CometChatVoIP.hasReadPhoneStatePermission(), hasManageOwnCallsPermission(), hasAnswerPhoneCallsPermission() 4. If granted: CometChatVoIP.addNewIncomingCall() with call details in a Bundle

This is an advanced topic — see the voip/ package in the sample apps for the full implementation.

---

Hard rules

  • Use `CometChatNotifications.registerPushToken()` — NOT the deprecated `CometChat.registerTokenForPushNotification()`. The v5 API requires PushPlatforms.FCM_ANDROID and a Provider ID.
  • Register AFTER login. The SDK needs a logged-in user to scope the token.
  • Unregister BEFORE logout. Call CometChatNotifications.unregisterPushToken() before CometChatUIKit.logout().
  • Handle `onNewToken()`. FCM rotates tokens — missing the rotation means push stops working for some users.
  • Create notification channels on API 26+. Without a channel, notifications are silently dropped.
  • Provider ID must match the dashboard. Copy the exact string from CometChat dashboard → Notifications → Push Notifications.
  • Call `CometChat.markAsDelivered()` in `onMessageReceived()`. This updates delivery receipts even when the app is backgrounded.
  • Test on a real device. Emulator FCM behavior differs from real devices.
  • Don't suppress `onMessageReceived()` for foreground messages. CometChat sends data-only pushes — the OS does NOT auto-display them. You must build the notification yourself.

Related skills

Mobile Developmentintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.