Send and receive messages

Updated

Shows how to implement sending and receiving these messages using the Agora Chat SDK.

After logging in to Chat, users can send the following types of messages to a peer user, a chat group, or a chat room:

  • Text messages, including hyperlinks and emojis.

  • Attachment messages, including image, voice, video, and file messages.

  • Location messages.

  • CMD messages.

  • Extended messages.

  • Custom messages.

The Chat message feature is language agnostic. End users can send messages in any language, as long as their devices support input in that language.

In addition to sending messages, users can also forward one or more messages. When forwarding multiple messages, users have the following options:

  • Forward messages one-by-one
  • Forward combined messages as message history

This page shows how to implement sending, receiving, forwarding multiple messages, and modifying sent messages using the Chat SDK.

Understand the tech

The process of sending and receiving a message is as follows:

  1. The message sender creates a text, file, or attachment message using the corresponding create method.
  2. The message sender calls send to send the message.
  3. The message recipient calls addEventHandler to listen for message events and receive the message in the corresponding callback.

Prerequisites

Before proceeding, ensure that you meet the following requirements:

  • You have integrated the Chat SDK, initialized the SDK, and implemented the functionality of registering accounts and login. For details, see Chat SDK quickstart.

    Use Chat SDK 1.2 or higher if you intend to enable users to forward multiple messages, or to modify sent messages.

  • You understand the API call frequency limits as described in Limitations.

Implementation

This section shows how to implement sending and receiving the various types of messages.

Send a text message

Use the Message class to create a text message, and send the message.

// Send a text message.
function sendTextMessage() {
  const options = {
    // Set the message type.
    type: "txt",
    // Set the message content.
    msg: "message content",
    // Set the user ID of the recipient for one-to-one chat, group ID for group chat, or chat room ID for room chat.
    to: "username",
    // Set `chatType` as `singleChat` for one-to-one chat, `groupChat` for group chat, or `chatRoom` for room chat.
    // The default value is `singleChat`.
    chatType: "singleChat",
  };
  // Create a text message.
  const msg = AgoraChat.message.create(options);
  // Call `send` to send the message.
  chatClient
    .send(msg)
    .then((res) => {
      console.log("Send message success", res);
    })
    .catch((e) => {
      console.log("Send message fail", e);
    });
}

Send a message to online users only

Agora Chat supports delivering messages only to users that are currently online. An example of using this function is displaying the votes in a group voting: Only users that are online need to see the changes in real time, while the others only need the final result.

All types of messages in one-to-one chats and chat groups support this function. Compared to an ordinary message, a message that is delivered only to online users has the following differences:

  • Does not support offline storage: If the recipient is offline when sending a message, the message cannot be received, even after logging in again. For ordinary messages, when the recipient is online, the message reminder is received in real time; when the recipient is offline, the offline push message is sent in real time. When the recipient is online again, the Chat server actively pushes the offline message to the client.
  • Support local storage: After a message is successfully sent, it is added to the database.
  • Roaming storage is not supported by default: Sent messages are not stored on the Chat message server by default, so users cannot obtain the messages on other devices. If you need to activate roaming storage of online messages, contact support@agora.io.

To deliver messages only to online users, set Message#deliverOnlineOnly to true when sending the message. The following is an example of sending a text message to only online users:

// Send text message.
function sendTextMessage() {
  const options = {
    // Message type.
    type: "txt",
    // Message content.
    msg: "message content",
    // Message recipient: Single chat is the other party's user ID, group chat is the group ID.
    to: "username",
    // Conversation type: single chat and group chat are `singleChat` and `groupChat` respectively, the default is single chat.
    chatType: "singleChat",
    // Whether the message is only delivered to online users. (Default) `false`: Delivered regardless of whether the user is online or not; `true`: Only delivered to online users. If the user is offline, message delivery fails.
    deliverOnlineOnly: true,
  };
  // Create text message.
  const msg = AgoraChat.message.create(options);
  // Call the `send` method to send the text message.
  chatClient
    .send(msg)
    .then((res) => {
      console.log("Send message success", res);
    })
    .catch((e) => {
      console.log("Send message fail", e);
    });
}

Set message priority

In high-concurrency use-cases, you can set a certain message type or messages from a chat room member as high, normal, or low priority. In this case, low-priority messages are dropped first to reserve resources for the high-priority ones, for example, gifts and announcements, when the server is overloaded. This ensures that the high-priority messages can be dealt with first when loads of messages are being sent in high concurrency or high frequency. Note that this feature can increase the delivery reliability of high-priority messages, but cannot guarantee the deliveries. Even high-priorities messages can be dropped when the server load goes too high.

