Skip to main content

Send and receive messages

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.

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

This page shows how to implement sending and receiving these messages using the Chat SDK.

Understand the tech

The Chat SDK uses the ChatManager class to send, receive, and withdraw messages.

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 sendMessage to send the message.
  3. The message recipient calls addMessageListener to listens for message events and receives the message in the OnMessageReceived 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.
  • 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 ChatMessage class to create a text message, and send the message.


_19
// Call createTextSendMessage to create a text message. Set content as the content of the text message, and toChatUsernames the user ID of the message recipient.
_19
ChatMessage message = ChatMessage.createTxtSendMessage(content, toChatUsername);
_19
// Set the message type using the MessageType attribute in Message.
_19
// You can set `MessageType` as `Chat`, `Group`, or `Room`, which indicates whether to send the message to a peer user, a chat group, or a chat room.
_19
message.setChatType(ChatType.GroupChat);
_19
// Calls setMessageStatusCallback to set the callback instance to get the status of messaging sending. You can update the status of messages in this callback, for example, adding a tip when the message sending fails.
_19
message.setMessageStatusCallback(new CallBack() {
_19
@Override
_19
public void onSuccess() {
_19
showToast("Message sending succeeds");
_19
dialog.dismiss();
_19
}
_19
@Override
_19
public void onError(int code, String error) {
_19
showToast("Message sending fails");
_19
}
_19
});
_19
// Send the message
_19
ChatClient.getInstance().chatManager().sendMessage(message);

Receive a message

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

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


_11
MessageListener msgListener = new MessageListener()
_11
{
_11
// Traverse the message list, and parse and render the messages.
_11
@Override
_11
public void onMessageReceived(List<ChatMessage> messages)
_11
{
_11
_11
}
_11
};
_11
ChatClient.getInstance().chatManager().addMessageListener(msgListener);
_11
ChatClient.getInstance().chatManager().removeMessageListener(msgListener);

Recall a message

Two minutes after a user sends a message, this user can withdraw it. Contact support@agora.io if you want to adjust the time limit.


_7
try {
_7
ChatClient.getInstance().chatManager().recallMessage(message);
_7
EMLog.d("TAG", "Recalling message succeeds");
_7
} catch (ChatException e) {
_7
e.printStackTrace();
_7
EMLog.e("TAG", "Recalling message fails: "+e.getDescription());
_7
}

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


_4
/**
_4
* Occurs when a received message is recalled.
_4
*/
_4
void onMessageRecalled(List<ChatMessage> messages);

Send and receive an attachment message

Voice, image, video, and file messages are essentially attachment messages. This section introduces how to send these types of messages.

Send and receive 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:


_6
// Set voiceUri as the local URI of the audio file, and duration as the length of the file in seconds.
_6
ChatMessage message = ChatMessage.createVoiceSendMessage(voiceUri, duration, toChatUsername);
_6
// Sets the chat type as one-to-one chat, group chat, or chatroom.
_6
if (chatType == CHATTYPE_GROUP)
_6
message.setChatType(ChatType.GroupChat);
_6
ChatClient.getInstance().chatManager().sendMessage(message);

When the recipient receives the message, refer to the following code example to get the audio file:


_5
VoiceMessageBody voiceBody = (VoiceMessageBody) msg.getBody();
_5
// Retrieves the URL of the audio file on the server.
_5
String voiceRemoteUrl = voiceBody.getRemoteUrl();
_5
// Retrieves the URI if the audio file on the local device.
_5
Uri voiceLocalUri = voiceBody.getLocalUri();

Send and receive an image message

By default, the SDK compresses the image file before sending it. To send the original file, you can set original as true.

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


_6
// Set imageUri as the URI of the image file on the local device. false means not to send the original image. The SDK compresses image files that exceeds 100K before sending them.
_6
ChatMessage message = ChatMessage.createImageSendMessage(imageUri, false, toChatUsername);
_6
// Sets the chat type as one-to-one chat, group chat, or chatroom.
_6
if (chatType == CHATTYPE_GROUP)
_6
message.setChatType(ChatType.GroupChat);
_6
ChatClient.getInstance().chatManager().sendMessage(message);

