> ## Documentation Index
> Fetch the complete documentation index at: https://www.cometchat.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Send A Message

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.

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.

## Text Message

*In other words, as a sender, how do I send a text message?*

To send a text message to a single user or group, you need to use the `sendMessage()` method and pass a `TextMessage` object to it.

### Add Metadata

To send custom data along with a text message, you can use the `setMetadata` method and pass a `JSONObject` to it.

<Tabs>
  <Tab title="Java">
    ```java theme={null}
    JSONObject metadata = new JSONObject();
    metadata.put("latitude", "50.6192171633316");
    metadata.put("longitude", "-72.68182268750002");
    textMessage.setMetadata(metadata);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val metadata = JSONObject()
    metadata.put("latitude", "50.6192171633316")
    metadata.put("longitude", "-72.68182268750002")
    textMessage.setMetadata(metadata)
    ```
  </Tab>
</Tabs>

### Add Tags

To add a tag to a message you can use the `setTags()` method of the TextMessage Class. The `setTags()` method accepts a list of tags.

<Tabs>
  <Tab title="Java">
    ```java theme={null}
    List<String> tags = new ArrayList<>();
    tags.add("pinned");
    textMessage.setTags(tags);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val tags: MutableList<String> = ArrayList()
    tags.add("pinned")
    textMessage.setTags(tags)
    ```
  </Tab>
</Tabs>

### Set Quoted Message

To set a quoted message for a message, use the `setQuotedMessageId()` and `setQuotedMessage()` method of the TextMessage class. This method accepts the ID of the message to be quoted.

<Tabs>
  <Tab title="Java">
    ```java theme={null}
    textMessage.setQuotedMessageId(10);
    textMessage.setQuotedMessage(); // Pass base message object here that you want to quote.
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    textMessage.quotedMessageId = 0
    textMessage.quotedMessage =  // Pass base message object here that you want to quote.
    ```
  </Tab>
</Tabs>

Once the text message object is ready, you need to use the `sendMessage()` method to send the text message to the recipient.