You can set the priority for all types of messages in the chat room.

// Send a text message.
function sendTextMessage() {
  const options = {
    type: "txt",
    msg: "message content",
    // Set the message priority. The default value is `normal`, indicating the normal priority.
    priority: "high",
    to: "chat room ID",
    chatType: "chatRoom",
  };
  const msg = AgoraChat.message.create(options);
  chatClient
    .send(msg)
    .then(() => {
      console.log("Send message success");
    })
    .catch((e) => {
      console.log("Send message fail");
    });
}

Receive a message

You can use addEventHandler to listen for message events. You can add multiple events. When you no longer listen for an event, ensure that you remove the handler.

When a message arrives, the recipient receives an onXXXMessage callback. Each callback contains one or more messages. You can traverse the message list, and parse and render these messages in this callback and render these messages.

// Use `addEventHandler` to listen for callback events.
chatClient.addEventHandler("handlerId", {
  // Occurs when the app is connected.
  onConnected: function (message) {},
  // Occurs when the connection is lost.
  onDisconnected: function (message) {},
  // Occurs when the text message is received.
  onTextMessage: function (message) {},
  // Occurs when the image message is received.
  onImageMessage: function (message) {},
  // Occurs when the CMD message is received.
  onCmdMessage: function (message) {},
  // Occurs when the audio message is received.
  onAudioMessage: function (message) {},
  // Occurs when the location message is received.
  onLocationMessage: function (message) {},
  // Occurs when the file message is received.
  onFileMessage: function (message) {},
  // Occurs when the custom message is received.
  onCustomMessage: function (message) {},
  // Occurs when the video message is received.
  onVideoMessage: function (message) {},
  // Occurs when the local network is connected.
  onOnline: function () {},
  // Occurs when the local network is disconnected.
  onOffline: function () {},
  // Occurs when an error occurs.
  onError: function (message) {},
  // Occurs when the message is recalled.
  onRecallMessage: function (message) {},
  // Occurs when the message is received.
  onReceivedMessage: function (message) {},
  // Occurs when the message delivery receipt is received.
  onDeliveredMessage: function (message) {},
  // Occurs when the message read receipt is received.
  onReadMessage: function (message) {},
  // Occurs when the conversation read receipt is received.
  onChannelMessage: function (message) {},
});

Recall a message

After a message is sent, you can recall it. The recallMessage method recalls a message saved on the server, whether it is a historical message, offline message or a roaming message.

The default time limit for recalling a message is two minutes. You can extend this time frame to up to 7 days in Agora Console. To do so, select a project that enables Agora Chat, then click Configure > Features > Message recall.

The following permission rules apply to message recall:

  • In one-to-one chats, only the message sender can recall a message they sent. If the message has expired, the recall fails.
  • In chat groups and chat rooms, regular members can recall only the messages they sent, and the recall fails if the message has expired. Since SDK v1.4.0, the chat group owner, chat room owner, and admins can recall messages sent by other members, even after those messages have expired.

  1. Except CMD messages, you can recall all types of message.
  2. If an attachment message, like an image, voice, video, or file message, is recalled, the attachment of the message is also deleted.
const options = {
  // The ID of the message to recall.
  mid: "msgId",
  // The message recipient.
  to: "userID",
  // The chat type: singleChat, groupChat, and chatRoom respectively indicate one-to-one chat, group chat, and room chat.
  chatType: "singleChat",
};
chatClient
  .recallMessage(options)
  .then((res) => {
    console.log("success", res);
  })
  .catch((error) => {
    // Recalling the message fails, probably because the time limit for recalling the message is exceeded.
    console.log("fail", error);
  });

You can also use onRecallMessage to listen for the message recall state:

chatClient.addEventHandler('handlerId',{
   onRecallMessage: (msg) =>  {
       // You can insert a message here, for example, XXX has recalled a message.
        console.log('Recalling the message succeeds',msg)
   },
})

Send an attachment message

Voice, image, video, and file messages are essentially attachment messages. When sending an attachment message, the SDK takes the following steps:

  1. Uploads the attachment to the server and gets the information of the attachment file on the server.
  2. Sends the attachment message, which contains the basic information of the message, and the path to the attachment file on the server.

For the attachment messages, you can upload the attachment to your server, instead of the Agora server, before sending an attachment message. In this case, you need to set the useOwnUploadFun parameter in the connection class to true during SDK initialization. For example, to send an image message, you can call sendPrivateUrlImg to pass in the image URL after uploading the image attachment.