When the recipient receives the message, refer to the following code example to get the thumbnail and attachment file of the image message:


_10
// Retrieves the thumbnail and attachment of the image file.
_10
ImageMessageBody imgBody = (ImageMessageBody) message.getBody();
_10
// Retrieves the image file the server.
_10
String imgRemoteUrl = imgBody.getRemoteUrl();
_10
// Retrieves the image thumbnail from the server.
_10
String thumbnailUrl = imgBody.getThumbnailUrl();
_10
// Retrieves the URI of the image file on the local device.
_10
Uri imgLocalUri = imgBody.getLocalUri();
_10
// Retrieves the URI of the image thumbnail on the local device.
_10
Uri thumbnailLocalUri = imgBody.thumbnailLocalUri();

If ChatClient.getInstance().getOptions().getAutodownloadThumbnail() is set as true on the recipient's client, the SDK automatically downloads the thumbnail after receiving the message. If not, you need to call ChatClient.getInstance().chatManager().downloadThumbnail(message) to download the thumbnail and get the path from the thumbnailLocalUri member in messageBody.

Send and receive 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:


_8
String thumbPath = getThumbPath(videoUri);
_8
// Set videoUri as the URI of the video file on the local device and videoLength as the length of the file in seconds,
_8
// Set thumbPath as the video capturing local path.
_8
ChatMessage message = ChatMessage.createVideoSendMessage(videoUri, thumbPath, videoLength, toChatUsername);
_8
// Set the chat type as one-to-one chat, group chat, or chatroom.
_8
if (chatType == CHATTYPE_GROUP)
_8
message.setChatType(ChatType.GroupChat);
_8
ChatClient.getInstance().chatManager().sendMessage(message);

By default, when the recipient receives the message, the SDK downloads the thumbnail of the video message.

If you do not want the SDK to automatically download the video thumbnail, set ChatClient.getInstance().getOptions().setAutodownloadThumbnail as false, and to download the thumbnail, you need to call ChatClient.getInstance().chatManager().downloadThumbnail(message), and get the path of the thumbnail from the thumbnailLocalUri member in messageBody.

To download the actual video file, call ChatClient.getInstance().chatManager().downloadAttachment(message), and get the path of the video file from the getLocalUri member in messageBody.


_31
// If you received a message with video attachment, you need to download the attachment before you open it.
_31
if (message.getType() == ChatMessage.Type.VIDEO)
_31
{
_31
VideoMessageBody messageBody = (VideoMessageBody)message.getBody();
_31
// Get the URL of the video on the server.
_31
String videoRemoteUrl = messageBody.getRemoteUrl();
_31
CallBack callBack = new CallBack()
_31
{
_31
@OverRide
_31
public void onSuccess()
_31
{
_31
// Download successfully
_31
}
_31
@Override
_31
public void onProgress(int progress, String status)
_31
{
_31
// Show progress
_31
}
_31
@Override
_31
public void onError(int code, String error)
_31
{
_31
// Download failed
_31
}
_31
};
_31
// Set Callback to know whether the download is finished.
_31
message.setMessageStatusCallback(callBack);
_31
// Download the video.
_31
ChatClient.getInstance().chatManager().downloadAttachment(message);
_31
// After the download finishes, get the URI of the local file.
_31
Uri videoLocalUri = messageBody.getLocalUri();
_31
}

Send and receive a file message

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


_5
// Set fileLocalUri as the URI of the file message on the local device.
_5
ChatMessage message = ChatMessage.createFileSendMessage(fileLocalUri, toChatUsername);
_5
// Sets the chat type as one-to-one chat, group chat, or chatroom.
_5
if (chatType == CHATTYPE_GROUP) message.setChatType(ChatType.GroupChat);
_5
ChatClient.getInstance().chatManager().sendMessage(message);

While sending a file message, refer to the following sample code to get the progress for uploading the attachment file:


