Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -4150,6 +4150,7 @@
"pages": [
"sdk/android/v5/messaging-overview",
"sdk/android/v5/send-message",
"sdk/android/v5/upload-files",
"sdk/android/v5/receive-messages",
"sdk/android/v5/additional-message-filtering",
"sdk/android/v5/retrieve-conversations",
Expand Down
Binary file added images/multi_attachments_mobile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 9 additions & 3 deletions sdk/android/v5/send-message.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -503,9 +503,15 @@ If you wish to send a caption or some text along with the Media Message, you can

## Multiple Attachments in a Media Message

Starting version 3.0.9 & above the SDK supports sending of multiple attachments in a single media message. As in case for single attachment in a media message, there are two ways you can send Media Messages using the CometChat SDK:
The SDK supports sending multiple attachments in a single media message. A media message can carry up to a configurable maximum number of attachments (default **10**, controlled by the `file.count.max` app setting). `sendMediaMessage()` calls back `onError` with `ERR_FILE_COUNT_EXCEEDED` if you exceed it — read the current limit at runtime with `CometChat.getMaxAttachmentCount()`.

1. **By providing an array of files:** You can now share a List of files while creating an object of the MediaMessage class. When the media message is sent using the `sendMediaMessage()` method, the files are uploaded to the CometChat servers & the URL of the files are sent in the success response of the `sendMediaMessage()` method.
<Tip>
**Recommended: upload first, then send.** For a real composer — where you want a progress bar per file, and the ability to remove or retry individual files — create an upload request with [`CometChat.createUploadFileRequest()`](/sdk/android/v5/upload-files), upload your files through it, then collect the resulting `Attachment`s (`request.getAttachments()`) and attach them here with `setAttachments()`. This decouples the (slow, cancellable) upload from the (instant) send. See [Upload Files & Send Attachments](/sdk/android/v5/upload-files) for the full flow.
</Tip>

There are two ways to send a multi-attachment media message using the CometChat SDK:

1. **By providing a list of files:** You can share a `List` of files while creating an object of the MediaMessage class. When the media message is sent using the `sendMediaMessage()` method, the files are uploaded to the CometChat servers & the URL of the files is sent in the success response of the `sendMediaMessage()` method. This is the simplest path, but it gives no upload progress and no per-file cancel/retry — for that, [upload first](/sdk/android/v5/upload-files).

<Tabs>
<Tab title="Java (User)">
Expand Down Expand Up @@ -618,7 +624,7 @@ The `MediaMessage` class constructor takes the following parameters:
| **messageType** | The type of the message that needs to be sent which in this case can be: <br />1. `CometChatConstants.MESSAGE_TYPE_IMAGE` <br />2. `CometChatConstants.MESSAGE_TYPE_VIDEO` <br />3. `CometChatConstants.MESSAGE_TYPE_AUDIO` <br />4. `CometChatConstants.MESSAGE_TYPE_FILE` |
| **receiverType** | The type of the receiver to whom the message is to be sent. <br />1. `CometChatConstants.RECEIVER_TYPE_USER` <br />2. `CometChatConstants.RECEIVER_TYPE_GROUP` |

2. **By providing the URL of the multiple files:** The second way to send multiple attachments using the CometChat SDK is to provide the SDK with the URL of multiple files that is hosted on your servers or any cloud storage. To achieve this you will have to make use of the `Attachment` class. For more information, you can refer to the below code snippet:
2. **By providing the URL of the multiple files:** The second way to send multiple attachments using the CometChat SDK is to provide the SDK with `Attachment` objects that already point at files hosted on your servers or any cloud storage. This is also the path the [upload-then-send flow](/sdk/android/v5/upload-files) uses — the `Attachment`s from an upload request's `getAttachments()` are ready to pass straight to `setAttachments()`. For more information, you can refer to the below code snippet:

<Tabs>
<Tab title="Java (User)">
Expand Down
578 changes: 578 additions & 0 deletions sdk/android/v5/upload-files.mdx

Large diffs are not rendered by default.

19 changes: 15 additions & 4 deletions ui-kit/android/v6/core-features.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,27 @@ Real-time text messaging — users can send and receive instant messages.

## Media Sharing

Share images, videos, audio files, and documents within conversations.
Share multiple images, videos, audio files, and documents in a single send. Tapping the attachment button opens a multi-select picker; the picks stage in a preview tray above the input box with per-file upload progress, and send together with an optional caption — all out of the box.

<Frame>
<img src="/images/8fa177a9-Media_Sharing-e84fa670d754f58294c0c31611107ef7.png" />
<img src="/images/multi_attachment_overview.png" alt="Multi-attachment message list showing an image grid, a file card, and an audio bubble with caption, plus the composer staging tray with mixed image, video, and file tiles" />
</Frame>

| Component | Role |
| --- | --- |
| [CometChatMessageComposer](/ui-kit/android/v6/message-composer) | Provides an action sheet with options for sharing media files. |
| [CometChatMessageList](/ui-kit/android/v6/message-list) | Renders media message bubbles — [Image](/ui-kit/android/v6/message-bubble-styling#image-bubble), [File](/ui-kit/android/v6/message-bubble-styling#file-bubble), [Audio](/ui-kit/android/v6/message-bubble-styling#audio-bubble), [Video](/ui-kit/android/v6/message-bubble-styling#video-bubble). |
| [CometChatMessageComposer](/ui-kit/android/v6/message-composer#multiple-attachments) | Multi-select picker, an attachment tray that uploads before send, and the composer text as the batch caption. |
| [CometChatMessageList](/ui-kit/android/v6/message-list#multiple-attachments) | Renders received attachments with per-type bubbles and groups a multi-type send as one visual batch. |

A mixed pick is split into one message per attachment type (images → videos → audios → files) that render as grouped bubbles: an image/video **grid**, a stacked **audio player** list, and a connected **file card** stack. Per-message file count and per-file size limits come from your app's dashboard settings.

**Supported media types:**

| Type | Single | Multiple |
| --- | --- | --- |
| Images | [Image Bubble](/ui-kit/android/v6/message-bubble-styling#image-bubble) | [Images Bubble](/ui-kit/android/v6/message-bubble-styling#images-bubble) |
| Videos | [Video Bubble](/ui-kit/android/v6/message-bubble-styling#video-bubble) | [Videos Bubble](/ui-kit/android/v6/message-bubble-styling#videos-bubble) |
| Audio | [Audio Bubble](/ui-kit/android/v6/message-bubble-styling#audio-bubble) (voice notes) | [Audios Bubble](/ui-kit/android/v6/message-bubble-styling#audios-bubble) |
| Files | [File Bubble](/ui-kit/android/v6/message-bubble-styling#file-bubble) | [Files Bubble](/ui-kit/android/v6/message-bubble-styling#files-bubble) |

## Read Receipts

Expand Down
124 changes: 105 additions & 19 deletions ui-kit/android/v6/message-bubble-styling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -163,24 +163,38 @@ incomingMessageBubbleStyle = CometChatIncomingMessageBubbleStyle.default().copy(
</Tab>
</Tabs>

### Audio Bubble
### Images Bubble

Renders a message that carries **multiple image attachments** (`CometChatImagesBubble`) as a count-based grid (1, 2, 3, 4, or 5+ tiles). When there are more images than visible tiles, the last tile shows a "+N" overflow overlay. Tapping a tile opens the fullscreen gallery viewer. A caption renders underneath the grid. This is the multi-attachment bubble the list renders for image messages; the single-attachment [Image Bubble](#image-bubble) remains for standalone use.

The image grid derives its look from your [CometChat theme](/ui-kit/android/v6/theme-introduction). In **Jetpack Compose** it is governed by the dedicated `CometChatImagesBubbleStyle` class. Its grid-specific properties:

| Property | Type | Description |
| --- | --- | --- |
| `tileCornerRadius` | `Dp` | Corner radius of each grid tile |
| `gridSpacing` | `Dp` | Gap between tiles (default `2.dp`) |
| `tilePlaceholderColor` | `Color` | Shown while a tile's image loads |
| `moreOverlayBackgroundColor` | `Color` | Scrim over the last tile when items overflow |
| `moreOverlayTextColor` / `moreOverlayTextStyle` | `Color` / `TextStyle` | The "+N" overflow label |
| `captionTextColor` / `captionTextStyle` | `Color` / `TextStyle` | The caption row under the grid |

### Video Bubble

<Frame>
<img src="/images/a1a5851e-custom_audio_bubble-7435f7e797b4c409156bc0df3c0bc077.png" />
<img src="/images/b4e3e6a4-custom_video_bubble-105a5b18f4021eafdf4266bedce930d7.png" />
</Frame>

<Tabs>
<Tab title="Kotlin (XML Views)">

```xml themes.xml lines
<style name="CustomIncomingAudioBubble" parent="CometChatIncomingAudioBubbleStyle">
<item name="cometchatAudioBubbleAudioWaveColor">#F76808</item>
<item name="cometchatAudioBubblePlayIconTint">#F76808</item>
<item name="cometchatAudioBubbleBackgroundColor">#FEEDE1</item>
<style name="CustomIncomingVideoBubble" parent="CometChatIncomingVideoBubbleStyle">
<item name="cometchatVideoBubbleBackgroundColor">#FEEDE1</item>
<item name="cometchatVideoBubblePlayIconTint">#F76808</item>
</style>

<style name="CustomIncomingBubble" parent="CometChatIncomingMessageBubbleStyle">
<item name="cometchatAudioBubbleStyle">@style/CustomIncomingAudioBubble</item>
<item name="cometchatVideoBubbleStyle">@style/CustomIncomingVideoBubble</item>
</style>
```

Expand All @@ -189,33 +203,50 @@ incomingMessageBubbleStyle = CometChatIncomingMessageBubbleStyle.default().copy(

```kotlin lines
incomingMessageBubbleStyle = CometChatIncomingMessageBubbleStyle.default().copy(
audioBubbleStyle = CometChatAudioBubbleStyle.default().copy(
playIconTint = Color(0xFFF76808),
backgroundColor = Color(0xFFFEEDE1)
videoBubbleStyle = CometChatVideoBubbleStyle.default().copy(
backgroundColor = Color(0xFFFEEDE1),
playIconTint = Color(0xFFF76808)
)
)
```

</Tab>
</Tabs>

### Video Bubble
### Videos Bubble

Renders a message that carries **multiple video attachments** (`CometChatVideosBubble`) as a count-based grid (1, 2, 3, 4, or 5+ tiles). Each tile shows a poster thumbnail with a centered play badge and a duration chip; the last tile shows a "+N" overflow overlay when there are more videos than visible tiles. Tapping a tile opens the fullscreen player. A caption renders underneath the grid. This is the multi-attachment bubble the list renders for video messages; the single-attachment [Video Bubble](#video-bubble) remains for standalone use.

The video grid derives its look from your [CometChat theme](/ui-kit/android/v6/theme-introduction). In **Jetpack Compose** it is governed by the dedicated `CometChatVideosBubbleStyle` class. Its grid-specific properties:

| Property | Type | Description |
| --- | --- | --- |
| `tileCornerRadius` / `gridSpacing` | `Dp` | Tile corner radius and gap |
| `tilePlaceholderColor` | `Color` | Shown while a thumbnail loads |
| `moreOverlayBackgroundColor` / `moreOverlayTextColor` / `moreOverlayTextStyle` | `Color` / `TextStyle` | The "+N" overflow overlay |
| `playBadgeBackgroundColor` / `playIconTint` | `Color` | The centered play badge on video tiles |
| `durationChipBackgroundColor` / `durationTextColor` / `durationTextStyle` | `Color` / `TextStyle` | The duration chip |
| `showVideoDuration` | `Boolean` | Whether the duration chip is shown |
| `captionTextColor` / `captionTextStyle` | `Color` / `TextStyle` | The caption row under the grid |

### Audio Bubble

<Frame>
<img src="/images/b4e3e6a4-custom_video_bubble-105a5b18f4021eafdf4266bedce930d7.png" />
<img src="/images/a1a5851e-custom_audio_bubble-7435f7e797b4c409156bc0df3c0bc077.png" />
</Frame>

<Tabs>
<Tab title="Kotlin (XML Views)">

```xml themes.xml lines
<style name="CustomIncomingVideoBubble" parent="CometChatIncomingVideoBubbleStyle">
<item name="cometchatVideoBubbleBackgroundColor">#FEEDE1</item>
<item name="cometchatVideoBubblePlayIconTint">#F76808</item>
<style name="CustomIncomingAudioBubble" parent="CometChatIncomingAudioBubbleStyle">
<item name="cometchatAudioBubbleAudioWaveColor">#F76808</item>
<item name="cometchatAudioBubblePlayIconTint">#F76808</item>
<item name="cometchatAudioBubbleBackgroundColor">#FEEDE1</item>
</style>

<style name="CustomIncomingBubble" parent="CometChatIncomingMessageBubbleStyle">
<item name="cometchatVideoBubbleStyle">@style/CustomIncomingVideoBubble</item>
<item name="cometchatAudioBubbleStyle">@style/CustomIncomingAudioBubble</item>
</style>
```

Expand All @@ -224,16 +255,40 @@ incomingMessageBubbleStyle = CometChatIncomingMessageBubbleStyle.default().copy(

```kotlin lines
incomingMessageBubbleStyle = CometChatIncomingMessageBubbleStyle.default().copy(
videoBubbleStyle = CometChatVideoBubbleStyle.default().copy(
backgroundColor = Color(0xFFFEEDE1),
playIconTint = Color(0xFFF76808)
audioBubbleStyle = CometChatAudioBubbleStyle.default().copy(
playIconTint = Color(0xFFF76808),
backgroundColor = Color(0xFFFEEDE1)
)
)
```

</Tab>
</Tabs>

### Audios Bubble

Renders a message carrying **audio file attachments** (`CometChatAudiosBubble`) — audio chosen through the file/audio picker — one player row per file, each with a play/pause button, a seekable progress bar, the time, the file name, and a download control. Four or more files collapse behind a "Show N more" toggle. Only one row plays at a time.

<Note>

This bubble is distinct from the [Audio Bubble](#audio-bubble), which renders **voice notes** recorded with the composer's microphone. Voice notes keep their waveform look and are never grouped with other attachments.

</Note>

In **Jetpack Compose** it is governed by `CometChatAudiosBubbleStyle`; the **Kotlin (XML Views)** list reuses your existing [Audio Bubble](#audio-bubble) style. Key Compose properties:

| Property | Type | Description |
| --- | --- | --- |
| `cardBackgroundColor` / `cardCornerRadius` | `Color` / `Dp` | Each player card (applies only when the message carries multiple files) |
| `itemSpacing` | `Dp` | Vertical gap between cards |
| `playButtonBackgroundColor` / `playIconTint` | `Color` | The play/pause circle |
| `seekFillColor` / `seekTrackColor` / `seekKnobColor` / `seekKnobBorderColor` | `Color` | The seek bar |
| `titleTextColor` / `titleTextStyle` | `Color` / `TextStyle` | File name text |
| `durationTextColor` / `durationTextStyle` | `Color` / `TextStyle` | The "mm:ss / mm:ss" time text |
| `downloadIconTint` | `Color` | Per-card download icon |
| `toggleTextColor` / `toggleTextStyle` | `Color` / `TextStyle` | The "Show N more" / "Show less" toggle |
| `captionTextColor` / `captionTextStyle` | `Color` / `TextStyle` | The caption row under the cards |

### File Bubble

<Frame>
Expand Down Expand Up @@ -269,6 +324,37 @@ incomingMessageBubbleStyle = CometChatIncomingMessageBubbleStyle.default().copy(
</Tab>
</Tabs>

### Files Bubble

Renders a message carrying **document attachments** as a connected stack of file cards — each with a file-type icon (PDF, Word, Excel, PowerPoint, ZIP, …), the file name, and its size/extension metadata. Four or more files collapse behind a "+N more" toggle. Tapping a card opens the file. A caption renders under the stack.

<Note>

`cardBackgroundColor` only applies when the message carries **multiple** files — a single file card sits directly on the bubble background.

</Note>

In **Jetpack Compose** it is governed by `CometChatFilesBubbleStyle`; the **Kotlin (XML Views)** list reuses your existing [File Bubble](#file-bubble) style. Key Compose properties:

| Property | Type | Description |
| --- | --- | --- |
| `cardBackgroundColor` / `cardCornerRadius` | `Color` / `Dp` | Each file card (multiples only) |
| `itemSpacing` | `Dp` | Vertical gap between cards |
| `fileIconBackgroundColor` / `fileIconCornerRadius` / `fileIconSize` | `Color` / `Dp` | The file-type icon plate |
| `titleTextColor` / `titleTextStyle` | `Color` / `TextStyle` | File name text |
| `subtitleTextColor` / `subtitleTextStyle` | `Color` / `TextStyle` | File size/extension text |
| `downloadIconTint` | `Color` | Per-card download icon |
| `toggleTextColor` / `toggleTextStyle` | `Color` / `TextStyle` | The "+N more" / "Show less" toggle |
| `captionTextColor` / `captionTextStyle` | `Color` / `TextStyle` | The caption row under the cards |

<Note>

Captions containing rich text (code blocks, quote blocks, inline code) render through the same pipeline as [Text Bubbles](#text-bubble), so their formatting looks identical across message types.

</Note>

---

### Sticker Bubble

<Frame>
Expand Down
Loading