Documentation Index
Fetch the complete documentation index at: https://cometchat-22654f5b-feature-android-campaigns.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
CometChat Campaigns lets you deliver targeted, rich notifications to users via an in-app notification feed. Each notification is a Card Schema JSON — a structured layout rendered natively by the CometChat Cards library.
The SDK provides APIs to fetch feed items, listen for real-time delivery, mark items as read/delivered, report engagement, and retrieve unread counts.
Key Concepts
| Concept | Description |
|---|
| NotificationFeedItem | A single notification in the feed. Contains Card Schema JSON in its content field, a category for filtering, timestamps, and metadata. |
| NotificationCategory | A category label used for filter chips (e.g., “Promotions”, “Updates”). |
| Card Schema JSON | The fully rendered card layout (images, text, buttons) inside NotificationFeedItem.getContent(). Passed directly to the CometChat Cards renderer. |
| PushNotification | Represents a campaign push notification payload received via FCM. |
How Cards Render in the Notification Feed
Each NotificationFeedItem has a content field containing a JSONObject — this is the Card Schema JSON. This JSON is passed directly to the CometChat Cards renderer library (com.cometchat:cards-android).
The rendering flow:
- Fetch feed items via
NotificationFeedRequest
- For each item, extract
item.getContent() — this is the Card Schema JSON
- Convert to string:
item.getContent().toString()
- Pass to the Cards renderer (
CometChatCardView or CometChatCardComposable)
- The renderer produces a native Android view from the JSON
Card Schema JSON Structure
{
"version": "1.0",
"body": [
{ "type": "image", "id": "img_1", "url": "https://...", "height": 200 },
{ "type": "text", "id": "txt_1", "content": "Flash Sale!", "variant": "heading2" },
{ "type": "button", "id": "btn_1", "label": "Shop Now", "action": { "type": "openUrl", "url": "https://..." } }
],
"style": { "background": {"light": "#FFFFFF", "dark": "#1E1E1E"}, "borderRadius": 12, "padding": 16 },
"fallbackText": "Flash Sale! Shop Now: https://..."
}
The body array contains elements (text, image, button, row, column, etc.) rendered top-to-bottom. Interactive elements like buttons emit actions via a callback — the consumer handles navigation, deep links, or API calls.
Retrieve Notification Feed Items
Use NotificationFeedRequest to fetch a paginated list of feed items. Uses cursor-based pagination internally.
Build the Request
NotificationFeedRequest request = new NotificationFeedRequest.NotificationFeedRequestBuilder()
.setLimit(20)
.build();
val request = NotificationFeedRequest.NotificationFeedRequestBuilder()
.setLimit(20)
.build()
Builder Parameters
| Method | Type | Default | Description |
|---|
setLimit(int) | int | 20 | Items per page (max 100) |
setReadState(FeedReadState) | enum | ALL | Filter by READ, UNREAD, or ALL |
setCategory(String) | String | null | Filter by category ID |
setChannelId(String) | String | null | Filter by channel |
setTags(List<String>) | List | null | Filter by tags |
setDateFrom(String) | String | null | ISO 8601 date — items sent on or after |
setDateTo(String) | String | null | ISO 8601 date — items sent on or before |
Fetch Items
request.fetchNext(new CometChat.CallbackListener<List<NotificationFeedItem>>() {
@Override
public void onSuccess(List<NotificationFeedItem> items) {
for (NotificationFeedItem item : items) {
String cardJson = item.getContent().toString();
// Pass cardJson to CometChatCardView or CometChatCardComposable
}
}
@Override
public void onError(CometChatException e) {
Log.e("Feed", "Error: " + e.getMessage());
}
});
request.fetchNext(object : CometChat.CallbackListener<List<NotificationFeedItem>>() {
override fun onSuccess(items: List<NotificationFeedItem>) {
items.forEach { item ->
val cardJson = item.content.toString()
// Pass cardJson to CometChatCardView or CometChatCardComposable
}
}
override fun onError(e: CometChatException) {
Log.e("Feed", "Error: ${e.message}")
}
})
Call fetchNext() repeatedly for pagination. When the server has no more items, subsequent calls return an empty list.
NotificationFeedItem Fields
| Field | Type | Description |
|---|
id | String | Unique item identifier |
category | String | Notification category (e.g., “promotions”) |
content | JSONObject | Card Schema JSON — pass to CometChat Cards renderer |
readAt | Long? | Unix timestamp when read, or null if unread |
deliveredAt | Long? | Unix timestamp when delivered, or null |
sentAt | long | Unix timestamp when sent |
metadata | HashMap | Custom key-value metadata |
tags | List<String> | Tags for filtering |
sender | String | Sender identifier |
receiver | String | Receiver identifier |
receiverType | String | Receiver type |
Retrieve Notification Categories
Use NotificationCategoriesRequest to fetch available categories for filter chips.
NotificationCategoriesRequest categoriesRequest = new NotificationCategoriesRequest
.NotificationCategoriesRequestBuilder()
.setLimit(50)
.build();
categoriesRequest.fetchNext(new CometChat.CallbackListener<List<NotificationCategory>>() {
@Override
public void onSuccess(List<NotificationCategory> categories) {
for (NotificationCategory category : categories) {
Log.d("Feed", "Category: " + category.getName());
}
}
@Override
public void onError(CometChatException e) {
Log.e("Feed", "Error: " + e.getMessage());
}
});
val categoriesRequest = NotificationCategoriesRequest.NotificationCategoriesRequestBuilder()
.setLimit(50)
.build()
categoriesRequest.fetchNext(object : CometChat.CallbackListener<List<NotificationCategory>>() {
override fun onSuccess(categories: List<NotificationCategory>) {
categories.forEach { category ->
Log.d("Feed", "Category: ${category.name}")
}
}
override fun onError(e: CometChatException) {
Log.e("Feed", "Error: ${e.message}")
}
})
NotificationCategory Fields
| Field | Type | Description |
|---|
id | String | Category identifier |
name | String | Display name for filter UI |
description | String | Category description |
appId | String | Associated app ID |
Real-Time Notification Feed Listener
Listen for new feed items arriving via WebSocket. This listener is independent from MessageListener, GroupListener, and CallListener.
CometChat.addNotificationFeedListener("feedListener", new NotificationFeedListener() {
@Override
public void onFeedItemReceived(NotificationFeedItem feedItem) {
Log.d("Feed", "New item: " + feedItem.getId());
String cardJson = feedItem.getContent().toString();
// Insert at top of feed and render
}
});
CometChat.addNotificationFeedListener("feedListener", object : NotificationFeedListener() {
override fun onFeedItemReceived(feedItem: NotificationFeedItem) {
Log.d("Feed", "New item: ${feedItem.id}")
val cardJson = feedItem.content.toString()
// Insert at top of feed and render
}
})
Remove the listener when no longer needed:
CometChat.removeNotificationFeedListener("feedListener");
CometChat.removeNotificationFeedListener("feedListener")
Mark Feed Item as Read
Mark a single item as read. Idempotent — safe to call multiple times.
CometChat.markFeedItemAsRead(feedItem, new CometChat.CallbackListener<Void>() {
@Override
public void onSuccess(Void unused) {
Log.d("Feed", "Marked as read");
}
@Override
public void onError(CometChatException e) {
Log.e("Feed", "Error: " + e.getMessage());
}
});
CometChat.markFeedItemAsRead(feedItem, object : CometChat.CallbackListener<Void?>() {
override fun onSuccess(result: Void?) {
Log.d("Feed", "Marked as read")
}
override fun onError(e: CometChatException) {
Log.e("Feed", "Error: ${e.message}")
}
})
Mark Feed Item as Delivered
Mark a single item as delivered. Idempotent.
CometChat.markFeedItemAsDelivered(feedItem, new CometChat.CallbackListener<Void>() {
@Override
public void onSuccess(Void unused) {
// Success
}
@Override
public void onError(CometChatException e) {
Log.e("Feed", "Error: " + e.getMessage());
}
});
CometChat.markFeedItemAsDelivered(feedItem, object : CometChat.CallbackListener<Void?>() {
override fun onSuccess(result: Void?) { /* Success */ }
override fun onError(e: CometChatException) {
Log.e("Feed", "Error: ${e.message}")
}
})
Report Engagement
Report that a user engaged with a feed item (e.g., viewed, clicked, interacted). Idempotent.
CometChat.reportFeedEngagement(feedItem, "clicked", new CometChat.CallbackListener<Void>() {
@Override
public void onSuccess(Void unused) { }
@Override
public void onError(CometChatException e) { }
});
CometChat.reportFeedEngagement(feedItem, "clicked", object : CometChat.CallbackListener<Void?>() {
override fun onSuccess(result: Void?) { }
override fun onError(e: CometChatException) { }
})
The interactionString parameter is a free-form string describing the engagement (e.g., "viewed", "clicked", "interacted").
Get Unread Count
Fetch the total number of unread notification feed items.
CometChat.getNotificationFeedUnreadCount(new CometChat.CallbackListener<Integer>() {
@Override
public void onSuccess(Integer count) {
Log.d("Feed", "Unread: " + count);
}
@Override
public void onError(CometChatException e) {
Log.e("Feed", "Error: " + e.getMessage());
}
});
CometChat.getNotificationFeedUnreadCount(object : CometChat.CallbackListener<Int>() {
override fun onSuccess(count: Int) {
Log.d("Feed", "Unread: $count")
}
override fun onError(e: CometChatException) {
Log.e("Feed", "Error: ${e.message}")
}
})
Fetch Single Feed Item
Fetch a specific item by ID — useful for deep linking from push notifications.
CometChat.getNotificationFeedItem("item-id-123", new CometChat.CallbackListener<NotificationFeedItem>() {
@Override
public void onSuccess(NotificationFeedItem item) {
String cardJson = item.getContent().toString();
// Render the card
}
@Override
public void onError(CometChatException e) {
Log.e("Feed", "Error: " + e.getMessage());
}
});
CometChat.getNotificationFeedItem("item-id-123", object : CometChat.CallbackListener<NotificationFeedItem>() {
override fun onSuccess(item: NotificationFeedItem) {
val cardJson = item.content.toString()
// Render the card
}
override fun onError(e: CometChatException) {
Log.e("Feed", "Error: ${e.message}")
}
})
Push Notification Tracking
When a campaign push notification arrives via FCM, use these methods to report delivery and click engagement.
Mark Push Notification as Delivered
Call this in your FirebaseMessagingService.onMessageReceived():
PushNotification pushNotification = PushNotification.fromJson(pushPayloadJson);
CometChat.markPushNotificationDelivered(pushNotification, new CometChat.CallbackListener<Void>() {
@Override
public void onSuccess(Void unused) { }
@Override
public void onError(CometChatException e) { }
});
val pushNotification = PushNotification.fromJson(pushPayloadJson)
CometChat.markPushNotificationDelivered(pushNotification, object : CometChat.CallbackListener<Void?>() {
override fun onSuccess(result: Void?) { }
override fun onError(e: CometChatException) { }
})
Mark Push Notification as Clicked
Call this when the user taps the push notification:
CometChat.markPushNotificationClicked(pushNotification, new CometChat.CallbackListener<Void>() {
@Override
public void onSuccess(Void unused) { }
@Override
public void onError(CometChatException e) { }
});
CometChat.markPushNotificationClicked(pushNotification, object : CometChat.CallbackListener<Void?>() {
override fun onSuccess(result: Void?) { }
override fun onError(e: CometChatException) { }
})
PushNotification Fields
| Field | Type | Description |
|---|
id | String | Announcement ID from the push payload |
announcementId | String | Same as id (for clarity) |
campaignId | String? | Campaign ID if from a campaign |
source | String | Always "campaign" for notification feed pushes |
FeedReadState Enum
| Value | Description |
|---|
READ | Only read items |
UNREAD | Only unread items |
ALL | All items (default) |
Rendering Cards
The content field of each NotificationFeedItem is a Card Schema JSON object. To render it natively, use the CometChat Cards library.
Add the Cards Dependency
Add the Cloudsmith repository and the cards library to your project:
// settings.gradle or project-level build.gradle
repositories {
maven { url "https://dl.cloudsmith.io/public/cometchat/cometchat/maven/" }
}
// app/build.gradle
dependencies {
implementation "com.cometchat:cards-android:1.0.0"
}
Requires minSdk 24, Kotlin, and internet permission in your AndroidManifest.xml.
Render a Card from a Feed Item
Jetpack Compose
Traditional View
import com.cometchat.cards.CometChatCardComposable
import com.cometchat.cards.core.CometChatCardThemeMode
@Composable
fun NotificationCard(item: NotificationFeedItem) {
CometChatCardComposable(
cardJson = item.content.toString(),
themeMode = CometChatCardThemeMode.AUTO,
onAction = { event ->
when (event.action) {
is CometChatCardOpenUrlAction -> {
// Open URL in browser
}
is CometChatCardChatWithUserAction -> {
// Navigate to chat
}
}
}
)
}
import com.cometchat.cards.CometChatCardView
import com.cometchat.cards.core.CometChatCardThemeMode
val cardView = CometChatCardView(context)
cardView.setCardSchema(item.content.toString())
cardView.setThemeMode(CometChatCardThemeMode.AUTO)
cardView.setActionCallback { event ->
// Handle action: event.action, event.elementId
}
parentLayout.addView(cardView)
The Cards library is a pure renderer — it does not execute actions. Your code must handle action callbacks (opening URLs, navigating to chats, making API calls, etc.).
Supported Card Actions
When a user taps a button or link inside a card, the action callback receives one of these action types:
| Action Type | Parameters | Description |
|---|
openUrl | url, openIn | Open a URL in browser or webview |
chatWithUser | uid | Navigate to 1:1 chat |
chatWithGroup | guid | Navigate to group chat |
sendMessage | text, receiverUid, receiverGuid | Send a text message |
copyToClipboard | value | Copy text to clipboard |
downloadFile | url, filename | Download a file |
initiateCall | callType (audio/video), uid, guid | Start a call |
apiCall | url, method, headers, body | Make an HTTP request |
customCallback | callbackId, payload | App-specific logic |