_12
// Calls setMessageStatusCallback to set the callback instance to listen for the state of messaging sending. You can update the message states in this callback.
_12
message.setMessageStatusCallback(new CallBack() {
_12
@OverRide
_12
public void onSuccess() {
_12
// Send message success
_12
}
_12
@OverRide
_12
public void onError(int code, String error) {
_12
// Send message failed
_12
}
_12
});
_12
ChatClient.getInstance().chatManager().sendMessage(message);

When the recipient receives the message, call the downloadAttachment method and then refer to the following code example to get the attachment file:


_25
CallBack callBack = new CallBack() {
_25
@OverRide
_25
public void onSuccess() {
_25
// Download successfully
_25
}
_25
@Override
_25
public void onProgress(int progress, String status) {
_25
// Show progress
_25
}
_25
@Override
_25
public void onError(int code, String error) {
_25
// Download failed
_25
}
_25
};
_25
// Set Callback to know whether the download is finished.
_25
message.setMessageStatusCallback(callBack);
_25
// Download the video.
_25
ChatClient.getInstance().chatManager().downloadAttachment(message);
_25
_25
// After the download finishes, get the URI of the local file.
_25
NormalFileMessageBody fileMessageBody = (NormalFileMessageBody) message.getBody();
_25
// Retrieves the file from the server.
_25
String fileRemoteUrl = fileMessageBody.getRemoteUrl();
_25
// Retrieves the file from the local device.
_25
Uri fileLocalUri = fileMessageBody.getLocalUri();

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 displays the location on the third-party map.


_7
// Sets the latitude and longitude information of the address.
_7
ChatMessage message = ChatMessage.createLocationSendMessage(latitude, longitude, locationAddress, toChatUsername);
_7
// Sets the latitude and longitude information of the address.
_7
ChatMessage message = ChatMessage.createLocationSendMessage(latitude, longitude, locationAddress, toChatUsername);
_7
// Sets the chat type as one-to-one chat, group chat, or chatroom.
_7
if (chatType == CHATTYPE_GROUP) message.setChatType(ChatType.GroupChat);
_7
ChatClient.getInstance().chatManager().sendMessage(message);

Send and receive 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.

  • CMD messages are not stored in the local database.
  • Actions beginning with em_ and easemob:: are internal fields. Do not use them.

_12
ChatMessage cmdMsg = ChatMessage.createSendMessage(ChatMessage.Type.CMD);
_12
// Sets the chat type as one-to-one chat, group chat, or chat room
_12
cmdMsg.setChatType(ChatType.GroupChat)String action="action1";
_12
// You can customize the action
_12
CmdMessageBody cmdBody = new CmdMessageBody(action);String toUsername = "test1";
_12
ChatMessage cmdMsg = ChatMessage.createSendMessage(ChatMessage.Type.CMD);
_12
// Sets the chat type as one-to-one chat, group chat, or chat room
_12
cmdMsg.setChatType(ChatType.GroupChat)String action="action1";
_12
// You can customize the action
_12
CmdMessageBody cmdBody = new CmdMessageBody(action);String toUsername = "test1";
_12
// Specify a username to send the CMD message.
_12
cmdMsg.setTo(toUsername);cmdMsg.addBody(cmdBody); ChatClient.getInstance().chatManager().sendMessage(cmdMsg);

To notify the recipient that a CMD message is received, use a separate delegate so that users can deal with the message differently.


_11
MessageListener msgListener = new MessageListener()
_11
{
_11
// Occurs when the message is received
_11
@Override
_11
public void onMessageReceived(List<ChatMessage> messages) {
_11
}
_11
// Occurs when a CMD message is received
_11
@Override
_11
public void onCmdMessageReceived(List<ChatMessage> messages) {
_11
}
_11
}

Implement typing indicators via CMD messages

Typing indicators signify when other users are typing a message. This feature enables users to communicate efficiently and sets users' expectations about new interactions in a chat app. You can implement typing indicators via CMD messages.