function sendPrivateUrlImg() {
  const options = {
    chatType: "singleChat",
    // Message type.
    type: "img",
    // Image URL
    url: "img url",
    // Message sender: the user ID of the peer user for one-to-one chat; group ID for group chat; chat room ID for room chat.
    to: "username",
  };
  // Create an image message.
  const msg = AgoraChat.message.create(options);
  // Call the `send` method to send the image message.
  chatClient.send(msg);
}

For image and video messages, the SDK also automatically generates a thumbnail. When receiving an attachment message, the SDK takes the following steps:

  • For voice messages, the SDK automatically downloads the audio file.
  • For image and video messages, the SDK automatically downloads the thumbnail of the image or video. To download the files, you need to call the download method.
  • For file messages, you need to call the download method to download the file.

Send a voice message

Before sending a voice message, you should implement audio recording on the app level, which provides the URI and duration of the recorded audio file. Refer to the following code example to create and send a voice message:

function sendAudioMessage() {
  // Select the local audio file.
  const input = document.getElementById("audio");
  // Turn the audio file to a binary file.
  const file = AgoraChat.utils.getFileUrl(input);
  const allowType = {
    mp3: true,
    amr: true,
    wmv: true,
  };
  if (file.filetype.toLowerCase() in allowType) {
    const options = {
      // Set the message type
      type: "audio",
      file: file,
      // Set the length of the audio file in seconds.
      length: "3",
      // Set the username of the message receiver.
      to: "username",
      // Set the chat type.
      chatType: "singleChat",
      // Occurs when the audio file fails to be uploaded.
      onFileUploadError: function () {
        console.log("onFileUploadError");
      },
      // Reports the progress of uploading the audio file.
      onFileUploadProgress: function (e) {
        console.log(e);
      },
      // Occurs when the audio file is successfully uploaded.
      onFileUploadComplete: function () {
        console.log("onFileUploadComplete");
      },
      ext: { file_length: file.data.size },
    };
    // Create a voice message.
    const msg = AgoraChat.message.create(options);
    // Call send to send the voice message.
    chatClient
      .send(msg)
      .then((res) => {
        // Occurs when the audio file is successfully sent.
        console.log("Success");
      })
      .catch((e) => {
        // Occurs when the audio file fails to be sent
        console.log("Fail");
      });
  }
}

Send an image message

Refer to the following code example to create and send an image message:

function sendImgMessage() {
  // Select the local image file.
  const input = document.getElementById("image");
  // Turn the image to a binary file.
  const file = AgoraChat.utils.getFileUrl(input);
  const allowType = {
    jpg: true,
    gif: true,
    png: true,
    bmp: true,
  };
  if (file.filetype.toLowerCase() in allowType) {
    const options = {
      // Set the message type.
      type: "img",
      file: file,
      ext: {
        // Set the image file length.
        file_length: file.data.size,
      },
      // Set the username of the message receiver.
      to: "username",
      // Set the chat type.
      chatType: "singleChat",
      // Occurs when the image file fails to be uploaded.
      onFileUploadError: function () {
        console.log("onFileUploadError");
      },
      // Reports the progress of uploading the image file.
      onFileUploadProgress: function (e) {
        console.log(e);
      },
      // Occurs when the image file is successfully uploaded.
      onFileUploadComplete: function () {
        console.log("onFileUploadComplete");
      },
    };
    // Create a voice message.
    const msg = AgoraChat.message.create(options);
    // Call send to send the voice message.
    chatClient
      .send(msg)
      .then((res) => {
        // Occurs when the audio file is successfully sent.
        console.log("Success");
      })
      .catch((e) => {
        // Occurs when the audio file fails to be sent
        console.log("Fail");
      });
  }
}

Send and receive a GIF image message

Since SDK v1.4.0, you can send and receive GIF image messages. A GIF image message is a subtype of image message that is not compressed when sent. Thumbnail generation is the same as for a regular image message.

To send a GIF image message, set isGif to true in the message options when you create the image message:

const options = {
  chatType: "singleChat",
  type: "img",
  to: "userId",
  file: file,
  isGif: true,
};
const msg = AgoraChat.message.create(options);
chatClient.send(msg);

When the recipient receives the message, they receive the onImageMessage callback. Read the isGif property of the message. If it is true, the message is a GIF image message.

chatClient.addEventHandler("handlerId", {
  onImageMessage: function (message) {
    if (message.isGif) {
      // The image is a GIF image.
    }
  },
});

Send a video message

Before sending a video message, you should implement video capturing on the app level, which provides the duration of the captured video file. Refer to the following code example to create and send a video message:

function sendVideoMessage() {
  // Select the local video file.
  const input = document.getElementById("video");
  // Turn the video to a binary file.
  const file = AC.utils.getFileUrl(input);
  const allowType = {
    mp4: true,
    wmv: true,
    avi: true,
    rmvb: true,
    mkv: true,
  };
  if (file.filetype.toLowerCase() in allowType) {
    const options = {
      // Set the message type
      type: "video",
      file: file,
      // The username of the message receiver
      to: "username",
      // Set the chat type
      chatType: "singleChat",
      onFileUploadError: function () {
        // Occurs when the file fails to be uploaded.
        console.log("onFileUploadError");
      },
      onFileUploadProgress: function (e) {
        // Reports the progress of uploading the file.
        console.log(e);
      },
      onFileUploadComplete: function () {
        // Occurs when the file is uploaded.
        console.log("onFileUploadComplete");
      },
      ext: { file_length: file.data.size },
    };
    // Create a video message.
    const msg = AgoraChat.message.create(options);
    // Call send to send the video message.
    chatClient
      .send(msg)
      .then((res) => {
        // Occurs when the message is sent.
        console.log("success");
      })
      .catch((e) => {
        // Occurs when the message fails to be sent, for example, because the local user is muted or blocked.
        console.log("Fail");
      });
  }
}

Send a file message

Refer to the following code example to create, send, and receive a file message:

function sendFileMessage() {
  // Select the local file.
  const input = document.getElementById("file");
  // Turn the file message to a binary file.
  const file = AgoraChat.utils.getFileUrl(input);
  const allowType = {
    jpg: true,
    gif: true,
    png: true,
    bmp: true,
    zip: true,
    txt: true,
    doc: true,
    pdf: true,
  };
  if (file.filetype.toLowerCase() in allowType) {
    const options = {
      // Set the message type.
      type: "file",
      file: file,
      // Set the username of the message receiver.
      to: "username",
      // Set the chat type.
      chatType: "singleChat",
      // Occurs when the file fails to be uploaded.
      onFileUploadError: function () {
        console.log("onFileUploadError");
      },
      // Reports the progress of uploading the file.
      onFileUploadProgress: function (e) {
        console.log(e);
      },
      // Occurs when the file is uploaded.
      onFileUploadComplete: function () {
        console.log("onFileUploadComplete");
      },
      ext: { file_length: file.data.size },
    };
    // Create a file message.
    const msg = AgoraChat.message.create(options);
    // Call send to send the file message.
    chatClient
      .send(msg)
      .then((res) => {
        // Occurs when the file message is sent.
        console.log("Success");
      })
      .catch((e) => {
        // Occurs when the file message fails to be sent.
        console.log("Fail");
      });
  }
}

Send a location message

To send and receive a location message, you need to integrate a third-party map service provider. When sending a location message, you get the longitude and latitude information of the location from the map service provider; when receiving a location message, you extract the received longitude and latitude information and display the location on the third-party map.

const sendLocMessage = () => {
  let coords;
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function (position) {
      coords = position.coords;
      const options = {
        chatType: "singleChat",
        type: "loc",
        to: "username",
        addr: "London",
        buildingName: "Digital Building",
        lat: Math.round(coords.latitude),
        lng: Math.round(coords.longitude),
      };
      const msg = AgoraChat.message.create(options);
      chatClient
        .send(msg)
        .then((res) => {
          console.log("Send message success", res);
        })
        .catch((e) => {
          console.log("Send message fail", e);
        });
    });
  }
};

Send a CMD message

CMD messages are command messages that instruct a specified user to take a certain action. The recipient deals with the command messages themselves. The following code sample shows how to send and receive a CMD message:

const options = {
  // Set the message type.
  type: "cmd",
  // Set the chat type.
  chatType: "singleChat",
  // The username of the message receiver.
  to: "username",
  // Set the custom action.
  action: "action",
  // Set the extended message.
  ext: { extmsg: "extends messages" },
};
// Create a CMD message.
const msg = AgoraChat.message.create(options);
// Call send to send the CMD message.
chatClient
  .send(msg)
  .then((res) => {
    // Occurs when the message is sent.
    console.log("Success");
  })
  .catch((e) => {
    // Occurs when the message fails to be sent.
    console.log("Fail");
  });

Send a customized message

Custom messages are self-defined key-value pairs that include the message type and the message content. The following code example shows how to create and send a customized message:

