{"id":"e5ecb107-d71b-4fa0-9419-3392e7e94d05","shortId":"TjB8MW","kind":"skill","title":"cometchat-android-v5-push","tagline":"Push notifications for CometChat Android — FCM setup, CometChatNotifications API, token registration with PushPlatforms, foreground/background handling, notification channels, reply-from-notification, and tap-to-deep-link.","description":"> **Companion skills:** `cometchat-android-v5-core` covers init and login;\n> `cometchat-android-v5-production` covers production auth and token security.\n\n## Purpose\n\nPush 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.\n\n**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.\n\n---\n\n## Use this skill when\n\n- \"Set up push notifications\"\n- \"Messages don't arrive when app is backgrounded\"\n- \"How do I handle notification taps?\"\n- \"FCM token registration with CometChat\"\n- \"How do I register push token?\"\n- \"CometChatNotifications API\"\n\n## Do not use this skill when\n\n- Setting up init/login → use `cometchat-android-v5-core`\n- Diagnosing non-push issues → use `cometchat-android-v5-troubleshooting`\n- Setting up VoIP calls → see VoIP section in this skill, but call UI is in `cometchat-android-v5-features`\n\n---\n\n## 1. The moving pieces\n\n```\nFCM (Google) → CometChat Dashboard → CometChat Server → Android Client\n```\n\nWhen user A sends a message to user B:\n1. CometChat server receives the message\n2. Looks up B's registered push token (registered via `CometChatNotifications.registerPushToken()`)\n3. Sends push via FCM using the dashboard credentials\n4. B's device receives it via `FirebaseMessagingService.onMessageReceived()`\n5. App builds and displays a notification; tap → deep-link to conversation\n\nAll five steps must work. A broken step is almost always silent — no log, no error, just no notification.\n\n---\n\n## 2. FCM setup\n\n### 2a. Firebase project + google-services.json\n\n1. https://console.firebase.google.com → Add project\n2. Project Overview → Add app → Android → enter your `applicationId`\n3. Download `google-services.json` → place at `app/google-services.json`\n\n### 2b. Gradle dependencies\n\n```groovy\n// project-level build.gradle\nbuildscript {\n    dependencies {\n        classpath 'com.google.gms:google-services:4.4.2'\n    }\n}\n\n// app-level build.gradle\napply plugin: 'com.google.gms.google-services'\n\ndependencies {\n    implementation 'com.google.firebase:firebase-messaging:24.+'\n}\n```\n\n### 2c. Service account JSON (for CometChat dashboard)\n\n1. Firebase Console → Project Settings → Service accounts\n2. Generate new private key → downloads a `.json` file\n3. You'll upload this to the CometChat dashboard in §3\n\n---\n\n## 3. CometChat dashboard — upload FCM credentials\n\n1. https://app.cometchat.com → your app → **Notifications** → **Push Notifications**\n2. **Add Provider** → choose **FCM**\n3. Upload the service account `.json` file from §2c\n4. Save → note the **Provider ID** (e.g., `\"Android-CometChat-Team-Messenger\"`)\n\nYou'll use this Provider ID in your client code when calling `CometChatNotifications.registerPushToken()`.\n\n---\n\n## 4. Token registration API — `CometChatNotifications`\n\nThe v5 SDK uses `CometChatNotifications.registerPushToken()` — **not** the deprecated `CometChat.registerTokenForPushNotification()`.\n\n### API reference\n\n| Method | Signature | Description |\n|---|---|---|\n| `registerPushToken` | `CometChatNotifications.registerPushToken(String token, String platform, String providerId, CallbackListener<String>)` | Register FCM token with CometChat |\n| `unregisterPushToken` | `CometChatNotifications.unregisterPushToken(CallbackListener<String>)` | Unregister token (call before logout) |\n\n### PushPlatforms constants\n\n| Constant | Value | Use for |\n|---|---|---|\n| `PushPlatforms.FCM_ANDROID` | `\"fcm_android\"` | Android FCM push |\n\n### Register token after login\n\n**Java:**\n```java\npublic static void registerFCMToken(CometChat.CallbackListener<String> listener) {\n    FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {\n        if (task.isSuccessful()) {\n            String pushToken = task.getResult();\n            CometChatNotifications.registerPushToken(\n                pushToken,\n                PushPlatforms.FCM_ANDROID,\n                \"YOUR_PROVIDER_ID\",  // from CometChat dashboard §3\n                new CometChat.CallbackListener<String>() {\n                    @Override\n                    public void onSuccess(String s) {\n                        listener.onSuccess(s);\n                    }\n\n                    @Override\n                    public void onError(CometChatException e) {\n                        listener.onError(e);\n                    }\n                }\n            );\n        } else {\n            listener.onError(new CometChatException(\"ERROR\", \"Failed to get FCM token\"));\n        }\n    });\n}\n```\n\n**Kotlin:**\n```kotlin\nfun registerFCMToken(listener: CometChat.CallbackListener<String>) {\n    FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->\n        if (task.isSuccessful) {\n            val pushToken = task.result\n            CometChatNotifications.registerPushToken(\n                pushToken,\n                PushPlatforms.FCM_ANDROID,\n                \"YOUR_PROVIDER_ID\",  // from CometChat dashboard §3\n                object : CometChat.CallbackListener<String?>() {\n                    override fun onSuccess(s: String?) {\n                        listener.onSuccess(s)\n                    }\n\n                    override fun onError(e: CometChatException) {\n                        listener.onError(e)\n                    }\n                }\n            )\n        } else {\n            listener.onError(CometChatException(\"ERROR\", \"Failed to get FCM token\"))\n        }\n    }\n}\n```\n\n### Unregister before logout\n\n**Java:**\n```java\npublic static void unregisterFCMToken(CometChat.CallbackListener<String> listener) {\n    CometChatNotifications.unregisterPushToken(new CometChat.CallbackListener<String>() {\n        @Override\n        public void onSuccess(String s) {\n            listener.onSuccess(s);\n        }\n\n        @Override\n        public void onError(CometChatException e) {\n            listener.onError(e);\n        }\n    });\n}\n```\n\n**Kotlin:**\n```kotlin\nfun unregisterFCMToken(listener: CometChat.CallbackListener<String>) {\n    CometChatNotifications.unregisterPushToken(object : CometChat.CallbackListener<String?>() {\n        override fun onSuccess(s: String?) {\n            listener.onSuccess(s)\n        }\n\n        override fun onError(e: CometChatException) {\n            listener.onError(e)\n        }\n    })\n}\n```\n\n---\n\n## 5. FirebaseMessagingService implementation\n\n### 5a. Service class\n\n**Java:**\n```java\npublic class FCMService extends FirebaseMessagingService {\n    private static String fcmToken;\n\n    @Override\n    public void onNewToken(@NonNull String token) {\n        super.onNewToken(token);\n        fcmToken = token;\n        // Re-register if user is already logged in\n        // (token rotation can happen at any time)\n    }\n\n    @Override\n    public void onMessageReceived(@NonNull RemoteMessage message) {\n        super.onMessageReceived(message);\n        if (message.getData().isEmpty()) return;\n\n        String type = message.getData().get(\"type\");\n        if (\"chat\".equalsIgnoreCase(type)) {\n            handleChatMessage(message);\n        } else if (\"call\".equalsIgnoreCase(type)) {\n            handleCallMessage(message);\n        }\n    }\n\n    private void handleChatMessage(RemoteMessage message) {\n        FCMMessageDTO dto = new Gson().fromJson(\n            new Gson().toJson(message.getData()), FCMMessageDTO.class);\n\n        // Mark as delivered\n        CometChat.markAsDelivered(\n            Long.parseLong(dto.getTag()),\n            dto.getSender(),\n            dto.getReceiverType(),\n            dto.getReceiver()\n        );\n\n        // Build and show notification\n        Intent clickIntent = new Intent(this, SplashActivity.class);\n        FCMMessageNotificationUtils.showNotification(\n            this, dto, clickIntent,\n            \"Reply\", NotificationCompat.CATEGORY_MESSAGE\n        );\n    }\n}\n```\n\n**Kotlin:**\n```kotlin\nclass FCMService : FirebaseMessagingService() {\n    companion object {\n        var fcmToken: String? = null\n            private set\n    }\n\n    override fun onNewToken(token: String) {\n        super.onNewToken(token)\n        fcmToken = token\n    }\n\n    override fun onMessageReceived(message: RemoteMessage) {\n        super.onMessageReceived(message)\n        if (message.data.isEmpty()) return\n\n        when (message.data[\"type\"]?.lowercase()) {\n            \"chat\" -> handleChatMessage(message)\n            \"call\" -> handleCallMessage(message)\n        }\n    }\n\n    private fun handleChatMessage(message: RemoteMessage) {\n        val dto = Gson().fromJson(\n            Gson().toJson(message.data), FCMMessageDTO::class.java)\n\n        CometChat.markAsDelivered(\n            dto.tag!!.toLong(),\n            dto.sender!!,\n            dto.receiverType!!,\n            dto.receiver!!\n        )\n\n        val clickIntent = Intent(this, SplashActivity::class.java)\n        FCMMessageNotificationUtils.showNotification(\n            this, dto, clickIntent,\n            \"Reply\", NotificationCompat.CATEGORY_MESSAGE\n        )\n    }\n}\n```\n\n### 5b. Register in AndroidManifest.xml\n\n```xml\n<service\n    android:name=\".fcm.FCMService\"\n    android:exported=\"false\">\n    <intent-filter>\n        <action android:name=\"com.google.firebase.MESSAGING_EVENT\" />\n    </intent-filter>\n</service>\n```\n\n---\n\n## 6. Push payload schema\n\nCometChat sends data-only FCM messages. The payload fields:\n\n### Chat message payload (`type: \"chat\"`)\n\n| Field | Type | Description |\n|---|---|---|\n| `type` | `String` | Always `\"chat\"` for messages |\n| `sender` | `String` | Sender UID |\n| `senderName` | `String` | Sender display name |\n| `senderAvatar` | `String` | Sender avatar URL |\n| `receiver` | `String` | Receiver UID (user) or GUID (group) |\n| `receiverName` | `String` | Receiver display name |\n| `receiverType` | `String` | `\"user\"` or `\"group\"` |\n| `receiverAvatar` | `String` | Receiver avatar URL |\n| `conversationId` | `String` | Conversation ID |\n| `body` | `String` | Message text |\n| `title` | `String` | Notification title |\n| `tag` | `String` | Message ID (as string) |\n| `unreadMessageCount` | `String` | Unread count (as string) |\n\n### Call payload (`type: \"call\"`)\n\n| Field | Type | Description |\n|---|---|---|\n| `type` | `String` | Always `\"call\"` |\n| `callAction` | `String` | `\"initiated\"`, `\"cancelled\"`, `\"unanswered\"` |\n| `sessionId` | `String` | Call session ID |\n| `callType` | `String` | `\"audio\"` or `\"video\"` |\n| `sender` / `receiver` / `senderName` / etc. | `String` | Same as chat payload |\n\n### DTO classes\n\n**Java:**\n```java\npublic class FCMMessageDTO {\n    @SerializedName(\"conversationId\") private String conversationId;\n    @SerializedName(\"sender\") private String sender;\n    @SerializedName(\"receiver\") private String receiver;\n    @SerializedName(\"receiverName\") private String receiverName;\n    @SerializedName(\"receiverType\") private String receiverType;\n    @SerializedName(\"receiverAvatar\") private String receiverAvatar;\n    @SerializedName(\"tag\") private String tag;\n    @SerializedName(\"body\") private String text;\n    @SerializedName(\"type\") private String type;\n    @SerializedName(\"title\") private String title;\n    @SerializedName(\"senderAvatar\") private String senderAvatar;\n    @SerializedName(\"senderName\") private String senderName;\n    @SerializedName(\"unreadMessageCount\") private String unreadMessageCount;\n    // getters and setters\n}\n```\n\n**Kotlin:**\n```kotlin\nclass FCMMessageDTO {\n    @SerializedName(\"conversationId\") var conversationId: String? = null\n    @SerializedName(\"sender\") var sender: String? = null\n    @SerializedName(\"receiver\") var receiver: String? = null\n    @SerializedName(\"receiverName\") var receiverName: String? = null\n    @SerializedName(\"receiverType\") var receiverType: String? = null\n    @SerializedName(\"receiverAvatar\") var receiverAvatar: String? = null\n    @SerializedName(\"tag\") var tag: String? = null\n    @SerializedName(\"body\") var text: String? = null\n    @SerializedName(\"type\") var type: String? = null\n    @SerializedName(\"title\") var title: String? = null\n    @SerializedName(\"senderAvatar\") var senderAvatar: String? = null\n    @SerializedName(\"senderName\") var senderName: String? = null\n    @SerializedName(\"unreadMessageCount\") var unreadMessageCount: String? = null\n}\n```\n\nParse from `RemoteMessage`:\n```java\nFCMMessageDTO dto = new Gson().fromJson(new Gson().toJson(message.getData()), FCMMessageDTO.class);\n```\n\n---\n\n## 7. Notification channels (API 26+)\n\nCreate channels in your `Application.onCreate()` or before showing the first notification:\n\n**Java:**\n```java\nif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n    NotificationManager manager = getSystemService(NotificationManager.class);\n\n    NotificationChannel messageChannel = new NotificationChannel(\n        \"Message\",                              // channel ID\n        \"Message notification\",                 // channel name\n        NotificationManager.IMPORTANCE_HIGH\n    );\n    manager.createNotificationChannel(messageChannel);\n\n    NotificationChannel callChannel = new NotificationChannel(\n        \"Call\",\n        \"Call notification\",\n        NotificationManager.IMPORTANCE_HIGH\n    );\n    callChannel.setSound(null, null);  // calls use their own ringtone\n    manager.createNotificationChannel(callChannel);\n}\n```\n\n**Kotlin:**\n```kotlin\nif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n    val manager = getSystemService(NotificationManager::class.java)\n\n    val messageChannel = NotificationChannel(\n        \"Message\", \"Message notification\", NotificationManager.IMPORTANCE_HIGH\n    )\n    manager.createNotificationChannel(messageChannel)\n\n    val callChannel = NotificationChannel(\n        \"Call\", \"Call notification\", NotificationManager.IMPORTANCE_HIGH\n    ).apply { setSound(null, null) }\n    manager.createNotificationChannel(callChannel)\n}\n```\n\n---\n\n## 8. Tap-to-deep-link\n\nThe notification click intent routes through `SplashActivity` → `HomeActivity` → correct fragment/conversation.\n\n### Setting up the click intent\n\n**Java:**\n```java\nIntent clickIntent = new Intent(context, SplashActivity.class);\nclickIntent.putExtra(\"NOTIFICATION_TYPE\", \"NOTIFICATION_TYPE_MESSAGE\");\nclickIntent.putExtra(\"NOTIFICATION_DATA\", new Gson().toJson(fcmMessageDTO));\nclickIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);\n\nPendingIntent pendingIntent = PendingIntent.getActivity(\n    context, notificationId, clickIntent,\n    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE\n);\n```\n\n### Handling in SplashActivity → HomeActivity\n\n```java\n// In HomeActivity.onCreate() or onNewIntent()\nString notificationType = getIntent().getStringExtra(\"NOTIFICATION_TYPE\");\nString notificationPayload = getIntent().getStringExtra(\"NOTIFICATION_DATA\");\n\nif (\"NOTIFICATION_TYPE_MESSAGE\".equals(notificationType) && notificationPayload != null) {\n    FCMMessageDTO dto = new Gson().fromJson(notificationPayload, FCMMessageDTO.class);\n    if (\"chat\".equalsIgnoreCase(dto.getType())) {\n        // Navigate to the conversation\n        boolean isUser = \"user\".equals(dto.getReceiverType());\n        String uid = isUser ? dto.getSender() : dto.getReceiver();\n        // Open MessagesActivity with uid/guid\n    }\n}\n```\n\n---\n\n## 9. Reply from notification\n\nThe sample apps support inline reply from the notification tray using `RemoteInput`:\n\n**Java:**\n```java\nRemoteInput remoteInput = new RemoteInput.Builder(\"key_text_reply\")\n    .setLabel(\"Reply\")\n    .build();\n\nNotificationCompat.Action replyAction = new NotificationCompat.Action.Builder(\n    R.drawable.ic_reply, \"Reply\", replyPendingIntent)\n    .addRemoteInput(remoteInput)\n    .build();\n\nbuilder.addAction(replyAction);\n```\n\nThe reply is received in a `BroadcastReceiver`:\n\n```java\npublic class FCMMessageBroadcastReceiver extends BroadcastReceiver {\n    @Override\n    public void onReceive(Context context, Intent intent) {\n        Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);\n        if (remoteInput != null) {\n            CharSequence replyText = remoteInput.getCharSequence(\"key_text_reply\");\n            // Send as TextMessage via CometChat.sendMessage()\n        }\n    }\n}\n```\n\n---\n\n## 10. Permissions\n\n```xml\n<uses-permission android:name=\"android.permission.POST_NOTIFICATIONS\" />\n<uses-permission android:name=\"android.permission.INTERNET\" />\n```\n\nRequest `POST_NOTIFICATIONS` at runtime on Android 13+:\n\n**Java:**\n```java\nif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {\n    if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {\n        requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, 100);\n    }\n}\n```\n\n**Kotlin:**\n```kotlin\nif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {\n    if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {\n        requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 100)\n    }\n}\n```\n\n---\n\n## 11. Badge count\n\nCometChat sends `unreadMessageCount` in the payload. Apply it:\n\n```java\nString unreadCountStr = message.getData().get(\"unreadMessageCount\");\nif (unreadCountStr != null) {\n    int count = Integer.parseInt(unreadCountStr);\n    ShortcutBadger.applyCount(getApplicationContext(), count);\n}\n```\n\nClear on app open:\n```java\nShortcutBadger.removeCount(this);\n```\n\n---\n\n## 12. Testing the push pipeline\n\n| Step | How | What it verifies |\n|---|---|---|\n| 1. FCM alone | Firebase Console → Cloud Messaging → Send test message to your FCM token | Firebase + `google-services.json` are correct |\n| 2. CometChat → device | Send a message to the logged-in user from another user (dashboard or another device) | Dashboard provider config + token registration |\n| 3. Tap deep-link | Background the app, send a message, tap the notification | `PendingIntent` routing to correct conversation |\n| 4. Reply from notification | Pull down notification, type reply, send | `BroadcastReceiver` + `CometChat.sendMessage()` |\n| 5. Token rotation | Clear app data, re-open → `onNewToken()` fires | `onNewToken()` re-registers with CometChat |\n\n---\n\n## 13. Troubleshooting — common silent failures\n\n| Symptom | Likely cause | Fix |\n|---|---|---|\n| Token prints but no push arrives | Token registered BEFORE login, or wrong Provider ID | Call `registerPushToken()` AFTER `CometChatUIKit.login()` resolves. Verify Provider ID matches dashboard. |\n| Foreground: nothing shows | No `onMessageReceived()` implementation or no notification channel | Implement `FCMService.onMessageReceived()` + create `NotificationChannel` on API 26+ |\n| \"Default FirebaseApp is not initialized\" | `google-services.json` missing or Gradle plugin not applied | Re-check §2. Clean build: `./gradlew clean` |\n| Notification tap doesn't navigate | `PendingIntent` missing extras or wrong Activity | Pass `NOTIFICATION_TYPE` + `NOTIFICATION_DATA` in Intent extras, handle in target Activity |\n| Works for User A but not User B after logout | `unregisterPushToken` not called on logout | Call `CometChatNotifications.unregisterPushToken()` BEFORE `CometChatUIKit.logout()` |\n| No notifications on Android 13+ | Missing `POST_NOTIFICATIONS` runtime permission | Request at runtime before registering token |\n| Using deprecated `registerTokenForPushNotification()` | Old API from v4 | Use `CometChatNotifications.registerPushToken()` with `PushPlatforms.FCM_ANDROID` |\n| Provider ID mismatch | Client uses different Provider ID than dashboard | Copy exact Provider ID string from CometChat dashboard → Notifications → Push |\n\n---\n\n## 14. VoIP call push (advanced)\n\nCall pushes (`type: \"call\"`) require VoIP permissions and `CometChatVoIP` integration. The flow:\n\n1. `onMessageReceived()` detects `type == \"call\"`\n2. Check `callAction`: `\"initiated\"` → show incoming call, `\"cancelled\"` / `\"unanswered\"` → dismiss\n3. Verify VoIP permissions: `CometChatVoIP.hasReadPhoneStatePermission()`, `hasManageOwnCallsPermission()`, `hasAnswerPhoneCallsPermission()`\n4. If granted: `CometChatVoIP.addNewIncomingCall()` with call details in a `Bundle`\n\nThis is an advanced topic — see the `voip/` package in the sample apps for the full implementation.\n\n---\n\n## Hard rules\n\n- **Use `CometChatNotifications.registerPushToken()` — NOT the deprecated `CometChat.registerTokenForPushNotification()`.** The v5 API requires `PushPlatforms.FCM_ANDROID` and a Provider ID.\n- **Register AFTER login.** The SDK needs a logged-in user to scope the token.\n- **Unregister BEFORE logout.** Call `CometChatNotifications.unregisterPushToken()` before `CometChatUIKit.logout()`.\n- **Handle `onNewToken()`.** FCM rotates tokens — missing the rotation means push stops working for some users.\n- **Create notification channels on API 26+.** Without a channel, notifications are silently dropped.\n- **Provider ID must match the dashboard.** Copy the exact string from CometChat dashboard → Notifications → Push Notifications.\n- **Call `CometChat.markAsDelivered()` in `onMessageReceived()`.** This updates delivery receipts even when the app is backgrounded.\n- **Test on a real device.** Emulator FCM behavior differs from real devices.\n- **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.","tags":["cometchat","android","push","skills","agent-skills","ai-agent","chat","claude-code","cursor","messaging","nextjs","react"],"capabilities":["skill","source-cometchat","skill-cometchat-android-v5-push","topic-agent-skills","topic-ai-agent","topic-chat","topic-claude-code","topic-cometchat","topic-cursor","topic-messaging","topic-nextjs","topic-react","topic-react-native","topic-ui-kit"],"categories":["cometchat-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cometchat/cometchat-skills/cometchat-android-v5-push","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cometchat/cometchat-skills","source_repo":"https://github.com/cometchat/cometchat-skills","install_from":"skills.sh"}},"qualityScore":"0.463","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 27 github stars · SKILL.md body (21,570 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:04:45.296Z","embedding":null,"createdAt":"2026-05-07T13:05:04.217Z","updatedAt":"2026-05-18T19:04:45.296Z","lastSeenAt":"2026-05-18T19:04:45.296Z","tsv":"'/gradlew':1701 '/src/main/java/com/cometchat/sampleapp/java/fcm':120 '/src/main/java/com/cometchat/sampleapp/kotlin/fcm':129 '1':216,237,310,367,400,1543,1810 '10':1453 '100':1481,1498 '11':1499 '12':1533 '13':1463,1633,1749 '14':1793 '2':243,303,314,374,407,1561,1698,1815 '24':359 '26':1160,1682,1919 '2a':306 '2b':329 '2c':360,420 '3':254,323,383,393,394,412,531,584,1585,1825 '4':263,421,446,1604,1832 '4.4.2':344 '5':271,665,1616 '5a':668 '5b':856 '6':861 '7':1156 '8':1253 '9':1373 'account':362,373,416 'activ':1297,1301,1713,1725 'add':312,317,408 'addoncompletelisten':514 'addremoteinput':1409 'advanc':1797,1845 'almost':293 'alon':1545 'alreadi':699 'alway':294,885,959 'android':3,10,37,46,87,96,182,193,213,226,319,429,494,496,497,524,577,1462,1748,1772,1872 'android-cometchat-team-messeng':428 'androidmanifest.xml':859 'anoth':1574,1578 'api':14,93,169,449,460,1159,1681,1765,1869,1918 'app':69,115,124,148,272,318,346,403,1379,1528,1592,1620,1854,1954 'app-level':345 'app.cometchat.com':401 'app/google-services.json':328 'appli':349,1247,1508,1694 'application.oncreate':1165 'applicationid':322 'arrayof':1495 'arriv':75,146,1647 'audio':973 'auth':51 'auto':1987 'auto-display':1986 'avatar':901,924 'b':236,246,264,1733 'background':68,150,1590,1956 'badg':1500 'behavior':1964 'bodi':930,1028,1107 'boolean':1359 'broadcastreceiv':1420,1426,1614 'broken':290 'build':273,764,1400,1411,1700,1992 'build.gradle':336,348 'build.version':1177,1222 'build.version.sdk':1175,1220,1467,1485 'build.version_codes.tiramisu':1469,1487 'builder.addaction':1412 'buildscript':337 'bundl':1435,1841 'call':199,207,444,484,735,820,950,953,960,968,1202,1203,1210,1242,1243,1656,1738,1741,1795,1798,1801,1814,1821,1837,1895,1943 'callact':961,1817 'callbacklisten':473,481 'callchannel':1199,1216,1240,1252 'callchannel.setsound':1207 'calltyp':971 'cancel':964,1822 'caus':1640 'channel':22,98,1158,1162,1188,1192,1675,1916,1922 'charsequ':1442 'chat':64,728,817,875,879,886,983,1352 'check':1697,1816 'checkselfpermiss':1471,1489 'choos':410 'class':670,674,783,986,990,1062,1423 'class.java':836,848,1228 'classpath':339 'clean':1699,1702 'clear':1302,1526,1619 'click':1261,1272 'clickint':769,777,844,852,1277,1309 'clickintent.putextra':1282,1288 'clickintent.setflags':1295 'client':227,441,1776 'cloud':1548 'code':442 'codes.o':1178,1223 'com.google.firebase':355 'com.google.gms':340 'com.google.gms.google':351 'cometchat':2,9,36,45,86,161,181,192,212,222,224,238,365,390,395,430,478,529,582,865,1502,1562,1632,1789,1938,1976 'cometchat-android-v5-core':35,180 'cometchat-android-v5-features':211 'cometchat-android-v5-production':44 'cometchat-android-v5-push':1 'cometchat-android-v5-troubleshooting':191 'cometchat.callbacklistener':510,533,565,586,620,624,646,649 'cometchat.markasdelivered':758,837,1944 'cometchat.registertokenforpushnotification':459,1866 'cometchat.sendmessage':1452,1615 'cometchatexcept':546,553,599,604,637,662 'cometchatnotif':13,92,168,450 'cometchatnotifications.registerpushtoken':253,445,455,466,521,574,1769,1862 'cometchatnotifications.unregisterpushtoken':480,622,647,1742,1896 'cometchatuikit.login':1659 'cometchatuikit.logout':1744,1898 'cometchatvoip':1806 'cometchatvoip.addnewincomingcall':1835 'cometchatvoip.hasreadphonestatepermission':1829 'common':1635 'companion':33,786 'config':1582 'consol':369,1547 'console.firebase.google.com':311 'constant':488,489 'context':1280,1307,1431,1432 'convers':283,928,1358,1603 'conversationid':926,993,996,1065,1067 'copi':1783,1933 'core':39,184 'correct':91,1267,1560,1602 'count':947,1501,1520,1525 'cover':40,49,78 'creat':1161,1678,1914 'credenti':262,399 'current':1312 'dashboard':223,261,366,391,396,530,583,1576,1580,1665,1782,1790,1932,1939 'data':868,1290,1335,1621,1718,1979 'data-on':867,1978 'deep':31,109,280,1257,1588 'deep-link':279,1587 'default':1683 'deliv':757 'deliveri':1949 'depend':331,338,353 'deprec':458,1762,1865 'descript':464,882,956 'detail':1838 'detect':1812 'devic':266,1563,1579,1961,1968 'diagnos':185 'differ':1778,1965 'dismiss':1824 'display':275,896,914,1988 'doesn':1705 'download':324,379 'drop':1926 'dto':746,776,829,851,985,1147,1345 'dto.getreceiver':763,1368 'dto.getreceivertype':762,1363 'dto.getsender':761,1367 'dto.gettag':760 'dto.gettype':1354 'dto.receiver':842 'dto.receivertype':841 'dto.sender':840 'dto.tag':838 'e':547,549,598,601,638,640,661,664 'e.g':427 'els':550,602,733 'emul':1962 'end':80,82 'end-to-end':79 'enter':320 'equal':1340,1362 'equalsignorecas':729,736,1353 'error':299,554,605 'etc':979 'even':1951 'exact':1784,1935 'extend':676,1425 'extra':1710,1721 'fail':555,606 'failur':1637 'fcm':11,83,157,220,258,304,398,411,475,495,498,558,609,870,1544,1555,1901,1963 'fcmmessagebroadcastreceiv':1424 'fcmmessagedto':745,835,991,1063,1146,1294,1344 'fcmmessagedto.class':754,1155,1350 'fcmmessagenotificationutils.shownotification':774,849 'fcmservic':675,784 'fcmservice.onmessagereceived':1677 'fcmtoken':681,691,789,801 'featur':215 'field':874,880,954 'file':382,418 'fire':1626 'firebas':307,357,368,1546,1557 'firebase-messag':356 'firebaseapp':1684 'firebasemessaging.getinstance':512,566 'firebasemessagingservic':666,677,785 'firebasemessagingservice.onmessagereceived':270 'first':1170 'five':285 'fix':1641 'flow':1809 'foreground':1666,1974 'foreground/background':19,99 'fragment/conversation':1268 'fromjson':749,831,1150,1348 'full':1857 'fun':562,589,596,643,652,659,795,804,824 'generat':375 'get':557,608,725,1514 'getapplicationcontext':1524 'getint':1326,1332 'getstringextra':1327,1333 'getsystemservic':1181,1226 'getter':1057 'gettoken':513 'googl':221,342 'google-servic':341 'google-services.json':309,325,1558,1688 'gradl':330,1691 'grant':1475,1493,1834 'groovi':332 'ground':111 'group':910,920 'gson':748,751,830,832,1149,1152,1292,1347 'guid':909 'handl':20,100,154,1315,1722,1899 'handlecallmessag':738,821 'handlechatmessag':731,742,818,825 'happen':705 'hard':1859 'hasanswerphonecallspermiss':1831 'hasmanageowncallspermiss':1830 'high':1195,1206,1236,1246 'homeact':1266,1318 'homeactivity.oncreate':1321 'id':426,438,527,580,929,941,970,1189,1655,1663,1774,1780,1786,1876,1928 'immut':1314 'implement':354,667,1671,1676,1858 'incom':1820 'init':41 'init/login':178 'initi':963,1687,1818 'inlin':1381 'int':1176,1221,1468,1486,1519 'integer.parseint':1521 'integr':1807 'intent':768,771,845,1262,1273,1276,1279,1433,1434,1438,1720 'intent.flag':1296,1300 'isempti':720 'issu':189 'isus':1360,1366 'java':116,504,505,614,615,671,672,987,988,1145,1172,1173,1274,1275,1319,1389,1390,1421,1464,1465,1510,1530 'json':363,381,417 'key':378,1395,1445 'kotlin':125,560,561,641,642,781,782,1060,1061,1217,1218,1482,1483 'level':335,347 'like':1639 'link':32,110,281,1258,1589 'listen':511,564,621,645 'listener.onerror':548,551,600,603,639,663 'listener.onsuccess':540,593,631,656 'll':385,434 'log':297,700,1570,1885 'logged-in':1569,1884 'login':43,503,1651,1879 'logout':486,613,1735,1740,1894 'long.parselong':759 'look':244 'lowercas':816 'manag':1180,1225 'manager.createnotificationchannel':1196,1215,1237,1251 'manifest.permission.post':1472,1479,1490,1496 'mark':755 'match':1664,1930 'mean':1907 'messag':74,143,233,242,358,715,717,732,739,744,780,806,809,819,822,826,855,871,876,888,932,940,1187,1190,1232,1233,1287,1339,1549,1552,1566,1595,1975 'message.data':814,834 'message.data.isempty':811 'message.getdata':719,724,753,1154,1513 'messagechannel':1184,1197,1230,1238 'messagesact':1370 'messeng':432 'method':462 'mismatch':1775 'miss':1689,1709,1750,1904 'move':218 'must':287,1929,1991 'name':897,915,1193 'navig':1355,1707 'need':1882 'negoti':61 'never':70 'new':376,532,552,623,747,750,770,1148,1151,1185,1200,1278,1291,1298,1346,1393,1403,1477 'non':60,187 'non-negoti':59 'non-push':186 'nonnul':686,713 'note':423 'noth':1667 'notif':7,21,26,57,97,104,119,128,142,155,277,302,404,406,767,936,1157,1171,1191,1204,1234,1244,1260,1283,1285,1289,1328,1334,1337,1376,1385,1458,1473,1480,1491,1497,1598,1607,1610,1674,1703,1715,1717,1746,1752,1791,1915,1923,1940,1942,1994 'notificationchannel':1183,1186,1198,1201,1231,1241,1679 'notificationcompat.action':1401 'notificationcompat.action.builder':1404 'notificationcompat.category':779,854 'notificationid':1308 'notificationmanag':1179,1227 'notificationmanager.class':1182 'notificationmanager.importance':1194,1205,1235,1245 'notificationpayload':1331,1342,1349 'notificationtyp':1325,1341 'null':791,1069,1075,1081,1087,1093,1099,1105,1111,1117,1123,1129,1135,1141,1208,1209,1249,1250,1343,1441,1518 'object':585,648,787 'old':1764 'onerror':545,597,636,660 'onmessagereceiv':712,805,1670,1811,1946,1972 'onnewint':1323 'onnewtoken':685,796,1625,1627,1900 'onrec':1430 'onsuccess':537,590,628,653 'open':1369,1529,1624 'os':1983 'overrid':534,542,588,595,625,633,651,658,682,709,794,803,1427 'overview':316 'packag':1850 'packagemanager.permission':1474,1492 'pars':1142 'pass':1714 'payload':863,873,877,951,984,1507 'pendingint':1304,1305,1599,1708 'pendingintent.flag':1310,1313 'pendingintent.getactivity':1306 'permiss':1454,1754,1804,1828 'piec':219 'pipelin':1537 'place':326 'platform':470 'plugin':350,1692 'post':1457,1751 'print':1643 'privat':377,678,740,792,823,994,999,1004,1009,1014,1019,1024,1029,1034,1039,1044,1049,1054 'product':48,50,63 'project':308,313,315,334,370 'project-level':333 'provid':409,425,437,526,579,1581,1654,1662,1773,1779,1785,1875,1927 'providerid':472 'public':506,535,543,616,626,634,673,683,710,989,1422,1428 'pull':1608 'purpos':55 'push':5,6,56,118,127,141,166,188,249,256,405,499,862,1536,1646,1792,1796,1799,1908,1941,1981 'push-notif':117,126 'pushplatform':18,487 'pushplatforms.fcm':95,493,523,576,1771,1871 'pushtoken':519,522,572,575 'r.drawable.ic':1405 're':694,1623,1629,1696 're-check':1695 're-open':1622 're-regist':693,1628 'real':1960,1967 'receipt':1950 'receiv':240,267,903,905,913,923,977,1003,1006,1077,1079,1417 'receiveravatar':921,1018,1021,1095,1097 'receivernam':911,1008,1011,1083,1085 'receivertyp':916,1013,1016,1089,1091 'refer':461 'regist':165,248,251,474,500,695,857,1630,1649,1759,1877 'registerfcmtoken':509,563 'registerpushtoken':465,1657 'registertokenforpushnotif':1763 'registr':16,159,448,1584 'remoteinput':1388,1391,1392,1410,1436,1440 'remoteinput.builder':1394 'remoteinput.getcharsequence':1444 'remoteinput.getresultsfromintent':1437 'remotemessag':714,743,807,827,1144 'repli':24,102,778,853,1374,1382,1397,1399,1406,1407,1415,1447,1605,1612 'reply-from-notif':23,101 'replyact':1402,1413 'replypendingint':1408 'replytext':1443 'repositori':134 'request':1456,1755 'requestpermiss':1476,1494 'requir':1802,1870 'resolv':1660 'return':721,812 'rington':1214 'rotat':703,1618,1902,1906 'rout':1263,1600 'rule':1860 'runtim':1460,1753,1757 'sampl':114,123,1378,1853 'sample-app-java':113 'sample-app-kotlin':122 'save':422 'schema':864 'scope':1889 'sdk':453,1881 'section':202 'secur':54 'see':200,1847 'send':231,255,866,1448,1503,1550,1564,1593,1613,1977 'sender':889,891,895,900,976,998,1001,1071,1073 'senderavatar':898,1043,1046,1125,1127 'sendernam':893,978,1048,1051,1131,1133 'serializednam':992,997,1002,1007,1012,1017,1022,1027,1032,1037,1042,1047,1052,1064,1070,1076,1082,1088,1094,1100,1106,1112,1118,1124,1130,1136 'server':225,239 'servic':343,352,361,372,415,669 'session':969 'sessionid':966 'set':139,176,196,371,793,1269 'setlabel':1398 'setsound':1248 'setter':1059 'setup':12,84,305 'shortcutbadger.applycount':1523 'shortcutbadger.removecount':1531 'show':766,1168,1668,1819 'signatur':463 'silent':295,1636,1925 'skill':34,77,137,174,205 'skill-cometchat-android-v5-push' 'source-cometchat' 'splashact':847,1265,1317 'splashactivity.class':773,1281 'static':507,617,679 'step':286,291,1538 'stop':1909 'string':467,469,471,518,538,587,592,629,650,655,680,687,722,790,798,884,890,894,899,904,912,917,922,927,931,935,939,943,945,949,958,962,967,972,980,995,1000,1005,1010,1015,1020,1025,1030,1035,1040,1045,1050,1055,1068,1074,1080,1086,1092,1098,1104,1110,1116,1122,1128,1134,1140,1324,1330,1364,1478,1511,1787,1936 'super.onmessagereceived':716,808 'super.onnewtoken':689,799 'support':1380 'suppress':1971 'symptom':1638 'tag':938,1023,1026,1101,1103 'tap':29,107,156,278,1255,1586,1596,1704 'tap-to-deep-link':28,106,1254 'target':1724 'task':515,568,1299 'task.getresult':520 'task.issuccessful':517,570 'task.result':573 'team':431 'test':1534,1551,1957 'text':933,1031,1109,1396,1446 'textmessag':1450 'time':708 'titl':934,937,1038,1041,1119,1121 'tojson':752,833,1153,1293 'token':15,53,158,167,250,447,468,476,483,501,559,610,688,690,692,702,797,800,802,1556,1583,1617,1642,1648,1760,1891,1903 'token.addoncompletelistener':567 'tolong':839 'top':1303 'topic':1846 'topic-agent-skills' 'topic-ai-agent' 'topic-chat' 'topic-claude-code' 'topic-cometchat' 'topic-cursor' 'topic-messaging' 'topic-nextjs' 'topic-react' 'topic-react-native' 'topic-ui-kit' 'tray':1386 'troubleshoot':195,1634 'truth':112 'type':723,726,730,737,815,878,881,883,952,955,957,1033,1036,1113,1115,1284,1286,1329,1338,1611,1716,1800,1813 'ui':208 'uid':892,906,1365 'uid/guid':1372 'uikit':133 'unansw':965,1823 'unread':946 'unreadcountstr':1512,1517,1522 'unreadmessagecount':944,1053,1056,1137,1139,1504,1515 'unregist':482,611,1892 'unregisterfcmtoken':619,644 'unregisterpushtoken':479,1736 'updat':1311,1948 'upload':386,397,413 'url':902,925 'use':89,135,172,179,190,259,435,454,491,1211,1387,1761,1768,1777,1861 'user':229,235,697,907,918,1361,1572,1575,1728,1732,1887,1913 'v4':1767 'v5':4,38,47,88,132,183,194,214,452,1868 'val':571,828,843,1224,1229,1239 'valu':490 'var':788,1066,1072,1078,1084,1090,1096,1102,1108,1114,1120,1126,1132,1138 'verifi':1542,1661,1826 'via':252,257,269,1451 'video':975 'void':508,536,544,618,627,635,684,711,741,1429 'voip':198,201,1794,1803,1827,1849 'wake':71 'without':65,1920 'work':288,1726,1910 'wrong':1653,1712 'xml':860,1455","prices":[{"id":"a69f6b16-3395-46e4-a87d-3abdaa3ada13","listingId":"e5ecb107-d71b-4fa0-9419-3392e7e94d05","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cometchat","category":"cometchat-skills","install_from":"skills.sh"},"createdAt":"2026-05-07T13:05:04.217Z"}],"sources":[{"listingId":"e5ecb107-d71b-4fa0-9419-3392e7e94d05","source":"github","sourceId":"cometchat/cometchat-skills/cometchat-android-v5-push","sourceUrl":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-android-v5-push","isPrimary":false,"firstSeenAt":"2026-05-07T13:05:04.217Z","lastSeenAt":"2026-05-18T19:04:45.296Z"}],"details":{"listingId":"e5ecb107-d71b-4fa0-9419-3392e7e94d05","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cometchat","slug":"cometchat-android-v5-push","github":{"repo":"cometchat/cometchat-skills","stars":27,"topics":["agent-skills","ai-agent","chat","claude-code","cometchat","cursor","messaging","nextjs","react","react-native","ui-kit"],"license":null,"html_url":"https://github.com/cometchat/cometchat-skills","pushed_at":"2026-05-18T05:04:24Z","description":"Add CometChat chat to any React, Next.js, React Native, Angular, Android, iOS, or Flutter project through your AI coding agent. Works with Claude Code, Cursor, Codex, VS Code Copilot, Windsurf, Cline, Kiro, and 50+ more agents.","skill_md_sha":"70bf94063cd896ff1c80ba9f27fc2f17d699659d","skill_md_path":"skills/cometchat-android-v5-push/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-android-v5-push"},"layout":"multi","source":"github","category":"cometchat-skills","frontmatter":{"name":"cometchat-android-v5-push","license":"MIT","description":"Push notifications for CometChat Android — FCM setup, CometChatNotifications API, token registration with PushPlatforms, foreground/background handling, notification channels, reply-from-notification, and tap-to-deep-link.","compatibility":"Android 7.0+; Java 8+; Kotlin 1.8+; com.cometchat:chat-uikit-android:5.x; com.google.firebase:firebase-messaging"},"skills_sh_url":"https://skills.sh/cometchat/cometchat-skills/cometchat-android-v5-push"},"updatedAt":"2026-05-18T19:04:45.296Z"}}