<Tabs>
  <Tab title="Java (User)">
    ```java theme={null}
    private String receiverID = "UID";
    private String messageText = "Hello CoemtChat!";
    private String receiverType = CometChatConstants.RECEIVER_TYPE_USER;

    TextMessage textMessage = new TextMessage(receiverID, messageText, receiverType);

    CometChat.sendMessage(textMessage, new CometChat.CallbackListener<TextMessage>() {
      @Override
      public void onSuccess(TextMessage textMessage) {
          Log.d(TAG, "Message sent successfully: " + textMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, "Message sending failed with exception: " + e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (User)">
    ```kotlin theme={null}
    private val receiverID = "UID"
    private val messageText = "Hello CometChat!"
    private val receiverType = CometChatConstants.RECEIVER_TYPE_USER

    val textMessage = TextMessage(receiverID, messageText, receiverType)

    CometChat.sendMessage(textMessage, object : CallbackListener<TextMessage>() {
      override fun onSuccess(textMessage: TextMessage) {
          Log.d(TAG, "Message sent successfully: $textMessage")
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, "Message sending failed with exception: " + e.message)
      }
    })
    ```
  </Tab>

  <Tab title="Java (Group)">
    ```java theme={null}
    private String receiverID = "GUID";
    private String messageText = "Hello CometChat!";
    private String receiverType = CometChatConstants.RECEIVER_TYPE_GROUP;

    TextMessage textMessage = new TextMessage(receiverID, messageText, receiverType);

    CometChat.sendMessage(textMessage, new CometChat.CallbackListener<TextMessage>() {
      @Override
      public void onSuccess(TextMessage textMessage) {
          Log.d(TAG, "Message sent successfully: " + textMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, "Message sending failed with exception: " + e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (Group)">
    ```kotlin theme={null}
    private val receiverID = "GUID"
    private val messageText = "Hello CometChat!"
    private val receiverType = CometChatConstants.RECEIVER_TYPE_GROUP

    val textMessage = TextMessage(receiverID, messageText, receiverType)
    CometChat.sendMessage(textMessage, object : CallbackListener<TextMessage>() {
      override fun onSuccess(textMessage: TextMessage) {
          Log.d(TAG, "Message sent successfully: $textMessage")
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, "Message sending failed with exception: " + e.message)
      }
    })
    ```
  </Tab>
</Tabs>

The `TextMessage` class constructor takes the following parameters:

| Parameter      | Description                                                                                                                  |          |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------- |
| `receiverID`   | `UID` of the user or `GUID` of the group receiving the message                                                               | Required |
| `messageText`  | The text message                                                                                                             | Required |
| `receiverType` | The type of the receiver- `CometChatConstants.RECEIVER_TYPE_USER` (user) or `CometChatConstants.RECEIVER_TYPE_GROUP` (group) | Required |

When a text message is sent successfully, the response will include a `TextMessage` object which includes all information related to the sent message.

## Media Message

*In other words, as a sender, how do I send a media message like photos, videos & files?*

To send a media message to any user or group, you need to use the `sendMediaMessage()` method and pass a `MediaMessage` object to it.

### Add Metadata

To send custom data along with a media message, you can use the `setMetadata` method and pass a `JSONObject` to it.

<Tabs>
  <Tab title="Java">
    ```java theme={null}
    JSONObject metadata = new JSONObject();
    metadata.put("latitude", "50.6192171633316");
    metadata.put("longitude", "-72.68182268750002");
    mediaMessage.setMetadata(metadata);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val metadata = JSONObject()
    metadata.put("latitude", "50.6192171633316")
    metadata.put("longitude", "-72.68182268750002")
    mediaMessage.setMetadata(metadata)
    ```
  </Tab>
</Tabs>

### Add Caption(Text along with Media Message)

To send a caption with a media message, you can use `setCaption` method and pass text to it.

<Tabs>
  <Tab title="Java">
    ```java theme={null}
    mediaMessage.setCaption("Message Caption");
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    mediaMessage.setCaption("Message Caption")
    ```
  </Tab>
</Tabs>

### Add Tags

To add a tag to a message you can use the `setTags()` method of the MediaMessage Class. The `setTags()` method accepts a list of tags.

<Tabs>
  <Tab title="Java">
    ```java theme={null}
    List<String> tags = new ArrayList<>();
    tags.add("pinned");
    mediaMessage.setTags(tags);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val tags: MutableList<String> = ArrayList()
    tags.add("pinned")
    mediaMessage.setTags(tags)
    ```
  </Tab>
</Tabs>

There are 2 ways you can send Media Messages using the CometChat SDK:

1. **By providing the File :** You can directly share the file object while creating an object of the MediaMessage class. When the media message is sent using the sendMediaMessage() method, this file is then uploaded to CometChat servers and the URL of the file is sent in the success response of the sendMediaMessage() function.

<Tabs>
  <Tab title="Java (User)">
    ```java theme={null}
    private String receiverID = "UID";
    private String messageType = CometChatConstants.MESSAGE_TYPE_IMAGE;
    private String receiverType = CometChatConstants.RECEIVER_TYPE_USER;
    private String filePath = "/storage/emulated/0/Download/CometChat.jpg";

    MediaMessage mediaMessage = new MediaMessage(receiverID, new File(filePath), messageType, receiverType);

    CometChat.sendMediaMessage(mediaMessage, new CometChat.CallbackListener<MediaMessage>() {
      @Override
      public void onSuccess(MediaMessage mediaMessage) {
          Log.d(TAG, "Media message sent successfully: " + mediaMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, "Media message sending failed with exception: " + e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (User)">
    ```kotlin theme={null}
    private val receiverID = "UID"
    private val messageType = CometChatConstants.MESSAGE_TYPE_IMAGE
    private val receiverType = CometChatConstants.RECEIVER_TYPE_USER
    private val filePath = "/storage/emulated/0/Download/CometChat.jpg"

    val mediaMessage = MediaMessage(receiverID, File(filePath), messageType, receiverType)
    CometChat.sendMediaMessage(mediaMessage, object : CallbackListener<MediaMessage>() {
      override fun onSuccess(mediaMessage: MediaMessage) {
          Log.d(TAG, "Media message sent successfully: " + mediaMessage.toString())
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, "Media message sending failed with exception: " + e.message)
      }
    })
    ```
  </Tab>

  <Tab title="Java (Group)">
    ```java theme={null}
    private String receiverID = "GUID";
    private String messageType = CometChatConstants.MESSAGE_TYPE_IMAGE;
    private String receiverType = CometChatConstants.RECEIVER_TYPE_GROUP;
    private String filePath = "/storage/emulated/0/Download/CometChat.jpg";

    MediaMessage mediaMessage = new MediaMessage(receiverID, new File(filePath), messageType, receiverType);

    CometChat.sendMediaMessage(mediaMessage, new CometChat.CallbackListener<MediaMessage>() {
      @Override
      public void onSuccess(MediaMessage mediaMessage) {
          Log.d(TAG, "Media message sent successfully: " + mediaMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, "Media message sending failed with exception: " + e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (Group)">
    ```kotlin theme={null}
    private val receiverID = "GUID"
    private val messageType = CometChatConstants.MESSAGE_TYPE_IMAGE
    private val receiverType = CometChatConstants.RECEIVER_TYPE_GROUP
    private val filePath = "/storage/emulated/0/Download/CometChat.jpg"

    val mediaMessage = MediaMessage(receiverID, File(filePath), messageType, receiverType)
    CometChat.sendMediaMessage(mediaMessage, object : CallbackListener<MediaMessage>() {
      override fun onSuccess(mediaMessage: MediaMessage) {
          Log.d(TAG, "Media message sent successfully: " + mediaMessage.toString())
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, "Media message sending failed with exception: " + e.message)
      }
    })
    ```
  </Tab>
</Tabs>

The `MediaMessage` class constructor takes the following parameters:

| Parameter      | Description                                                                                                                                                                                                                                                                               |          |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `receiverId`   | The UID or GUID of the recipient                                                                                                                                                                                                                                                          | Required |
| `file`         | The file object to be sent                                                                                                                                                                                                                                                                | Required |
| `messageType`  | The type of the message that needs to be sent. Options: <br />1. `CometChatConstants.MESSAGE_TYPE_IMAGE` (image) <br />2. `CometChatConstants.MESSAGE_TYPE_VIDEO` (video) <br />3. `CometChatConstants.MESSAGE_TYPE_AUDIO` (audio) <br />4. `CometChatConstants.MESSAGE_TYPE_FILE` (file) | 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)                                                                                                                   | Optional |

2. **By providing the URL of the File:** The second way to send media messages using the CometChat SDK is to provide the SDK with the URL of any file that is hosted on your servers or any cloud storage. To achieve this you will have to make use of the Attachment class that is available in the MediaMessage class. For more information, you can refer to the below code snippet:

<Tabs>
  <Tab title="Java (User)">
    ```java theme={null}
    String receiverId = "recipient_UID";

    MediaMessage mediaMessage = new MediaMessage(receiverId, CometChatConstants.MESSAGE_TYPE_IMAGE, CometChatConstants.RECEIVER_TYPE_USER);

    Attachment attachment = new Attachment();
    attachment.setFileName("test");
    attachment.setFileExtension("png");
    attachment.setFileUrl("https://pngimg.com/uploads/mario/mario_PNG125.png");

    mediaMessage.setAttachment(attachment);

    CometChat.sendMediaMessage(mediaMessage, new CometChat.CallbackListener<MediaMessage>() {
      @Override
      public void onSuccess(MediaMessage mediaMessage1) {
          Log.i(TAG, "onSuccess");
      }

      @Override
      public void onError(CometChatException e) {
          Log.e(TAG, e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (User)">
    ```kotlin theme={null}
    val receiverId = "recipient_UID"

    val mediaMessage = MediaMessage(receiverId, CometChatConstants.MESSAGE_TYPE_IMAGE, CometChatConstants.RECEIVER_TYPE_USER)

    val attachment = Attachment()
    attachment.fileName = "test"
    attachment.fileExtension = "png"
    attachment.fileUrl = "https://pngimg.com/uploads/mario/mario_PNG125.png"

    mediaMessage.attachment = attachment

    CometChat.sendMediaMessage(mediaMessage, object : CallbackListener<MediaMessage?>() {
      override fun onSuccess(mediaMessage1: MediaMessage?) {
          Log.i(TAG, "onSuccess")
      }

      override fun onError(e: CometChatException) {
          Log.e(TAG, e.message!!)
      }
    })
    ```
  </Tab>

  <Tab title="Java (Group)">
    ```java theme={null}
    String receiverId = "recipient_GUID";

    MediaMessage mediaMessage = new MediaMessage(receiverId, CometChatConstants.MESSAGE_TYPE_IMAGE, CometChatConstants.RECEIVER_TYPE_GROUP);

    Attachment attachment = new Attachment();
    attachment.setFileName("test");
    attachment.setFileExtension("png");
    attachment.setFileUrl("https://pngimg.com/uploads/mario/mario_PNG125.png");

    mediaMessage.setAttachment(attachment);

    CometChat.sendMediaMessage(mediaMessage, new CometChat.CallbackListener<MediaMessage>() {
      @Override
      public void onSuccess(MediaMessage mediaMessage1) {
          Log.i(TAG, "onSuccess");
      }

      @Override
      public void onError(CometChatException e) {
          Log.e(TAG, e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (Group)">
    ```kotlin theme={null}
    val receiverId = "recipient_GUID"

    val mediaMessage = MediaMessage(receiverId, CometChatConstants.MESSAGE_TYPE_IMAGE, CometChatConstants.RECEIVER_TYPE_GROUP)

    val attachment = Attachment()
    attachment.fileName = "test"
    attachment.fileExtension = "png"
    attachment.fileUrl = "https://pngimg.com/uploads/mario/mario_PNG125.png"

    mediaMessage.attachment = attachment

    CometChat.sendMediaMessage(mediaMessage, object : CallbackListener<MediaMessage?>() {
      override fun onSuccess(mediaMessage1: MediaMessage?) {
          Log.i(TAG, "onSuccess")
      }

      override fun onError(e: CometChatException) {
          Log.e(TAG, e.message!!)
      }
    })
    ```
  </Tab>
</Tabs>

When a media message is sent successfully, the response will include a `MediaMessage` object which includes all information related to the sent message.

If you wish to send a caption or some text along with the Media Message, you can use the `caption field` provided by the MediaMessage class. To set the caption you can use the `setCaption()` method and at the receiver end, you can obtain the caption using the `getCaption()` method. As with text messages, the metadata field can be used with media messages as well. Any additional information can be passed along with the media message as a `JSONObject`.

## 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:

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.

<Tabs>
  <Tab title="Java (User)">
    ```java theme={null}
    String receiverId = "cometchat-uid-1";

    List<File> files = new ArrayList<File>();
    files.add(new File("/storage/emulated/0/Download/1.jpg"));
    files.add(new File("/storage/emulated/0/Download/2.jpg"));
    files.add(new File("/storage/emulated/0/Download/3.jpg"));

    MediaMessage mediaMessage = new MediaMessage(receiverId, files, fileType, CometChatConstants.RECEIVER_TYPE_USER);

    CometChat.sendMediaMessage(mediaMessage, new CometChat.CallbackListener<MediaMessage>() {
      @Override
      public void onSuccess(MediaMessage mediaMessage) {
          Log.d(TAG, "Message Sent Successfully")
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, "Message Sending Failed with exception : " + e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (User)">
    ```kotlin theme={null}
    val receiverId = "cometchat-uid-1"
    val files: MutableList<File> = ArrayList()
    files.add(File("/storage/emulated/0/Download/1.jpg"))
    files.add(File("/storage/emulated/0/Download/2.jpg"))
    files.add(File("/storage/emulated/0/Download/3.jpg"))

    val mediaMessage = MediaMessage(receiverId, files, fileType, CometChatConstants.RECEIVER_TYPE_USER)

    CometChat.sendMediaMessage(mediaMessage, object : CallbackListener<MediaMessage?>() {
      override fun onSuccess(mediaMessage: MediaMessage?) {
          Log.d(TAG, "Message Sent Successfully")
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, "Message Sending Failed with exception : " + e.message)
      }
    })
    ```
  </Tab>

  <Tab title="Java (Group)">
    ```java theme={null}
    String groupId = "cometchat-guid-1";

    List<File> files = new ArrayList<File>();
    files.add(new File("/storage/emulated/0/Download/1.jpg"));
    files.add(new File("/storage/emulated/0/Download/2.jpg"));
    files.add(new File("/storage/emulated/0/Download/3.jpg"));

    MediaMessage mediaMessage = new MediaMessage(groupId, files, fileType, CometChatConstants.RECEIVER_TYPE_GROUP);

    CometChat.sendMediaMessage(mediaMessage, new CometChat.CallbackListener<MediaMessage>() {
      @Override
      public void onSuccess(MediaMessage mediaMessage) {
          Log.d(TAG, "Message Sent Successfully")
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, "Message Sending Failed with exception : " + e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (Group)">
    ```kotlin theme={null}
    val groupId = "cometchat-guid-1"

    val files: MutableList<File> = ArrayList()
    files.add(File("/storage/emulated/0/Download/1.jpg"))
    files.add(File("/storage/emulated/0/Download/2.jpg"))
    files.add(File("/storage/emulated/0/Download/3.jpg"))

    val mediaMessage = MediaMessage(groupId, files, fileType, CometChatConstants.RECEIVER_TYPE_GROUP)

    CometChat.sendMediaMessage(mediaMessage, object : CallbackListener<MediaMessage?>() {
      override fun onSuccess(mediaMessage: MediaMessage?) {
          Log.d(TAG, "Message Sent Successfully")
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, "Message Sending Failed with exception : " + e.message)
      }
    })
    ```
  </Tab>
</Tabs>

The `MediaMessage` class constructor takes the following parameters:

| **Parameter**    | **Description**                                                                                                                                                                                                                                                             |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **receiverId**   | The `UID` or `GUID` of the recipient.                                                                                                                                                                                                                                       |
| **files**        | An array of files.                                                                                                                                                                                                                                                          |
| **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:

<Tabs>
  <Tab title="Java (User)">
    ```java theme={null}
    String receiverId = "cometchat-uid-1";

    MediaMessage mediaMessage = new MediaMessage(receiverId, CometChatConstants.MESSAGE_TYPE_IMAGE, CometChatConstants.RECEIVER_TYPE_USER);

    List<Attachment> attachments = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        Attachment attachment = new Attachment();
        attachment.setFileName("test");
        attachment.setFileExtension("png");
        attachment.setFileUrl("https://pngimg.com/uploads/mario/mario_PNG125.png");
        attachment.setFileMimeType("image/png");
        attachments.add(attachment);
    }

    mediaMessage.setAttachments(attachments);

    CometChat.sendMediaMessage(mediaMessage, new CometChat.CallbackListener<MediaMessage>() {
        @Override
        public void onSuccess(MediaMessage mediaMessage) {
            Log.d(TAG, "Message Sent Successfully")
        }

        @Override
        public void onError(CometChatException e) {
            Log.d(TAG, "Message Sending Failed with exception : " + e.getMessage());
        }
    });
    ```
  </Tab>

  <Tab title="Kotlin (User)">
    ```kotlin theme={null}
    val receiverId = "cometchat-uid-1"
    val mediaMessage = MediaMessage(receiverId, CometChatConstants.MESSAGE_TYPE_IMAGE, CometChatConstants.RECEIVER_TYPE_USER)

    val attachments: MutableList<Attachment> = ArrayList()
    for (i in 0..4) {
        val attachment = Attachment()
        attachment.fileName = "test"
        attachment.fileExtension = "png"
        attachment.fileUrl = "https://pngimg.com/uploads/mario/mario_PNG125.png"
        attachment.fileMimeType = "image/png"
        attachments.add(attachment)
    }

    mediaMessage.attachments = attachments

    CometChat.sendMediaMessage(mediaMessage, object : CallbackListener<MediaMessage?>() {
        override fun onSuccess(mediaMessage: MediaMessage?) {
            Log.d(TAG, "Message Sent Successfully")
        }

        override fun onError(e: CometChatException) {
            Log.d(TAG, "Message Sending Failed with exception : " + e.message)
        }
    })
    ```
  </Tab>

  <Tab title="Java (Group)">
    ```java theme={null}
    String groupId = "cometchat-guid-1";

    MediaMessage mediaMessage = new MediaMessage(groupId, CometChatConstants.MESSAGE_TYPE_IMAGE, CometChatConstants.RECEIVER_TYPE_GROUP);

    List<Attachment> attachments = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        Attachment attachment = new Attachment();
        attachment.setFileName("test");
        attachment.setFileExtension("png");
        attachment.setFileUrl("https://pngimg.com/uploads/mario/mario_PNG125.png");
        attachment.setFileMimeType("image/png");
        attachments.add(attachment);
    }

    mediaMessage.setAttachments(attachments);

    CometChat.sendMediaMessage(mediaMessage, new CometChat.CallbackListener<MediaMessage>() {
        @Override
        public void onSuccess(MediaMessage mediaMessage) {
            Log.d(TAG, "Message Sent Successfully")
        }

        @Override
        public void onError(CometChatException e) {
            Log.d(TAG, "Message Sending Failed with exception : " + e.getMessage());
        }
    });
    ```
  </Tab>

  <Tab title="Kotlin (Group)">
    ```kotlin theme={null}
    val groupId = "cometchat-guid-1"
    val mediaMessage = MediaMessage(groupId, CometChatConstants.MESSAGE_TYPE_IMAGE, CometChatConstants.RECEIVER_TYPE_GROUP)

    val attachments: MutableList<Attachment> = ArrayList()
    for (i in 0..4) {
        val attachment = Attachment()
        attachment.fileName = "test"
        attachment.fileExtension = "png"
        attachment.fileUrl = "https://pngimg.com/uploads/mario/mario_PNG125.png"
        attachment.fileMimeType = "image/png"
        attachments.add(attachment)
    }

    mediaMessage.attachments = attachments

    CometChat.sendMediaMessage(mediaMessage, object : CallbackListener<MediaMessage?>() {
        override fun onSuccess(mediaMessage: MediaMessage?) {
            Log.d(TAG, "Message Sent Successfully")
        }

        override fun onError(e: CometChatException) {
            Log.d(TAG, "Message Sending Failed with exception : " + e.message)
        }
    })
    ```
  </Tab>
</Tabs>

When a media message is sent successfully, the response will include a `MediaMessage` object which includes all information related to the sent message.

You can use the `setMetadata()`, `setCaption()` & `setTags()` methods to add metadata, caption and tags respectively in exactly the same way as it is done while sending a single file or attachment in a Media Message.

## Custom Message

*In other words, as a sender, how do I send a custom message like location co-ordinates?*

CometChat allows you to send custom messages which are neither text nor media messages.

In order to send a custom message, you need to use the `sendCustomMessage()` method.

The `sendCustomMessage()` methods takes an object of the `CustomMessage` which can be obtained using the below constructor.

<Tabs>
  <Tab title="Java">
    ```java theme={null}
    CustomMessage customMessage = new CustomMessage(receiverId, receiverType,customType, customData)
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val customMessage = CustomMessage(receiverId, receiverType, customType, customData)
    ```
  </Tab>
</Tabs>

The above constructor, helps you create a custom message with the message type set to whatever is passed to the constructor and the category set to `custom`.

The parameters involved are:

1. `receiverId` - Unique id of the user or group to which the message is to be sent.
2. `receiverType` - Type of the receiver i.e user or group
3. `customType` - custom message type that you need to set
4. `customData` - The data to be passed as the message in the form of a JSONObject.

You can also use the subType field of the `CustomMessage` class to set a specific type for the custom message. This can be achieved using the `setSubtype()` method.

### Add Tags

To add a tag to a message you can use the `setTags()` method of the CustomMessage Class. The `setTags()` method accepts a list of tags.

<Tabs>
  <Tab title="Java">
    ```java theme={null}
    List<String> tags = new ArrayList<>();
    tags.add("pinned");
    customMessage.setTags(tags);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val tags: MutableList<String> = ArrayList()
    tags.add("pinned")
    customMessage.setTags(tags)
    ```
  </Tab>
</Tabs>

Once the object of `CustomMessage` class is ready you can send the custom message using the `sendCustomMessage()` method.

<Tabs>
  <Tab title="Java (User)">
    ```java theme={null}
    private String UID = "UID";
    private String customType = "LOCATION";

    JSONObject customData = new JSONObject();
    customData.put("latitude", "19.0760");
    customData.put("longitude", "72.8777");

    CustomMessage customMessage = new CustomMessage(UID, CometChatConstants.RECEIVER_TYPE_USER, customType, customData);

    CometChat.sendCustomMessage(customMessage, new CometChat.CallbackListener<CustomMessage>() {
      @Override
      public void onSuccess(CustomMessage customMessage) {
          Log.d(TAG, customMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (User)">
    ```kotlin theme={null}
    private val UID = "UID"
    private val customType = "LOCATION"

    val customData = JSONObject()
    customData.put("latitude", "19.0760")
    customData.put("longitude", "72.8777")
    val customMessage = CustomMessage(UID, CometChatConstants.RECEIVER_TYPE_USER, customType, customData)

    CometChat.sendCustomMessage(customMessage, object : CallbackListener<CustomMessage>() {
      override fun onSuccess(customMessage: CustomMessage) {
          Log.d(TAG, customMessage.toString())
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, e.message!!)
      }
    })
    ```
  </Tab>

  <Tab title="Java (Group)">
    ```java theme={null}
    private String GUID = "GUID";
    private String customType = "LOCATION";

    JSONObject customData = new JSONObject();
    customData.put("latitude", "19.0760");
    customData.put("longitude", "72.8777");

    CustomMessage customMessage = new CustomMessage(GUID, CometChatConstants.RECEIVER_TYPE_GROUP, customType, customData);

    CometChat.sendCustomMessage(customMessage, new CometChat.CallbackListener<CustomMessage>() {
      @Override
      public void onSuccess(CustomMessage customMessage) {
          Log.d(TAG, customMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (Group)">
    ```kotlin theme={null}
    private val GUID = "GUID"
    private val customType = "LOCATION"

    val customData = JSONObject()
    customData.put("latitude", "19.0760")
    customData.put("longitude", "72.8777")
    val customMessage = CustomMessage(GUID, CometChatConstants.RECEIVER_TYPE_GROUP, customType, customData)

    CometChat.sendCustomMessage(customMessage, object : CallbackListener<CustomMessage>() {
      override fun onSuccess(customMessage: CustomMessage) {
          Log.d(TAG, customMessage.toString())
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, e.message!!)
      }
    })
    ```
  </Tab>
</Tabs>

The above sample explains how custom messages can be used to share the location with a user. Similarly, you can send custom messages to groups.

On success, you will receive an object of `CustomMessage` class.

### Update Conversation

*How can I decide whether the custom message should update the last message of a conversation?*

By default, a custom message will update the last message of a conversation. If you wish to not update the last message of the conversation when a custom message is sent, please use `shouldUpdateConversation(boolean value)` method of the Custom Message.

<Tabs>
  <Tab title="Java (User)">
    ```java theme={null}
    private String UID = "UID";
    private String customType = "LOCATION";

    JSONObject customData = new JSONObject();
    customData.put("latitude", "19.0760");
    customData.put("longitude", "72.8777");

    CustomMessage customMessage = new CustomMessage(UID, CometChatConstants.RECEIVER_TYPE_USER, customType, customData);
    customMessage.shouldUpdateConversation(false);

    CometChat.sendCustomMessage(customMessage, new CometChat.CallbackListener<CustomMessage>() {
      @Override
      public void onSuccess(CustomMessage customMessage) {
          Log.d(TAG, customMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (User)">
    ```kotlin theme={null}
    private val UID = "UID"
    private val customType = "LOCATION"

    val customData = JSONObject()
    customData.put("latitude", "19.0760")
    customData.put("longitude", "72.8777")

    val customMessage = CustomMessage(UID, CometChatConstants.RECEIVER_TYPE_USER, customType, customData)
    customMessage.shouldUpdateConversation(false)

    CometChat.sendCustomMessage(customMessage, object : CallbackListener<CustomMessage>() {
      override fun onSuccess(customMessage: CustomMessage) {
          Log.d(TAG, customMessage.toString())
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, e.message!!)
      }
    })
    ```
  </Tab>

  <Tab title="Java (Group)">
    ```java theme={null}
    private String GUID = "GUID";
    private String customType = "LOCATION";

    JSONObject customData = new JSONObject();
    customData.put("latitude", "19.0760");
    customData.put("longitude", "72.8777");

    CustomMessage customMessage = new CustomMessage(GUID, CometChatConstants.RECEIVER_TYPE_GROUP, customType, customData);
    customMessage.shouldUpdateConversation(false);

    CometChat.sendCustomMessage(customMessage, new CometChat.CallbackListener<CustomMessage>() {
      @Override
      public void onSuccess(CustomMessage customMessage) {
          Log.d(TAG, customMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (Group)">
    ```kotlin theme={null}
    private val GUID = "GUID"
    private val customType = "LOCATION"

    val customData = JSONObject()
    customData.put("latitude", "19.0760")
    customData.put("longitude", "72.8777")

    val customMessage = CustomMessage(GUID, CometChatConstants.RECEIVER_TYPE_GROUP, customType, customData)
    customMessage.shouldUpdateConversation(false)

    CometChat.sendCustomMessage(customMessage, object : CallbackListener<CustomMessage>() {
      override fun onSuccess(customMessage: CustomMessage) {
          Log.d(TAG, customMessage.toString())
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, e.message!!)
      }
    })
    ```
  </Tab>
</Tabs>

### Custom Notification Body

*How can i customise the notification body of custom message?*

To add a custom notification body for `Push, Email & SMS` notification of a custom message you can use the `setConversationText(text: string)` method of Custom Message class.

<Tabs>
  <Tab title="Java (User)">
    ```java theme={null}
    private String UID = "UID";
    private String customType = "LOCATION";

    JSONObject customData = new JSONObject();
    customData.put("latitude", "19.0760");
    customData.put("longitude", "72.8777");

    CustomMessage customMessage = new CustomMessage(UID, CometChatConstants.RECEIVER_TYPE_USER, customType, customData);
    customMessage.setConversationText("Custom Notification Body");

    CometChat.sendCustomMessage(customMessage, new CometChat.CallbackListener<CustomMessage>() {
      @Override
      public void onSuccess(CustomMessage customMessage) {
          Log.d(TAG, customMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (User)">
    ```kotlin theme={null}
    private val UID = "UID"
    private val customType = "LOCATION"

    val customData = JSONObject()
    customData.put("latitude", "19.0760")
    customData.put("longitude", "72.8777")

    val customMessage = CustomMessage(UID, CometChatConstants.RECEIVER_TYPE_USER, customType, customData)
    customMessage.setConversationText("Custom Notification Body")

    CometChat.sendCustomMessage(customMessage, object : CallbackListener<CustomMessage>() {
      override fun onSuccess(customMessage: CustomMessage) {
          Log.d(TAG, customMessage.toString())
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, e.message!!)
      }
    })
    ```
  </Tab>

  <Tab title="Java (Group)">
    ```java theme={null}
    private String GUID = "GUID";
    private String customType = "LOCATION";

    JSONObject customData = new JSONObject();
    customData.put("latitude", "19.0760");
    customData.put("longitude", "72.8777");

    CustomMessage customMessage = new CustomMessage(GUID, CometChatConstants.RECEIVER_TYPE_GROUP, customType, customData);
    customMessage.setConversationText("Custom Notification Body");

    CometChat.sendCustomMessage(customMessage, new CometChat.CallbackListener<CustomMessage>() {
      @Override
      public void onSuccess(CustomMessage customMessage) {
          Log.d(TAG, customMessage.toString());
      }

      @Override
      public void onError(CometChatException e) {
          Log.d(TAG, e.getMessage());
      }
    });
    ```
  </Tab>

  <Tab title="Kotlin (Group)">
    ```kotlin theme={null}
    private val GUID = "GUID"
    private val customType = "LOCATION"

    val customData = JSONObject()
    customData.put("latitude", "19.0760")
    customData.put("longitude", "72.8777")

    val customMessage = CustomMessage(GUID, CometChatConstants.RECEIVER_TYPE_GROUP, customType, customData)
    customMessage.setConversationText("Custom Notification Body")

    CometChat.sendCustomMessage(customMessage, object : CallbackListener<CustomMessage>() {
      override fun onSuccess(customMessage: CustomMessage) {
          Log.d(TAG, customMessage.toString())
      }

      override fun onError(e: CometChatException) {
          Log.d(TAG, e.message!!)
      }
    })
    ```
  </Tab>
</Tabs>

## 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.

<Note>
  **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.
</Note>

On the receiving end, the `CardMessage` object gives you access to the card payload and its related fields.

<Tabs>
  <Tab title="Java">
    ```java theme={null}
    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<String> tags = cardMessage.getTags();           // tags associated with the message
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    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
    ```
  </Tab>
</Tabs>

The `CardMessage` class provides the following methods:

| 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<String>` | 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`.

### 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 theme={null}
// settings.gradle (or project-level build.gradle)
repositories {
    maven { url "https://dl.cloudsmith.io/public/cometchat/cometchat/maven/" }
}
```

```groovy theme={null}
// app/build.gradle
dependencies {
    implementation "com.cometchat:cards-android:1.0.0"
}
```

<Note>
  Requires `minSdk 24`, Kotlin, and the internet permission in your `AndroidManifest.xml`.
</Note>

#### Render the card

Pass the card JSON (`cardMessage.getCard().toString()`) to the renderer and handle actions through the callback.

<Tabs>
  <Tab title="Jetpack Compose">
    ```kotlin theme={null}
    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 */ }
                }
            }
        )
    }
    ```
  </Tab>

  <Tab title="XML Views">
    ```kotlin theme={null}
    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
        // event.cardJson  -> the raw card schema JSON
        handleCardAction(event.action)
    }
    parentLayout.addView(cardView)
    ```
  </Tab>
</Tabs>

<Note>
  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()`).
</Note>