The following diagram explains how typing indicators work.

Listen for the input status of user A. Once there is text input, the input status is sent to user B through a command message, and user B receives the input status that indicates that user A is typing.

  • User A sends a message to user B indicating the starting input status.
  • After receiving the message, if user B is currently on the chat page of with user A, the typing indicator of user A is displayed.
  • If user B receives the ending input status of user A or have not received from user A again after a few seconds, the typing indicator is automatically canceled.

Note: User A can set the sending interval between CMD messages as needed.

The following code example shows how to send a CMD message of the input status.


_16
EditText.addTextChangedListener(new TextWatcher() {
_16
@Override
_16
public void onTextChanged(CharSequence s, int start, int before, int count) {
_16
sendCmdMessage(ACTION_TYPING_BEGIN);
_16
_16
});
_16
_16
public void sendCmdMessage(String action) {
_16
ChatMessage beginMsg = ChatMessage.createSendMessage(ChatMessage.Type.CMD);
_16
CmdMessageBody body = new CmdMessageBody(action);
_16
// Only deliver this CMD msg to online users.
_16
body.deliverOnlineOnly(true);
_16
beginMsg.addBody(body);
_16
beginMsg.setTo(toChatUsername);
_16
ChatClient.getInstance().chatManager().sendMessage(beginMsg);
_16
}

The following code example shows how to receive and parse a CMD message of the input status.


_24
ChatManager.getInstance().addMessageListener(new MessageListener() {
_24
_24
@Override
_24
public void onCmdMessageReceived(List<ChatMessage> messages) {
_24
for (final ChatMessage msg : messages) {
_24
final CmdMessageBody body = (CmdMessageBody) msg.getBody();
_24
EMLog.i(TAG, "Receive cmd message: " + body.action() + " - " + body.isDeliverOnlineOnly());
_24
EaseThreadManager.getInstance().runOnMainThread(() -> {
_24
if(TextUtils.equals(msg.getFrom(), conversationId)) {
_24
if (TextUtils.equals(action, EaseChatLayout.ACTION_TYPING_BEGIN)) {
_24
binding.subTitle.setText(getString(R.string.alert_during_typing));
_24
binding.subTitle.setVisibility(View.VISIBLE);
_24
} else if (TextUtils.equals(action, EaseChatLayout.ACTION_TYPING_END)) {
_24
setDefaultTitle();
_24
}
_24
if(typingHandler != null) {
_24
typingHandler.removeMessages(MSG_OTHER_TYPING_END);
_24
typingHandler.sendEmptyMessageDelayed(MSG_OTHER_TYPING_END, OTHER_TYPING_SHOW_TIME);
_24
}
_24
}
_24
});
_24
}
_24
}
_24
});

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:


_12
ChatMessage customMessage = ChatMessage.createSendMessage(ChatMessage.Type.CUSTOM);
_12
// Set event as the customized message type, for example, gift.
_12
String event = "gift";
_12
CustomMessageBody customBody = new CustomMessageBody(event);
_12
// The data type of params is Map<String, String>.
_12
customBody.setParams(params);
_12
customMessage.addBody(customBody);
_12
// Specifies the user ID to receive the message, as Chat ID, chat group ID, or chat room ID.
_12
customMessage.setTo(to);
_12
// Sets the chat type as one-to-one chat, group chat, or chat room
_12
customMessage.setChatType(chatType);
_12
ChatClient.getInstance().chatManager().sendMessage(customMessage);

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


_9
ChatMessage message = ChatMessage.createTextSendMessage(content, toChatUsername);
_9
// Adds message attributes.
_9
message.setAttribute("attribute1", "value");
_9
message.setAttribute("attribute2", true);
_9
// Sends the message.
_9
ChatClient.getInstance().chatManager().sendMessage(message);
_9
// Retrieves the message attributes when receiving the message.
_9
String attribute1 = message.getStringAttribute("attribute1",null);
_9
boolean attribute2 = message.getBooleanAttribute("attribute2", false);

Next steps

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