function sendCustomMessage() {
  // Set the custom event.
  const customEvent = "customEvent";
  // Set the custom message content with key-value pairs.
  const customExts = {};
  const options = {
    // Set the message type.
    type: "custom",
    // Set the username of the message receiver.
    to: "username",
    // Set the chat type.
    chatType: "singleChat",
    customEvent,
    customExts,
    // The extended field. Do not set it as null.
    ext: {},
  };
  // Create a custom message.
  const msg = AgoraChat.message.create(options);
  // Call send to send the custom message.
  chatClient
    .send(msg)
    .then((res) => {
      // Occurs when the message is sent.
      console.log("Success");
    })
    .catch((e) => {
      // Occurs when the message fails to be sent.
      console.log("Fail");
    });
}

Use message extensions

If the message types listed above do not meet your requirements, you can use message extensions to add attributes to the message. This can be applied in more complicated messaging use-cases.

function sendTextWithExt() {
  const options = {
    type: "txt",
    msg: "message content",
    to: "username",
    chatType: "singleChat",
    // Set the message extension.
    ext: {
      key1: "Self-defined value1",
      key2: {
        key3: "Self-defined value3",
      },
    },
  };
  const msg = AgoraChat.message.create(options);
  // Call send to send the extended message.
  chatClient
    .send(msg)
    .then((res) => {
      console.log("send private text Success");
    })
    .catch((e) => {
      console.log("Send private text error");
    });
}

Forward multiple messages

Supported types for forwarded messages include text, images, audio & video files, attachment, and custom messages. A user can create a combined message with a list of original messages and send it. When receiving a combined message, the recipient can select it and other messages to create a new layered combined message. A combined message can contain up to 10 layers of messages, with at most 300 messages at each layer.

To forward and receive combined messages, refer to the following code:

  1. Create a combined message using multiple message IDs:

    const options = {
      chatType: "singleChat",
      type: "combine",
      to: "userId",
      compatibleText:
        "Your SDK does not support combined messages. Please upgrade.",
      title: "Chat history",
      summary: "hi",
      messageList: [
        // message body
        {
          type: "txt",
          chatType: "singleChat",
          // ...
        },
      ],
      onFileUploadComplete: (data) => {
        options.url = data.url;
      },
    };
    const msg = AgoraChat.message.create(options);
    chatClient
      .send(msg)
      .then((res) => {
        console.log("Succeeded in sending the message", res);
      })
      .catch((err) => {
        console.log("Failed to send the message", err);
      });
  2. Download and parse combined messages:

    chatClient
      .downloadAndParseCombineMessage({
        url: msg.url,
        secret: msg.secret,
      })
      .then((res) => {
        console.log("The list of original messages obtained after parsing", res);
      });

For further details see Multiple messages forwarding limitations.

Modify sent messages

For messages that have been sent successfully, the SDK supports modifying the message content.

  • Before SDK v1.4.0, you could only modify text messages sent in one-to-one chats and chat groups.
  • Since SDK v1.4.0, you can modify various message types sent in one-to-one chats, chat groups, and chat rooms:
    • Text and custom messages: modify both the message body and the extension fields (ext).
    • File, video, voice, image, location, and combined messages: modify the extension fields (ext) only.
    • Command messages: modification is not supported.

To modify a sent message, create a message that contains the new content and pass it to modifyMessage with the ID of the original message. To listen for messages modified by other users, register the onModifiedMessage event.

// Register the message modification event.
chatClient.addEventHandler("modifiedMessage", {
  onModifiedMessage: (message) => {
    console.log("onModifiedMessage", message);
  },
});

// Text message: you can modify the msg and ext fields.
const textMessage = AgoraChat.message.create({
  chatType: "singleChat",
  type: "txt",
  to: "to",
  msg: "message content",
  ext: { key: "new value" },
});

// Custom message: you can modify the customEvent, customExts, and ext fields.
const customMessage = AgoraChat.message.create({
  chatType: "singleChat",
  type: "custom",
  to: "to",
  customEvent: "new event",
  customExts: { key: "new value" },
  ext: { key: "new value" },
});

// File, image, voice, video, location, or combined message: you can modify the ext field only.
const imageMessage = AgoraChat.message.create({
  chatType: "singleChat",
  type: "img",
  url: "origin message url",
  to: "to",
  ext: { key: "new value" },
});

chatClient
  .modifyMessage({
    messageId: "origin message id",
    modifiedMessage: textMessage,
  })
  .then((res) => {
    console.log("modify msg success", res.modifiedInfo);
  })
  .catch((e) => {
    console.log("modify failed", e);
  });

For further details see Sent message modification limitations.

Next steps

After implementing sending and receiving messages, you can refer to the following documents to add more messaging functionalities to your app: