From 6e092fd2221ddb5006cd320ee62862e00cc8993f Mon Sep 17 00:00:00 2001 From: Hritika Date: Thu, 25 Jun 2026 16:48:01 +0530 Subject: [PATCH 1/8] Add card streaming events and update documentation for card messages --- sdk/android/v5/ai-agents.mdx | 131 ++++++++++++++++++++++++++++++++++- sdk/android/v5/campaigns.mdx | 50 +++++++++++++ ui-kit/android/v6/events.mdx | 38 ++++++---- 3 files changed, 204 insertions(+), 15 deletions(-) diff --git a/sdk/android/v5/ai-agents.mdx b/sdk/android/v5/ai-agents.mdx index 853da43a7..6e7e16bf5 100644 --- a/sdk/android/v5/ai-agents.mdx +++ b/sdk/android/v5/ai-agents.mdx @@ -25,15 +25,20 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI - Tool Call Arguments - Tool Call End - Tool Call Result -3. One or more assistant reply streams: +3. Zero or more card streams (repeats for each card the agent produces): + - Card Start + - Card + - Card End +4. One or more assistant reply streams: - Text Message Start - Text Message Content (multiple times; token/char streaming) - Text Message End -4. Run Finished +5. Run Finished Notes: - `Run Start` and `Run Finished` are always emitted. - `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run. +- `Card` events (`Card Start` → `Card` → `Card End`) appear only when the agent produces a card, and repeat for each card. - `Text Message` events are always emitted and carry the assistant’s reply incrementally. @@ -72,11 +77,76 @@ Notes: - Tool Call Arguments: Arguments being passed to the tool. - Tool Call End: Tool execution completed. - Tool Call Result: Tool’s output is available. +- Card Start: The agent began producing a card; carries a `cardId` and an `executionText` loading label. +- Card: The full card payload for the given `cardId` is available to render. +- Card End: The card stream for the given `cardId` is complete. - Text Message Start: The agent started composing a reply. - Text Message Content: Streaming content chunks for progressive rendering. - Text Message End: The agent reply is complete. - Run Finished: The run is finalized; persisted messages will follow. +#### Card Streaming Events + +When an agent produces a card, it is delivered through three streaming events on `onAIAssistantEventReceived`. Each event is a subclass of `AIAssistantBaseEvent` — check the concrete type to handle it. + +| Event | Getter | Description | +| ----- | ------ | ----------- | +| `AIAssistantCardStartedEvent` | `getCardId()` | Identifier for the card being generated. | +| | `getExecutionText()` | Loading label shown while the card is built. | +| | `getStreamMessageId()` | Identifier of the streaming message that owns this card. | +| `AIAssistantCardReceivedEvent` | `getCardId()` | Identifier matching the corresponding start event. | +| | `getCard()` | The complete card payload (`JSONObject`) to render. | +| `AIAssistantCardEndedEvent` | `getCardId()` | Signals the card stream for this `cardId` is complete. | + + + + ```java + + CometChat.addAIAssistantListener(LISTENERS_TAG, new CometChat.AIAssistantListener() { + @Override + public void onAIAssistantEventReceived(AIAssistantBaseEvent event) { + if (event instanceof AIAssistantCardStartedEvent) { + AIAssistantCardStartedEvent started = (AIAssistantCardStartedEvent) event; + String cardId = started.getCardId(); + String label = started.getExecutionText(); // e.g. "Building card…" + } else if (event instanceof AIAssistantCardReceivedEvent) { + AIAssistantCardReceivedEvent received = (AIAssistantCardReceivedEvent) event; + String cardId = received.getCardId(); + JSONObject card = received.getCard(); // full card payload + } else if (event instanceof AIAssistantCardEndedEvent) { + AIAssistantCardEndedEvent ended = (AIAssistantCardEndedEvent) event; + // card stream for ended.getCardId() is complete + } + } + }); + + ``` + + + ```kotlin + + CometChat.addAIAssistantListener(LISTENERS_TAG, object : CometChat.AIAssistantListener() { + override fun onAIAssistantEventReceived(event: AIAssistantBaseEvent) { + when (event) { + is AIAssistantCardStartedEvent -> { + val cardId = event.cardId + val label = event.executionText // e.g. "Building card…" + } + is AIAssistantCardReceivedEvent -> { + val cardId = event.cardId + val card = event.card // full card payload (JSONObject) + } + is AIAssistantCardEndedEvent -> { + // card stream for event.cardId is complete + } + } + } + }) + + ``` + + + ### Agentic Messages These events are received via the **`MessageListener`** after the run completes. @@ -128,6 +198,63 @@ These events are received via the **`MessageListener`** after the run completes. } }) + ``` + + + +### AIAssistantMessage Elements + +Once a run completes, the assistant's reply is persisted as an `AIAssistantMessage`. Its content is exposed as an ordered list of blocks via `getElements()`, letting you render text and cards in the exact order the agent produced them. When `getElements()` is `null` or empty, fall back to the plain `getText()` body. + +| Method | Returns | Description | +| ------ | ------- | ----------- | +| `getElements()` | `List` | Ordered content blocks. `null`/empty for plain-text replies. | +| `getText()` | `String` | Plain-text body (fallback when there are no elements). | + +Each `AIAssistantElement` exposes: + +| Method | Returns | Description | +| ------ | ------- | ----------- | +| `getType()` | `String` | Block type — `"text"` or `"card"`. | +| `getData()` | `Object` | The block body (text string, or card payload). | + + + + ```java + + List elements = message.getElements(); + if (elements == null || elements.isEmpty()) { + renderText(message.getText()); + } else { + for (AIAssistantElement element : elements) { + switch (element.getType()) { + case "text": + renderText(String.valueOf(element.getData())); + break; + case "card": + renderCard(element.getData()); + break; + } + } + } + + ``` + + + ```kotlin + + val elements = message.elements + if (elements.isNullOrEmpty()) { + renderText(message.text.orEmpty()) + } else { + for (element in elements) { + when (element.type) { + "text" -> renderText(element.data?.toString().orEmpty()) + "card" -> renderCard(element.data) + } + } + } + ``` \ No newline at end of file diff --git a/sdk/android/v5/campaigns.mdx b/sdk/android/v5/campaigns.mdx index 71fa9efd8..147c3b1af 100644 --- a/sdk/android/v5/campaigns.mdx +++ b/sdk/android/v5/campaigns.mdx @@ -23,6 +23,56 @@ Before using the SDK, set up your channels, categories, templates, and campaigns --- +## Card Messages + +A **Card Message** is a structured, interactive message rendered as a card bubble inside a conversation. Cards are **receive-only** on the SDK: they are created through the **Platform REST API** or the **Dashboard Bubble Builder** and delivered to clients like any other message — the SDK does not send them. + +- **Type:** `com.cometchat.chat.models.CardMessage` +- **Category:** `"card"` (`CometChatConstants.CATEGORY_CARD`) + +### Properties + +| Method | Returns | Description | +| ------ | ------- | ----------- | +| `getCard()` | `JSONObject` | The raw card schema/payload passed to the Cards renderer. | +| `getText()` | `String` | Optional text shown alongside the card. | +| `getFallbackText()` | `String` | Text displayed when the card payload cannot be rendered. | +| `getTags()` | `List` | Tags associated with the message. | + +### Listening for card messages + +To be notified when a card message arrives, implement `onCardMessageReceived` on your `MessageListener`. + + + + ```java + + CometChat.addMessageListener(LISTENER_ID, new CometChat.MessageListener() { + @Override + public void onCardMessageReceived(CardMessage message) { + Log.d(TAG, "Card message received: " + message.getCard()); + } + }); + + ``` + + + ```kotlin + + CometChat.addMessageListener(LISTENER_ID, object : CometChat.MessageListener() { + override fun onCardMessageReceived(message: CardMessage) { + Log.d(TAG, "Card message received: ${message.card}") + } + }) + + ``` + + + +See [Real-time Listeners](/sdk/android/v5/real-time-listeners) for the full `MessageListener` reference. + +--- + ## Rendering Cards The `content` field of each `NotificationFeedItem` is a Card Schema JSON object. To render it natively, use the CometChat Cards library. diff --git a/ui-kit/android/v6/events.mdx b/ui-kit/android/v6/events.mdx index 3baae1188..b4fee3436 100644 --- a/ui-kit/android/v6/events.mdx +++ b/ui-kit/android/v6/events.mdx @@ -445,16 +445,17 @@ fun UserEventsHandler() { ### UI Events -`CometChatEvents.uiEvents` emits `UIEvent` sealed class instances for UI-level actions such as panel visibility and active chat changes. +`CometChatEvents.uiEvents` emits `CometChatUIEvent` sealed class instances for UI-level actions such as panel visibility and active chat changes. **Event types:** | Event | Description | | ----- | ----------- | -| `UIEvent.ShowPanel(id, alignment, view)` | Triggered to show an additional UI panel with custom elements. | -| `UIEvent.HidePanel(id, alignment)` | Triggered to hide a previously shown UI panel. | -| `UIEvent.ActiveChatChanged(id, message, user, group)` | Triggered when the active chat changes. | -| `UIEvent.OpenChat(user, group)` | Triggered to open a chat with a specific user or group. | +| `CometChatUIEvent.ShowPanel(id, alignment, view)` | Triggered to show an additional UI panel with custom elements. | +| `CometChatUIEvent.HidePanel(id, alignment)` | Triggered to hide a previously shown UI panel. | +| `CometChatUIEvent.ActiveChatChanged(id, message, user, group)` | Triggered when the active chat changes. | +| `CometChatUIEvent.OpenChat(user, group)` | Triggered to open a chat with a specific user or group. | +| `CometChatUIEvent.CardActionClicked(message, actionEvent)` | Triggered when a user taps an interactive element (button/link) inside a [card message](/ui-kit/android/v6/card-message) (`CardMessage`) or an AI agent card (`AIAssistantMessage`). `actionEvent` is typed `Any`; cast it to `com.cometchat.cards.actions.CometChatCardActionEvent`. | **Collecting events:** @@ -464,24 +465,31 @@ fun UserEventsHandler() { lifecycleScope.launch { CometChatEvents.uiEvents.collect { event -> when (event) { - is UIEvent.ShowPanel -> { + is CometChatUIEvent.ShowPanel -> { val alignment = event.alignment // Show custom UI panel } - is UIEvent.HidePanel -> { + is CometChatUIEvent.HidePanel -> { val alignment = event.alignment // Hide custom UI panel } - is UIEvent.ActiveChatChanged -> { + is CometChatUIEvent.ActiveChatChanged -> { val user = event.user val group = event.group // React to active chat change } - is UIEvent.OpenChat -> { + is CometChatUIEvent.OpenChat -> { val user = event.user val group = event.group // Navigate to chat with user or group } + is CometChatUIEvent.CardActionClicked -> { + val message = event.message // CardMessage or AIAssistantMessage + val action = event.actionEvent as CometChatCardActionEvent + // action.action, action.elementId, action.cardJson + // Handle the card / agent-card action tap + } + else -> { /* no-op */ } } } } @@ -495,10 +503,12 @@ fun UIEventsHandler() { LaunchedEffect(Unit) { CometChatEvents.uiEvents.collect { event -> when (event) { - is UIEvent.ShowPanel -> { /* Show custom UI panel */ } - is UIEvent.HidePanel -> { /* Hide custom UI panel */ } - is UIEvent.ActiveChatChanged -> { /* React to active chat change */ } - is UIEvent.OpenChat -> { /* Navigate to chat */ } + is CometChatUIEvent.ShowPanel -> { /* Show custom UI panel */ } + is CometChatUIEvent.HidePanel -> { /* Hide custom UI panel */ } + is CometChatUIEvent.ActiveChatChanged -> { /* React to active chat change */ } + is CometChatUIEvent.OpenChat -> { /* Navigate to chat */ } + is CometChatUIEvent.CardActionClicked -> { /* Handle the card agent-card action tap */ } + else -> { /* no-op */ } } } } @@ -507,6 +517,8 @@ fun UIEventsHandler() { +> **About `CardActionClicked`:** The UI Kit renders card bubbles automatically (`CometChatCardBubble`) and emits this event when a user taps an action inside one — so a single subscriber handles every card action across your app. `event.message` is a `CardMessage` for standalone [card messages](/ui-kit/android/v6/card-message) and an `AIAssistantMessage` for cards embedded in AI agent replies. `event.actionEvent` is typed `Any`; import and cast it to `com.cometchat.cards.actions.CometChatCardActionEvent` to read its `action`, `elementId`, and `cardJson`. + --- ## Lifecycle Management From a1af48d08743cf0775ae185fe1a5df8add553f28 Mon Sep 17 00:00:00 2001 From: Hritika Date: Thu, 25 Jun 2026 17:25:01 +0530 Subject: [PATCH 2/8] Add support for loading the last agent conversation in message list --- ui-kit/android/v6/message-list.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-kit/android/v6/message-list.mdx b/ui-kit/android/v6/message-list.mdx index 8661228c1..e8e7b263c 100644 --- a/ui-kit/android/v6/message-list.mdx +++ b/ui-kit/android/v6/message-list.mdx @@ -274,6 +274,7 @@ The component listens to SDK message events internally. No manual setup needed. | `setHideEmptyState(true)` | `hideEmptyState = true` | Hide empty state view | | `setHideErrorState(true)` | `hideErrorState = true` | Hide error state view | | `setStartFromUnreadMessages(true)` | `startFromUnreadMessages = true` | Scroll to first unread on load | +| `setLoadLastAgentConversation(true)` | `loadLastAgentConversation = true` | Load last agent conversation | | `setMessagesRequestBuilder(builder)` | `messagesRequestBuilder = builder` | Custom message request builder | | `setBubbleFactories(list)` | `bubbleFactories = list` | Set custom bubble factories for message types | | `setOnThreadRepliesClick { }` | `onThreadRepliesClick = { }` | Thread reply tap callback | From 774d19618bfbb2e99289987876c4639a9ad5706e Mon Sep 17 00:00:00 2001 From: Hritika Date: Thu, 25 Jun 2026 18:24:10 +0530 Subject: [PATCH 3/8] Add support for receiving Card Messages and update documentation --- sdk/android/v5/receive-messages.mdx | 22 ++++++++++++++++++++++ sdk/android/v5/send-message.mdx | 25 +++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/sdk/android/v5/receive-messages.mdx b/sdk/android/v5/receive-messages.mdx index 22bd67e07..2531099c6 100644 --- a/sdk/android/v5/receive-messages.mdx +++ b/sdk/android/v5/receive-messages.mdx @@ -37,6 +37,11 @@ CometChat.addMessageListener(listenerID, new CometChat.MessageListener() { public void onCustomMessageReceived(CustomMessage customMessage) { Log.d(TAG, "Custom message received successfully: " + customMessage.toString()); } + + @Override + public void onCardMessageReceived(CardMessage cardMessage) { + Log.d(TAG, "Card message received successfully: " + cardMessage.toString()); + } }); ``` @@ -58,6 +63,10 @@ CometChat.addMessageListener(listenerID, object : MessageListener() { override fun onCustomMessageReceived(customMessage: CustomMessage) { Log.d(TAG, "Custom message received successfully: $customMessage") } + + override fun onCardMessageReceived(cardMessage: CardMessage) { + Log.d(TAG, "Card message received successfully: $cardMessage") + } }) ``` @@ -98,6 +107,19 @@ As a sender, you will not receive your own message in a real-time message event. +### Receiving Card Messages + +`onCardMessageReceived(CardMessage cardMessage)` is triggered when a card message (category `"card"`) is received. Card Messages are **receive-only** — they are created via the Platform REST API or the Dashboard Bubble Builder, not sent from the SDK (see [Send a Message → Card Message](/sdk/android/v5/send-message#card-message)). + +The `CardMessage` payload exposes: + +| Method | Returns | Description | +| ------ | ------- | ----------- | +| `getCard()` | `JSONObject` | The raw card schema/payload to render. | +| `getText()` | `String` | Optional text shown alongside the card. | +| `getFallbackText()` | `String` | Text shown when the card payload cannot be rendered. | +| `getTags()` | `List` | Tags associated with the message. | + ## Missed Messages *In other words, as a recipient, how do I receive messages that I missed when my app was not running?* diff --git a/sdk/android/v5/send-message.mdx b/sdk/android/v5/send-message.mdx index f3c86b1b5..2cd895751 100644 --- a/sdk/android/v5/send-message.mdx +++ b/sdk/android/v5/send-message.mdx @@ -1151,3 +1151,28 @@ CometChat.sendCustomMessage(customMessage, object : CallbackListener + +## Card Message + +A **Card Message** is a structured, interactive message rendered as a card bubble. It belongs to the `"card"` category (`CometChatConstants.CATEGORY_CARD`) and carries a block of card schema JSON that an external renderer (the CometChat Cards library) draws. + + + +**Card Messages cannot be sent through the SDK.** The `CardMessage` class is **receive-only** — it has no public constructor and the SDK exposes no `sendCardMessage()` API. Card Messages are created server-side and delivered to clients like any other message. + +To send a Card Message, use the **Platform REST API** or the **Dashboard Bubble Builder**. See the [Send a Message REST API reference](https://api-explorer.cometchat.com/reference/sends-a-message) for the message creation flow. + + + +### CardMessage structure + +`CardMessage` extends `BaseMessage`, so it exposes the standard message fields (`getId()`, `getSender()`, `getReceiverUid()`, `getSentAt()`, `getCategory()` = `"card"`, etc.) in addition to the card-specific fields below: + +| Method | Returns | Description | +| ------ | ------- | ----------- | +| `getCard()` | `JSONObject` | The raw card schema/payload passed to the Cards renderer (version, body, style, fallbackText, etc.). | +| `getText()` | `String` | Optional text shown alongside the card. | +| `getFallbackText()` | `String` | Text displayed when the card payload cannot be rendered. | +| `getTags()` | `List` | Tags associated with the message. | + +To handle incoming Card Messages on the client, implement [`onCardMessageReceived`](/sdk/android/v5/receive-messages#real-time-messages) on your `MessageListener`. From 54b9ac2e80a524641d26b3b9eeba9d8d391653d2 Mon Sep 17 00:00:00 2001 From: Hritika Date: Thu, 25 Jun 2026 18:46:06 +0530 Subject: [PATCH 4/8] Update documentation for Card Messages and remove references to Interactive Messages --- docs.json | 1 - .../v5/message-structure-and-hierarchy.mdx | 14 ++---- sdk/android/v5/send-message.mdx | 47 ++++++++++++++----- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/docs.json b/docs.json index f2ad5f2c5..1ecc8635b 100644 --- a/docs.json +++ b/docs.json @@ -4152,7 +4152,6 @@ "sdk/android/v5/typing-indicators", "sdk/android/v5/delivery-read-receipts", "sdk/android/v5/transient-messages", - "sdk/android/v5/interactive-messages", "sdk/android/v5/mentions", "sdk/android/v5/reactions" ] diff --git a/sdk/android/v5/message-structure-and-hierarchy.mdx b/sdk/android/v5/message-structure-and-hierarchy.mdx index f61945388..0d68bf88a 100644 --- a/sdk/android/v5/message-structure-and-hierarchy.mdx +++ b/sdk/android/v5/message-structure-and-hierarchy.mdx @@ -33,19 +33,11 @@ A message belonging to the category `message` can be classified into either 1 of In the case of messages that belong to the `custom` category, there are no predefined types. Custom messages can be used by developers to send messages that do not fit in the default category and types provided by CometChat. For messages with the category `custom`, the developers can set their own type to uniquely identify the custom message. A very good example of a custom message would be the sharing of location co-ordinates. In this case, the developer can decide to use the custom message with type set to `location`. -## Interactive +## Card -An `InteractiveMessage` is a specialized object that encapsulates an interactive unit within a chat message, such as an embedded form that users can fill out directly within the chat interface. This enhances user engagement by making the chat experience more interactive and responsive to user input. +A message belonging to the `card` category is a `CardMessage` — a structured, interactive message rendered as a card bubble. The `card` category has no predefined types; the layout is described by a block of card schema JSON that the CometChat Cards library renders. -1. form- for interactive form -2. card- for interactive card -3. customInteractive- for custom interaction messages - - - -to know about Interactive messages please [click here](/sdk/android/v5/interactive-messages) - - +Card Messages are **receive-only**: they are created via the Platform REST API or the Dashboard Bubble Builder and delivered to clients like any other message. See [Send a Message](/sdk/android/v5/send-message#card-message) for the `CardMessage` fields and [Receive Messages](/sdk/android/v5/receive-messages#real-time-messages) for handling incoming card messages. ## Action diff --git a/sdk/android/v5/send-message.mdx b/sdk/android/v5/send-message.mdx index 2cd895751..a041cb425 100644 --- a/sdk/android/v5/send-message.mdx +++ b/sdk/android/v5/send-message.mdx @@ -4,12 +4,12 @@ title: "Send A Message" -Using CometChat, you can send three types of messages: +Using CometChat, you can send four types of messages: 1. A [Text Message](/sdk/android/v5/send-message#text-message), the most common and standard message type. 2. A [Media Message](/sdk/android/v5/send-message#media-message), for sending photos, videos and files. 3. A [Custom Message](/sdk/android/v5/send-message#custom-message), for sending completely custom data using JSON structures. -4. A [Interactive Messages](/sdk/android/v5/interactive-messages), for sending end-user interactive messages of type form, card and custom Interactive +4. A [Card Message](/sdk/android/v5/send-message#card-message), a structured, interactive card message (receive-only — created via the REST API). You can also send metadata along with a text or media message. Think, for example, if you'd want to share the user's location with every message, you can use the metadata field. @@ -1146,33 +1146,54 @@ CometChat.sendCustomMessage(customMessage, object : CallbackListener +## Card Message + +*In other words, as a sender, how do I send a card message?* + +A `CardMessage` is a structured, interactive message rendered as a card bubble. It belongs to the `card` category and carries a block of card schema JSON that the CometChat Cards library draws. + -It is also possible to send interactive messages from CometChat , to know more [click here](/sdk/android/v5/interactive-messages) +**Card Messages cannot be sent through the SDK.** The `CardMessage` class is **receive-only** — it has no public constructor and the SDK exposes no `sendCardMessage()` method. Card Messages are created server-side via the **Platform REST API** or the **Dashboard Bubble Builder**, and delivered to clients like any other message. - +To create and send a Card Message, use the REST API. See the [Send Message REST API reference](https://www.cometchat.com/docs/rest-api/messages/send-message) for the message creation flow. -## Card Message + -A **Card Message** is a structured, interactive message rendered as a card bubble. It belongs to the `"card"` category (`CometChatConstants.CATEGORY_CARD`) and carries a block of card schema JSON that an external renderer (the CometChat Cards library) draws. +On the receiving end, the `CardMessage` object gives you access to the card payload and its related fields. - + + +```java +JSONObject card = cardMessage.getCard(); // raw card schema/payload +String text = cardMessage.getText(); // optional text shown alongside the card +String fallbackText = cardMessage.getFallbackText(); // shown when the card cannot be rendered +List tags = cardMessage.getTags(); // tags associated with the message +``` -**Card Messages cannot be sent through the SDK.** The `CardMessage` class is **receive-only** — it has no public constructor and the SDK exposes no `sendCardMessage()` API. Card Messages are created server-side and delivered to clients like any other message. + -To send a Card Message, use the **Platform REST API** or the **Dashboard Bubble Builder**. See the [Send a Message REST API reference](https://api-explorer.cometchat.com/reference/sends-a-message) for the message creation flow. + +```kotlin +val card = cardMessage.card // raw card schema/payload +val text = cardMessage.text // optional text shown alongside the card +val fallbackText = cardMessage.fallbackText // shown when the card cannot be rendered +val tags = cardMessage.tags // tags associated with the message +``` - + -### CardMessage structure + -`CardMessage` extends `BaseMessage`, so it exposes the standard message fields (`getId()`, `getSender()`, `getReceiverUid()`, `getSentAt()`, `getCategory()` = `"card"`, etc.) in addition to the card-specific fields below: +The `CardMessage` class provides the following methods: | Method | Returns | Description | | ------ | ------- | ----------- | -| `getCard()` | `JSONObject` | The raw card schema/payload passed to the Cards renderer (version, body, style, fallbackText, etc.). | +| `getCard()` | `JSONObject` | The raw card schema/payload passed to the Cards renderer. | | `getText()` | `String` | Optional text shown alongside the card. | | `getFallbackText()` | `String` | Text displayed when the card payload cannot be rendered. | | `getTags()` | `List` | Tags associated with the message. | +`CardMessage` extends `BaseMessage`, so it also exposes the standard message fields (`getId()`, `getSender()`, `getReceiverUid()`, `getSentAt()`, `getCategory()` = `card`, etc.). + To handle incoming Card Messages on the client, implement [`onCardMessageReceived`](/sdk/android/v5/receive-messages#real-time-messages) on your `MessageListener`. From 71b1829209a37bd8d50396ae04a95281f805bb2e Mon Sep 17 00:00:00 2001 From: Hritika Date: Thu, 25 Jun 2026 19:50:33 +0530 Subject: [PATCH 5/8] Update documentation for Card Messages and remove references to Interactive Messages --- .../v5/message-structure-and-hierarchy.mdx | 9 ++- sdk/android/v5/receive-messages.mdx | 77 +++++++++++++++++++ sdk/android/v5/send-message.mdx | 77 +++++++++++++++++++ 3 files changed, 159 insertions(+), 4 deletions(-) diff --git a/sdk/android/v5/message-structure-and-hierarchy.mdx b/sdk/android/v5/message-structure-and-hierarchy.mdx index 0d68bf88a..87dd44d01 100644 --- a/sdk/android/v5/message-structure-and-hierarchy.mdx +++ b/sdk/android/v5/message-structure-and-hierarchy.mdx @@ -7,15 +7,16 @@ title: "Message Structure And Hierarchy" The below diagram helps you better understand the various message categories and types that a CometChat message can belong to. - + -As you can see in the above diagram, every message belongs to a particular category. A message can belong to either one of the 4 categories +As you can see in the above diagram, every message belongs to a particular category. A message can belong to either one of the 5 categories 1. Message 2. Custom -3. Action -4. Call +3. Card +4. Action +5. Call Each category can be further be classified into types. diff --git a/sdk/android/v5/receive-messages.mdx b/sdk/android/v5/receive-messages.mdx index 2531099c6..eb88396d2 100644 --- a/sdk/android/v5/receive-messages.mdx +++ b/sdk/android/v5/receive-messages.mdx @@ -120,6 +120,83 @@ The `CardMessage` payload exposes: | `getFallbackText()` | `String` | Text shown when the card payload cannot be rendered. | | `getTags()` | `List` | Tags associated with the message. | +### Render a Card Message + +The received `CardMessage` carries raw card-schema JSON in `getCard()`. To draw it natively, use the **CometChat Cards** renderer library (`com.cometchat:cards-android`) — the same renderer the UI Kit's card bubble wraps. It is a pure renderer: you hand it the card JSON and an action callback, and you own all action behavior. + +#### Add the Cards dependency + +```groovy +// settings.gradle (or project-level build.gradle) +repositories { + maven { url "https://dl.cloudsmith.io/public/cometchat/cometchat/maven/" } +} +``` + +```groovy +// app/build.gradle +dependencies { + implementation "com.cometchat:cards-android:1.0.0" +} +``` + + +Requires `minSdk 24`, Kotlin, and the internet permission in your `AndroidManifest.xml`. + + +#### Render the card + +Pass the card JSON (`cardMessage.getCard().toString()`) to the renderer and handle actions through the callback. + + + +```kotlin +import com.cometchat.cards.CometChatCardComposable +import com.cometchat.cards.models.CometChatCardThemeMode +import com.cometchat.cards.models.* + +@Composable +fun CardMessageContent(cardMessage: CardMessage) { + CometChatCardComposable( + cardJson = cardMessage.card.toString(), + themeMode = CometChatCardThemeMode.AUTO, // follows system light/dark + onAction = { event -> + when (val action = event.action) { + is CometChatCardOpenUrlAction -> openUrl(action.url) + is CometChatCardChatWithUserAction -> openUserChat(action.uid) + is CometChatCardCopyToClipboardAction -> copyToClipboard(action.value) + is CometChatCardCustomCallbackAction -> handleCallback(action.callbackId, action.payload) + else -> { /* handle the remaining action types */ } + } + } + ) +} +``` + + +```kotlin +import com.cometchat.cards.CometChatCardView +import com.cometchat.cards.models.CometChatCardThemeMode + +val cardView = CometChatCardView(context) +cardView.setCardSchema(cardMessage.card.toString()) +cardView.setThemeMode(CometChatCardThemeMode.AUTO) +cardView.setActionCallback { event -> + // event.action -> one of the 9 tagged action types + // event.elementId -> id of the tapped button/link + handleCardAction(event.action) +} +parentLayout.addView(cardView) +``` + + + + +The Cards library is a **pure renderer** — it never executes actions, it only emits them through the callback. You own all behavior (opening URLs, navigating to chats, API calls, etc.). The 9 action types (`CometChatCardOpenUrlAction`, `CometChatCardChatWithUserAction`, …) live in `com.cometchat.cards.models`, and `event` is a `com.cometchat.cards.actions.CometChatCardActionEvent` exposing `action` and `elementId`. + +When rendering directly, fallback is your responsibility: if the card JSON is empty or invalid, fall back to `cardMessage.getFallbackText()` (then `getText()`). + + ## Missed Messages *In other words, as a recipient, how do I receive messages that I missed when my app was not running?* diff --git a/sdk/android/v5/send-message.mdx b/sdk/android/v5/send-message.mdx index a041cb425..e668c923a 100644 --- a/sdk/android/v5/send-message.mdx +++ b/sdk/android/v5/send-message.mdx @@ -1197,3 +1197,80 @@ The `CardMessage` class provides the following methods: `CardMessage` extends `BaseMessage`, so it also exposes the standard message fields (`getId()`, `getSender()`, `getReceiverUid()`, `getSentAt()`, `getCategory()` = `card`, etc.). To handle incoming Card Messages on the client, implement [`onCardMessageReceived`](/sdk/android/v5/receive-messages#real-time-messages) on your `MessageListener`. + +### Render a Card Message + +A `CardMessage` carries raw card-schema JSON in `getCard()`. To draw it natively, use the **CometChat Cards** renderer library (`com.cometchat:cards-android`) — the same renderer the UI Kit's card bubble wraps. It is a pure renderer: you hand it the card JSON and an action callback, and you own all action behavior. + +#### Add the Cards dependency + +```groovy +// settings.gradle (or project-level build.gradle) +repositories { + maven { url "https://dl.cloudsmith.io/public/cometchat/cometchat/maven/" } +} +``` + +```groovy +// app/build.gradle +dependencies { + implementation "com.cometchat:cards-android:1.0.0" +} +``` + + +Requires `minSdk 24`, Kotlin, and the internet permission in your `AndroidManifest.xml`. + + +#### Render the card + +Pass the card JSON (`cardMessage.getCard().toString()`) to the renderer and handle actions through the callback. + + + +```kotlin +import com.cometchat.cards.CometChatCardComposable +import com.cometchat.cards.models.CometChatCardThemeMode +import com.cometchat.cards.models.* + +@Composable +fun CardMessageContent(cardMessage: CardMessage) { + CometChatCardComposable( + cardJson = cardMessage.card.toString(), + themeMode = CometChatCardThemeMode.AUTO, // follows system light/dark + onAction = { event -> + when (val action = event.action) { + is CometChatCardOpenUrlAction -> openUrl(action.url) + is CometChatCardChatWithUserAction -> openUserChat(action.uid) + is CometChatCardCopyToClipboardAction -> copyToClipboard(action.value) + is CometChatCardCustomCallbackAction -> handleCallback(action.callbackId, action.payload) + else -> { /* handle the remaining action types */ } + } + } + ) +} +``` + + +```kotlin +import com.cometchat.cards.CometChatCardView +import com.cometchat.cards.models.CometChatCardThemeMode + +val cardView = CometChatCardView(context) +cardView.setCardSchema(cardMessage.card.toString()) +cardView.setThemeMode(CometChatCardThemeMode.AUTO) +cardView.setActionCallback { event -> + // event.action -> one of the 9 tagged action types + // event.elementId -> id of the tapped button/link + handleCardAction(event.action) +} +parentLayout.addView(cardView) +``` + + + + +The Cards library is a **pure renderer** — it never executes actions, it only emits them through the callback. You own all behavior (opening URLs, navigating to chats, API calls, etc.). The 9 action types (`CometChatCardOpenUrlAction`, `CometChatCardChatWithUserAction`, …) live in `com.cometchat.cards.models`, and `event` is a `com.cometchat.cards.actions.CometChatCardActionEvent` exposing `action` and `elementId`. + +When rendering directly, fallback is your responsibility: if the card JSON is empty or invalid, fall back to `cardMessage.getFallbackText()` (then `getText()`). + From c51514abbc6f6ca82ee72dc9a19dc706b4d4e0aa Mon Sep 17 00:00:00 2001 From: Hritika Date: Thu, 25 Jun 2026 20:05:04 +0530 Subject: [PATCH 6/8] Add SVG diagram for message structure hierarchy --- images/message-structure-hierarchy-card.svg | 116 ++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 images/message-structure-hierarchy-card.svg diff --git a/images/message-structure-hierarchy-card.svg b/images/message-structure-hierarchy-card.svg new file mode 100644 index 000000000..49472b390 --- /dev/null +++ b/images/message-structure-hierarchy-card.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Category + Type + Type + Type + Action + status + + + + + + + Message + + + + message + + + + custom + + + + action + + + + call + + + + card + + + + + + + text + image + audio + video + file + + + groupMember + joined + left + kicked + banned + unbanned + added + scopeChanged + + + message + edited + deleted + + + audio + video + + + initiated + ongoing + rejected + cancel + busy + unanswered + ended + + From 42dc10bd6eccdf1049689d0226efdf4eb951fac7 Mon Sep 17 00:00:00 2001 From: Hritika Date: Fri, 26 Jun 2026 13:22:28 +0530 Subject: [PATCH 7/8] Fix grammar and punctuation in documentation for agent run lifecycle and message flow --- docs.json | 4 + sdk/android/ai-agents.mdx | 8 +- sdk/android/v5/ai-agents.mdx | 8 +- sdk/android/v5/interactive-messages.mdx | 264 ------------------------ sdk/android/v5/send-message.mdx | 7 +- ui-kit/android/v6/events.mdx | 4 +- 6 files changed, 19 insertions(+), 276 deletions(-) delete mode 100644 sdk/android/v5/interactive-messages.mdx diff --git a/docs.json b/docs.json index 1ecc8635b..580841b1e 100644 --- a/docs.json +++ b/docs.json @@ -8347,6 +8347,10 @@ "source": "/fundamentals/limits", "destination": "/rest-api/rate-limits" }, + { + "source": "/sdk/android/v5/interactive-messages", + "destination": "/sdk/android/v5/send-message" + }, { "source": "/sdk/javascript/interactive-messages", "destination": "/sdk/javascript/send-message" diff --git a/sdk/android/ai-agents.mdx b/sdk/android/ai-agents.mdx index 827ac5133..d4f853f9d 100644 --- a/sdk/android/ai-agents.mdx +++ b/sdk/android/ai-agents.mdx @@ -31,7 +31,7 @@ Currently, an Agent only responds to **Text Messages**. ## Agent Run Lifecycle and Message Flow -This section explains how a user’s text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval. +This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval. - A user sends a text message to an Agent. - The platform starts a run and streams real-time events via the **`AIAssistantListener`**. - After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**. @@ -54,7 +54,7 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI Notes: - `Run Start` and `Run Finished` are always emitted. - `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run. -- `Text Message` events are always emitted and carry the assistant’s reply incrementally. +- `Text Message` events are always emitted and carry the assistant's reply incrementally. @@ -87,11 +87,11 @@ Notes: #### Event descriptions -- Run Start: A new run has begun for the user’s message. +- Run Start: A new run has begun for the user's message. - Tool Call Start: The agent decided to invoke a tool. - Tool Call Arguments: Arguments being passed to the tool. - Tool Call End: Tool execution completed. -- Tool Call Result: Tool’s output is available. +- Tool Call Result: Tool's output is available. - Text Message Start: The agent started composing a reply. - Text Message Content: Streaming content chunks for progressive rendering. - Text Message End: The agent reply is complete. diff --git a/sdk/android/v5/ai-agents.mdx b/sdk/android/v5/ai-agents.mdx index 6e7e16bf5..ec86c0ae9 100644 --- a/sdk/android/v5/ai-agents.mdx +++ b/sdk/android/v5/ai-agents.mdx @@ -11,7 +11,7 @@ AI Agents enable intelligent, automated interactions within your application. Th ## Agent Run Lifecycle and Message Flow -This section explains how a user’s text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval. +This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval. - A user sends a text message to an Agent. - The platform starts a run and streams real-time events via the **`AIAssistantListener`**. - After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**. @@ -39,7 +39,7 @@ Notes: - `Run Start` and `Run Finished` are always emitted. - `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run. - `Card` events (`Card Start` → `Card` → `Card End`) appear only when the agent produces a card, and repeat for each card. -- `Text Message` events are always emitted and carry the assistant’s reply incrementally. +- `Text Message` events are always emitted and carry the assistant's reply incrementally. @@ -72,11 +72,11 @@ Notes: #### Event descriptions -- Run Start: A new run has begun for the user’s message. +- Run Start: A new run has begun for the user's message. - Tool Call Start: The agent decided to invoke a tool. - Tool Call Arguments: Arguments being passed to the tool. - Tool Call End: Tool execution completed. -- Tool Call Result: Tool’s output is available. +- Tool Call Result: Tool's output is available. - Card Start: The agent began producing a card; carries a `cardId` and an `executionText` loading label. - Card: The full card payload for the given `cardId` is available to render. - Card End: The card stream for the given `cardId` is complete. diff --git a/sdk/android/v5/interactive-messages.mdx b/sdk/android/v5/interactive-messages.mdx deleted file mode 100644 index d6f468c0e..000000000 --- a/sdk/android/v5/interactive-messages.mdx +++ /dev/null @@ -1,264 +0,0 @@ ---- -title: "Interactive Messages" ---- - - - -An `InteractiveMessage` is a specialized object that encapsulates an interactive unit within a chat message, such as an embedded form that users can fill out directly within the chat interface. This enhances user engagement by making the chat experience more interactive and responsive to user input. - -### InteractiveMessage - -`InteractiveMessage` is a chat message with embedded interactive content. It can contain various properties: - -| Parameter | Description | | -| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -| `receiverId` | The UID or GUID of the recipient | Required | -| `receiverType` | The type of the receiver to whom the message is to be sent. Options: `CometChatConstants.RECEIVER_TYPE_USER` (user) or `CometChatConstants.RECEIVER_TYPE_GROUP` (group) | Required | -| `messageType` | The type of the message that needs to be sent | Required | -| `interactiveData` | A JSONObject holding structured data for the interactive element. | Required | -| `allowSenderInteraction` | A boolean determining whether the message sender can interact with the message. Default is set to false. | | -| `interactionGoal` | An `InteractionGoal` object encapsulating the intended outcome of interacting with the `InteractiveMessage`. Default is set to none. | | - -### Interaction - -An Interaction represents a user action involved with an `InteractiveMessage`. It includes: - -* `elementId`: An identifier for a specific interactive element. -* `interactedAt`: A timestamp indicating when the interaction occurred. - -### Mark as Interacted - -This method marks a message as interacted by identifying it with the provided Id. it also logs the interactive element associated with the interaction. - - - -```java -int messageId = 1; -String elementId = "elementId"; -CometChat.markAsInteracted(messageId, elementId, new CometChat.CallbackListener() { - @Override - public void onSuccess(Void unused) { - - } - - @Override - public void onError(CometChatException e) { - - } -}); -``` - - - - -```kotlin -val messageId = 1 -val elementId = "elementId" - -CometChat.markAsInteracted(messageId, elementId, object : CometChat.CallbackListener() { - override fun onSuccess(unused: Void?) { - - } - - override fun onError(e: CometChatException) { - - } -}) -``` - - - - - -### Goal Completion - -A key feature of `InteractiveMessage` is checking whether a user's interactions with the message meet the defined `InteractionGoal` - -You would be tracking every interaction users perform on an `InteractiveMessage` (captured as `Interaction` objects) and comparing those with the defined `InteractionGoal`. The completion of a goal can vary depending on the goal type: - -| Goals | Description | Keys | -| ---------------------------- | ---------------------------------------------------------------------- | --------------------------------------------- | -| Any Interaction | The goal is considered completed if there is at least one interaction. | CometChatConstants.INTERACTION\_TYPE\_ANY | -| Any of Specific Interactions | The goal is achieved if any of the specified interactions occurred. | CometChatConstants.INTERACTION\_TYPE\_ANY\_OF | -| All of Specific Interactions | The goal is completed when all specified interactions occur. | CometChatConstants.INTERACTION\_TYPE\_ALL\_OF | -| None | The goal is never completed. | CometChatConstants.INTERACTION\_TYPE\_NONE | - -### InteractionGoal - -The `InteractionGoal` represents the desired outcome of an interaction with an InteractiveMessage. It includes: - -* `elementIds`: A list of identifiers for the interactive elements. -* `type`: The type of interaction goal from the `CometChatConstants`. - -### Sending InteractiveMessages - -The `InteractiveMessage` can be sent using the `sendInteractiveMessage` method of the CometChat class. The method requires an `InteractiveMessage` object and a `CallbackListener` for handling the response. - -Here is an example of how to use it: - - - -```java -JSONObject interactiveData = new JSONObject(); -try { - interactiveData.put("title", "Demo Form"); - JSONArray jsonArray = new JSONArray(); - JSONObject textInput = new JSONObject(); - textInput.put("elementType", "textInput"); - textInput.put("elementId", "element1"); - textInput.put("label", "Name"); - textInput.put("optional", false); - textInput.put("maxLines", 1); - jsonArray.put(textInput); - interactiveData.put("formFields", jsonArray); - JSONObject submitElement = new JSONObject(); - submitElement.put("elementType", "button"); - submitElement.put("elementId", "element8"); - submitElement.put("buttonText", "Submit"); - submitElement.put("disableAfterInteracted", true); - JSONObject action = new JSONObject(); - action.put("actionType", "urlNavigation"); - action.put("url", "https://www.cometchat.com/"); - submitElement.put("action", action); - interactiveData.put("submitElement", submitElement); -} catch (JSONException e) { - throw new RuntimeException(e); -} - -InteractiveMessage interactiveMessage = new InteractiveMessage(receiverId,receiverType,"form", interactiveData); - -CometChat.sendInteractiveMessage(interactiveMessage, new CometChat.CallbackListener() { - @Override - public void onSuccess(InteractiveMessage interactiveMessage) { - // This block is executed when the InteractiveMessage is sent successfully. - } - - @Override - public void onError(CometChatException e) { - // This block is executed if an error occurs while sending the InteractiveMessage. - } -}); -``` - - - - -```kotlin -val interactiveData = JSONObject() -try { - interactiveData.put("title", "Demo Form") - val jsonArray = JSONArray() - val textInput = JSONObject() - textInput.put("elementType", "textInput") - textInput.put("elementId", "element1") - textInput.put("label", "Name") - textInput.put("optional", false) - textInput.put("maxLines", 1) - jsonArray.put(textInput) - interactiveData.put("formFields", jsonArray) - val submitElement = JSONObject() - submitElement.put("elementType", "button") - submitElement.put("elementId", "element8") - submitElement.put("buttonText", "Submit") - submitElement.put("disableAfterInteracted", true) - val action = JSONObject() - action.put("actionType", "urlNavigation") - action.put("url", "https://www.cometchat.com/") - submitElement.put("action", action) - interactiveData.put("submitElement", submitElement) -} catch (e: JSONException) { - throw RuntimeException(e) -} - -val interactiveMessage = InteractiveMessage(receiverId, receiverType, "form", interactiveData) - -CometChat.sendInteractiveMessage(interactiveMessage, object : CometChat.CallbackListener() { - override fun onSuccess(interactiveMessage: InteractiveMessage) { - // This block is executed when the InteractiveMessage is sent successfully. - } - - override fun onError(e: CometChatException) { - // This block is executed if an error occurs while sending the InteractiveMessage. - } -}) -``` - - - - - -### Event Listeners - -CometChat SDK provides event listeners to handle real-time events related to `InteractiveMessage`. - -On `InteractiveMessage` Received The `onInteractiveMessageReceived` event listener is triggered when an InteractiveMessage is received. - -Here is an example: - - - -```java -CometChat.addMessageListener("UNIQUE_ID", new CometChat.MessageListener() { - @Override - public void onInteractiveMessageReceived(InteractiveMessage interactiveMessage){ - // This block is executed when an InteractiveMessage is received. - // Here you can define logic to handle the received InteractiveMessage and display it in your chat interface. - } -}); -``` - - - - -```kotlin -CometChat.addMessageListener("UNIQUE_ID", object : CometChat.MessageListener() { - override fun onInteractiveMessageReceived(interactiveMessage: InteractiveMessage) { - // This block is executed when an InteractiveMessage is received. - // Here you can define logic to handle the received InteractiveMessage and display it in your chat interface. - } -}) -``` - - - - - -### On Interaction Goal Completed - -The `onInteractionGoalCompleted` event listener is invoked when an interaction goal is achieved. - -Here is an example: - - - -```java -CometChat.addMessageListener("UNIQUE_ID", new CometChat.MessageListener() { - @Override - public void onInteractionGoalCompleted(InteractionReceipt interactionReceipt) { - // This block is executed when an interaction goal is completed. - // Here you can specify the actions your application should take once an interaction goal is achieved, such as updating the UI or notifying the user. - } -}); -``` - - - - -```kotlin -CometChat.addMessageListener("UNIQUE_ID", object : CometChat.MessageListener() { - override fun onInteractionGoalCompleted(interactionReceipt: InteractionReceipt) { - // This block is executed when an interaction goal is completed. - // Here you can specify the actions your application should take once an interaction goal is achieved, such as updating the UI or notifying the user. - } -}) -``` - - - - - -These event listeners offer your application a way to provide real-time updates in response to incoming interactive messages and goal completions, contributing to a more dynamic and responsive user chat experience. - -## Usage - -An `InteractiveMessage` is constructed with the receiver's UID, the receiver type, the interactive type, and interactive data as a JSONObject. Once created, the `InteractiveMessage` can be sent using CometChat's `sendInteractiveMessage()` method. Incoming `InteractiveMessages` can be received and processed via CometChat's message listener framework. diff --git a/sdk/android/v5/send-message.mdx b/sdk/android/v5/send-message.mdx index e668c923a..83290f987 100644 --- a/sdk/android/v5/send-message.mdx +++ b/sdk/android/v5/send-message.mdx @@ -4,12 +4,15 @@ title: "Send A Message" -Using CometChat, you can send four types of messages: +Using CometChat, you can work with four types of messages. The first three you can send directly: 1. A [Text Message](/sdk/android/v5/send-message#text-message), the most common and standard message type. 2. A [Media Message](/sdk/android/v5/send-message#media-message), for sending photos, videos and files. 3. A [Custom Message](/sdk/android/v5/send-message#custom-message), for sending completely custom data using JSON structures. -4. A [Card Message](/sdk/android/v5/send-message#card-message), a structured, interactive card message (receive-only — created via the REST API). + +The fourth is receive-only: + +4. A [Card Message](/sdk/android/v5/send-message#card-message), a structured, interactive card message created server-side via the REST API and delivered to clients. You can also send metadata along with a text or media message. Think, for example, if you'd want to share the user's location with every message, you can use the metadata field. diff --git a/ui-kit/android/v6/events.mdx b/ui-kit/android/v6/events.mdx index b4fee3436..462d9805c 100644 --- a/ui-kit/android/v6/events.mdx +++ b/ui-kit/android/v6/events.mdx @@ -455,7 +455,7 @@ fun UserEventsHandler() { | `CometChatUIEvent.HidePanel(id, alignment)` | Triggered to hide a previously shown UI panel. | | `CometChatUIEvent.ActiveChatChanged(id, message, user, group)` | Triggered when the active chat changes. | | `CometChatUIEvent.OpenChat(user, group)` | Triggered to open a chat with a specific user or group. | -| `CometChatUIEvent.CardActionClicked(message, actionEvent)` | Triggered when a user taps an interactive element (button/link) inside a [card message](/ui-kit/android/v6/card-message) (`CardMessage`) or an AI agent card (`AIAssistantMessage`). `actionEvent` is typed `Any`; cast it to `com.cometchat.cards.actions.CometChatCardActionEvent`. | +| `CometChatUIEvent.CardActionClicked(message, actionEvent)` | Triggered when a user taps an interactive element (button/link) inside a [card message](/sdk/android/v5/send-message#card-message) (`CardMessage`) or an AI agent card (`AIAssistantMessage`). `actionEvent` is typed `Any`; cast it to `com.cometchat.cards.actions.CometChatCardActionEvent`. | **Collecting events:** @@ -517,7 +517,7 @@ fun UIEventsHandler() { -> **About `CardActionClicked`:** The UI Kit renders card bubbles automatically (`CometChatCardBubble`) and emits this event when a user taps an action inside one — so a single subscriber handles every card action across your app. `event.message` is a `CardMessage` for standalone [card messages](/ui-kit/android/v6/card-message) and an `AIAssistantMessage` for cards embedded in AI agent replies. `event.actionEvent` is typed `Any`; import and cast it to `com.cometchat.cards.actions.CometChatCardActionEvent` to read its `action`, `elementId`, and `cardJson`. +> **About `CardActionClicked`:** The UI Kit renders card bubbles automatically (`CometChatCardBubble`) and emits this event when a user taps an action inside one — so a single subscriber handles every card action across your app. `event.message` is a `CardMessage` for standalone [card messages](/sdk/android/v5/send-message#card-message) and an `AIAssistantMessage` for cards embedded in AI agent replies. `event.actionEvent` is typed `Any`; import and cast it to `com.cometchat.cards.actions.CometChatCardActionEvent` to read its `action`, `elementId`, and `cardJson`. --- From 69609a648b58746515eff056856fbe25fd1f7804 Mon Sep 17 00:00:00 2001 From: Hritika Date: Fri, 26 Jun 2026 13:50:39 +0530 Subject: [PATCH 8/8] Add cardJson to event in action callback documentation for message handling --- sdk/android/v5/receive-messages.mdx | 3 ++- sdk/android/v5/send-message.mdx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sdk/android/v5/receive-messages.mdx b/sdk/android/v5/receive-messages.mdx index eb88396d2..f75852c10 100644 --- a/sdk/android/v5/receive-messages.mdx +++ b/sdk/android/v5/receive-messages.mdx @@ -184,6 +184,7 @@ cardView.setThemeMode(CometChatCardThemeMode.AUTO) cardView.setActionCallback { event -> // event.action -> one of the 9 tagged action types // event.elementId -> id of the tapped button/link + // event.cardJson -> the raw card schema JSON handleCardAction(event.action) } parentLayout.addView(cardView) @@ -192,7 +193,7 @@ parentLayout.addView(cardView) -The Cards library is a **pure renderer** — it never executes actions, it only emits them through the callback. You own all behavior (opening URLs, navigating to chats, API calls, etc.). The 9 action types (`CometChatCardOpenUrlAction`, `CometChatCardChatWithUserAction`, …) live in `com.cometchat.cards.models`, and `event` is a `com.cometchat.cards.actions.CometChatCardActionEvent` exposing `action` and `elementId`. +The Cards library is a **pure renderer** — it never executes actions, it only emits them through the callback. You own all behavior (opening URLs, navigating to chats, API calls, etc.). The 9 action types (`CometChatCardOpenUrlAction`, `CometChatCardChatWithUserAction`, …) live in `com.cometchat.cards.models`, and `event` is a `com.cometchat.cards.actions.CometChatCardActionEvent` exposing `action`, `elementId`, and `cardJson`. When rendering directly, fallback is your responsibility: if the card JSON is empty or invalid, fall back to `cardMessage.getFallbackText()` (then `getText()`). diff --git a/sdk/android/v5/send-message.mdx b/sdk/android/v5/send-message.mdx index 83290f987..b9d66c5c3 100644 --- a/sdk/android/v5/send-message.mdx +++ b/sdk/android/v5/send-message.mdx @@ -1265,6 +1265,7 @@ cardView.setThemeMode(CometChatCardThemeMode.AUTO) cardView.setActionCallback { event -> // event.action -> one of the 9 tagged action types // event.elementId -> id of the tapped button/link + // event.cardJson -> the raw card schema JSON handleCardAction(event.action) } parentLayout.addView(cardView) @@ -1273,7 +1274,7 @@ parentLayout.addView(cardView) -The Cards library is a **pure renderer** — it never executes actions, it only emits them through the callback. You own all behavior (opening URLs, navigating to chats, API calls, etc.). The 9 action types (`CometChatCardOpenUrlAction`, `CometChatCardChatWithUserAction`, …) live in `com.cometchat.cards.models`, and `event` is a `com.cometchat.cards.actions.CometChatCardActionEvent` exposing `action` and `elementId`. +The Cards library is a **pure renderer** — it never executes actions, it only emits them through the callback. You own all behavior (opening URLs, navigating to chats, API calls, etc.). The 9 action types (`CometChatCardOpenUrlAction`, `CometChatCardChatWithUserAction`, …) live in `com.cometchat.cards.models`, and `event` is a `com.cometchat.cards.actions.CometChatCardActionEvent` exposing `action`, `elementId`, and `cardJson`. When rendering directly, fallback is your responsibility: if the card JSON is empty or invalid, fall back to `cardMessage.getFallbackText()` (then `getText()`).