Instant Messaging
Android
Getting Started
Introduction
Overview
Benefits
Features
Features
Account Integration and Login
Group Chat
Chat Room
Chat Room Tags
Multi-device Login
Statistics Monitoring
Limits
Integration
Interface Overview
Integrate and Initialize SDK
Messaging
Basic Messaging
Message History
Message Sending
Message Receiving
Recent Chats
Server Sessions
User Profile
User Relationship
Online Status Subscription
Push and Message Alert
Superteam
Chat Room
Moderation
Chat Extension
Miscellaneous Features
Best Practice
Traffic Control in Chat Rooms
Reference
API Reference
Status Codes

Message Sending

Update time: 2022/06/28 17:11:37

Overview

The SDK provides a set of messaging management features, such as sending and receiving messages, storing messages, uploading and downloading attachments. You are allowed to send text, audio messages, image, video, file, location, and custom messages.

The message structure is IMMessage and different message types are distinguished by MsgTypeEnum.IMMessage does not support inheritance or extension.

  • Parameters for IMMessage
Return Method Description
String getUuid() Get message client ID.
long getServerId() Get message server ID.
String getSessionId() Get chat object ID or group ID.
String getFromAccount() Get account of the message sender.
SessionTypeEnum getSessionType() Get session type, for example, group chat.
int getFromClientType() Get type of message sender.
String getFromNick() Get display name of message sender.
MsgTypeEnum getMsgType() Get message type.
int getSubtype() Get subtype of message.
void setSubtype Set subtype of message.
MsgStatusEnum getStatus() Get message sending or receiving status.
MsgDirectionEnum getDirect() Get message direction.
boolean isInBlocklist() Send a message to a recipient, and determine whether you are added to a blocklist.
String getContent() Get message content. Except text message and tip, others are null.
long getTime() Get message time. Unit: ms.
void setAttachment Set message attachment object. See MsgAttachment parameter.
MsgAttachment getAttachment() Get message attachment object. It is valid only when getMsgType() returns non-text content.
AttachStatusEnum getAttachStatus() Get sending or receiving status of message attachment.
CustomMessageConfig getConfig() Get message configuration See CustomMessageConfig parameter.
Map<String, Object> getRemoteExtension() Get the extension field.
void setRemoteExtension
(Map
remoteExtension)
Set extension field
(The field will be sent to other clients),
with max. length 1024.
Developers must ensure that the Map can be transformed into JsonObject.
Map<String, Object> getLocalExtension() Get local extension field (valid for local client only).
void setLocalExtension
(Map
localExtension)
Set local extension field
(The field is valid for local client and will not be sent to other clients),
with max. length 1024.
Developers must ensure that the Map can be transformed into JsonObject.
String getCallbackExtension Get customer extension field returned from the third-party invocation.
String getPushContent() Get APNS text.
void setPushContent(String pushContent) Set push content.
Map<String, Object> getPushPayload() Get push configuration.
void setPushPayload
(Map
pushPayload)
Set push property
(the developer must ensure that the Map can be transformed into JsonObject),
with max. length 2048.
MemberPushOption getMemberPushOption() Get forced push property of group members.
boolean isRemoteRead() Determine that message is read by recipient in one-to-one chat scenario.
NIMAntiSpamOption getNIMAntiSpamOption() Get anti-spam configuration option.
String getYiDunAntiCheating() Get GuardEase Anti-spam field.
void setYiDunAntiCheating Set GuardEase Anti-spam field, with Json format.
boolean isSessionUpdate() Determine that message is updated to session service.
void setSessionUpdate Set whether message is updated to session service.

The available message types:

MsgTypeEnum parameter Description
text Text message.
image Image message.
audio Audio message.
video Video message.
location Location message.
file File message.
avchat Message of audio & video call event.
notification Notification message.
tip Message alert.
custom Custom message.

For information about message receiving, read receipt, and broadcast message receiving, see Message Receiving.

Sending messages

You must create corresponding message object using MessageBuilder provided interface and then call sendMessage interface under MsgService to send messages.

/**
 * Send a message
 * @param msg - Message body to be sent, constituted by {@link MessageBuilder}
 * @param resend - If a message is sent unsuccessfully and then re-sent, it is marked as "true". Otherwise, as "false"
 * @return InvocationFuture - Configurable callback feature. It can be invoked only when the message is sent. If an error occurs, detailed error code will be returned.
 */
public InvocationFuture<Void> sendMessage(IMMessage msg, boolean resend);

Sending a text message

Creation prototype of text messages.

/**
 * Create a text message.
 *
 * @param sessionId - Chat object ID.
 * @param sessionType session type.
 * @param text - Content of text messages.
 * @return IMMessage - Generated message object.
 */
public static IMMessage createTextMessage(String sessionId, SessionTypeEnum sessionType, String text);
  • Parameters
Parameter Description
sessionId Chat object ID. It is user account for one-to-one chat and group ID for group chat.
sessionType Chat type. SessionTypeEnum.peer-to-peer is one-to-one chat type and SessionTypeEnum. group is group chat type.
text Content of text messages.
  • Example
// The account is taken for an example.
String account = "testAccount";
// The one-to-one chat type is taken for an example.
SessionTypeEnum sessionType = SessionTypeEnum.peer-to-peer;
String text = "this is an example";
// Create a text message.
IMMessage textMessage = MessageBuilder.createTextMessage(account, sessionType, text);
// Send to the other party.
NIMClient.getService(MsgService.class).sendMessage(textMessage, false).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {

                }

                @Override
                public void onFailed(int code) {
                    
                }

                @Override
                public void onException(Throwable exception) {

                }
            });

Send image messages

Creation prototype of image messages:

/**
 * Create an image message.
 *
 * @param sessionId - Chat object ID.
 * @param sessionType Session type.
 * @param file - Image file.
 * @param displayName - Display name of an image file. It can be different from file name.
 * @param nosTokenSceneKey - File resource scene.
 * @return IMMessage - Generated message object.
 */
public static IMMessage createImageMessage(String sessionId, SessionTypeEnum sessionType, File file, String displayName);

// Or: Create an image message and specify the file resource scene used for uploading the specified image.
public static IMMessage createImageMessage(String sessionId, SessionTypeEnum sessionType, File file, String displayName, String nosTokenSceneKey); 
  • Parameters
Parameter Description
sessionId Chat object ID. It is user account for one-to-one chat and group ID for group chat.
sessionType Chat type. SessionTypeEnum.peer-to-peer is one-to-one chat type and SessionTypeEnum.Group is group chat type.
file Image file object.
displayName Display name of image file. It can be different from file name or set to "null".
nosTokenSceneKey nos scene used for uploading image. Default value is NimNosSceneKeyConstant.NIM_DEFAULT_IM. See "File resource scenario".
  • Example
// The account is an example. Please register.
String account = "testAccount";
// The one-to-one chat type is taken for an example.
SessionTypeEnum sessionType = SessionTypeEnum.peer-to-peer;
// Example image. It requires developers to have the image under related directory.
File file = new File("/sdcard/test.jpg");
// Create an image message
IMMessage message = MessageBuilder.createImageMessage(account, sessionType, file, file.getName());
// Or: Create an image message and specify the file resource scene used for uploading the specified image. "nos_scene_key" must be replaced with the one configured by developers.
IMMessage message = MessageBuilder.createImageMessage(account, sessionType, file, file.getName(),"nos_scene_key");
// Send to the other party
NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {

                }

                @Override
                public void onFailed(int code) {
                    
                }

                @Override
                public void onException(Throwable exception) {

                }
            });

Send an audio message

Creation prototype of audio messages:

/**
 * Create an audio message
 *
 * @param sessionId - Chat object ID.
 * @param sessionType session type.
 * @param file - Audio file object.
 * @param duration - Duration of an audio file. Unit: ms.
 * @param nosTokenSceneKey - File resource scene.
 * @return IMMessage - Generated message object.
 */
public static IMMessage createAudioMessage(String sessionId, SessionTypeEnum sessionType, File file, long duration);

// Or: Create an audio message and specify the file resource scene used for uploading the specified audio file
public static IMMessage createAudioMessage(String sessionId, SessionTypeEnum sessionType, File file, long duration, String nosTokenSceneKey);
  • Parameters
Parameter Description
sessionId Chat object ID. It is user account for one-to-one chat and group ID for group chat.
sessionType Chat type. SessionTypeEnum.peer-to-peer is one-to-one chat type and SessionTypeEnum.Group is group chat type.
file Audio file object
duration Duration of audio file. Unit: ms
nosTokenSceneKey nos scene used for uploading audio file. Default value is NimNosSceneKeyConstant.NIM_DEFAULT_IM. See "File resource scenario".
  • Example
// The account is an example. Please register.
String account = "testAccount";
// The one-to-one chat type is taken for an example.
SessionTypeEnum sessionType = SessionTypeEnum.peer-to-peer;
// Example audio files. It requires developers to have the file under related directory.
File audioFile = new File("/sdcard/testAudio.mp3");
// Audio duration; time is taken for an example.
long audiolength = 2000;
// Create an audio message.
IMMessage audioMessage = MessageBuilder.createAudioMessage(account, sessionType, audioFile, audioLength);
// Or: Create an audio message and specify the file resource scene used for uploading the specified audio file. "nos_scene_key" must be replaced with the one configured by developers.
IMMessage audioMessage = MessageBuilder.createAudioMessage(account, sessionType, audioFile, "nos_scene_key");
// Send to the other party.
NIMClient.getService(MsgService.class).sendMessage(audioMessage, false).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {

                }

                @Override
                public void onFailed(int code) {
                    
                }

                @Override
                public void onException(Throwable exception) {

                }
            });

Send a video message

Creation prototype of video messages:

/**
 * Create a video message
 *
 * @param sessionId - Chat object ID.
 * @param sessionType session type.
 * @param file - Video file object.
 * @param duration - Duration of a video file.
 * @param width - Video width.
 * @param height - Video height.
 * @param displayName - Display name of a video file. It can be null.
 * @param nosTokenSceneKey - File resource scene.
 * @return - Video messages.
 */
public static IMMessage createVideoMessage(String sessionId, SessionTypeEnum sessionType, File file, long duration, int width, int height, String displayName);

// Or: Create a video message and specify the file resource scene used for uploading the specified video file.
public static IMMessage createVideoMessage(String sessionId, SessionTypeEnum sessionType, File file, long duration, int width, int height, String displayName, String nosTokenSceneKey)
  • Parameters
Parameter Description
sessionId Chat object ID. It is user account for one-to-one chat and group ID for group chat.
sessionType Chat type. SessionTypeEnum.peer-to-peer is one-to-one chat type and SessionTypeEnum.Group is group chat type.
file Video file object.
duration Duration of video file. Unit: ms.
width Video width.
height Video height.
displayName Display name of video file. It can be set to null.
nosTokenSceneKey nos scene used for uploading video file. Default value is NimNosSceneKeyConstant.NIM_DEFAULT_IM. See "File resource scenario".
  • Example
// The account is an example. Please register.
String account = "testAccount";
// The one-to-one chat type is taken for an example.
SessionTypeEnum sessionType = SessionTypeEnum.peer-to-peer;
// Example video. It requires developers to have the file under related directory.
File file = new File("/sdcard/testVideo.mp4");
// Get video mediaPlayer.
MediaPlayer mediaPlayer;
try {
    mediaPlayer = MediaPlayer.create(context, Uri.fromFile(file));
} catch (Exception e) {
    e.printStackTrace();
}
// Duration of a video file.
long duration = mediaPlayer == null ? 0 : mediaPlayer.getDuration();
// Video height.
int height = mediaPlayer == null ? 0 : mediaPlayer.getVideoHeight();
// Video width.
int width = mediaPlayer == null ? 0 : mediaPlayer.getVideoWidth();
// Create a video message.
IMMessage message = MessageBuilder.createVideoMessage(account, sessionType, file, duration, width, height, null);
// Or: Create a video message and specify the file resource scene used for uploading the specified video file. "nos_scene_key" must be replaced with the one configured by developers.
IMMessage message = MessageBuilder.createVideoMessage(account, sessionType, file, duration, width, height, null,"nos_scene_key");
// Send to the other party.
NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {

                }

                @Override
                public void onFailed(int code) {
                    
                }

                @Override
                public void onException(Throwable exception) {

                }
            });

Send a file message

Creation prototype of file messages:

/**
 * Create a file message.
 *
 * @param sessionId - Chat object ID.
 * @param sessionType session type.
 * @param file -File.
 * @param displayName - Display name of a file. It can be different from file name.
 * @param nosTokenSceneKey - File resource scene.
 * @return IMMessage - Generated message object.
 */
public static IMMessage createFileMessage(String sessionId, SessionTypeEnum sessionType, File file, String displayName);

// Or: Create a file message and specify the file resource scene used for uploading the specified file.
public static IMMessage createFileMessage(String sessionId, SessionTypeEnum sessionType, File file, String displayName, String nosTokenSceneKey)
  • Parameters
Parameter Description
sessionId Chat object ID. It is user account for one-to-one chat and group ID for group chat.
sessionType Chat type. SessionTypeEnum.peer-to-peer is one-to-one chat type and SessionTypeEnum.Group is group chat type.
file File.
displayName Display name of file. It can be different from file name.
nosTokenSceneKey nos scene used for uploading file. Default value is NimNosSceneKeyConstant.NIM_DEFAULT_IM. See "File resource scenario".
  • Example
// The account is an example. Please register.
String account = "testAccount";
// The one-to-one chat type is taken for an example.
SessionTypeEnum sessionType = SessionTypeEnum.peer-to-peer;
// Example file. It requires developers to have the file under related directory.
File file = new File("/sdcard/test.txt");
// Create a file message.
IMMessage message = MessageBuilder.createFileMessage(account, sessionType, file, file.getName());
// Or: Create a file message and specify the file resource scene used for uploading the specified file. "nos_scene_key" must be replaced with the one configured by developers.
IMMessage message = MessageBuilder.createFileMessage(account, sessionType, file, file.getName(),"nos_scene_key");
// Send to the other party
NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {

                }

                @Override
                public void onFailed(int code) {
                    
                }

                @Override
                public void onException(Throwable exception) {

                }
            });

Sending a location message

Creation prototype of location messages:

/**
 * Create a geolocation information.
 *
 * @param sessionId - Chat object ID.
 * @param sessionType session type.
 * @param lat - Latitude.
 * @param lng - Longitude.
 * @param addr - Description information about geographical location.
 * @param nosTokenSceneKey - File resource scene.
 * @return IMMessage - Generated message object.
 */
public static IMMessage createLocationMessage(String sessionId, SessionTypeEnum sessionType, double lat, double lng, String addr);
  • Parameters
Parameter Description
sessionId Chat object ID. It is user account for one-to-one chat and group ID for group chat.
sessionType Chat type. SessionTypeEnum.peer-to-peer is one-to-one chat type and SessionTypeEnum.Group is group chat type.
lat Latitude.
lng Longitude.
addr Description information about geographical location.
  • Example
// The account is an example. Please register.
String account = "testAccount";
// The one-to-one chat type is taken for an example.
SessionTypeEnum sessionType = SessionTypeEnum.peer-to-peer;
// Latitude.
double lat = 30.3;
// Longitude.
double lng = 120.2;
// Description information about geographical location.
String addr = "Hangzhou";
// Create a geolocation information.
IMMessage message = MessageBuilder.createLocationMessage(account, sessionType, lat, lng, addr);

// Send to the other party
NIMClient.getService(MsgService.class).sendMessage(message, false).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {

                }

                @Override
                public void onFailed(int code) {
                    
                }

                @Override
                public void onException(Throwable exception) {

                }
            });

Send a tip message

Independent message type MsgTypeEnum.tip is available. A tip message is mainly used for notification tip in a session and can be considered as simplified custom message. It is different from a custom message. A tip message does not support setAttachment now. If you want to use Attachment, please send a custom message. The tip message scenarios include welcome message in session or tip message containing sensitive words in session. Definitely, you can send a custom message, but it may be relatively complex.

Creation prototype of tip messages:

/**
 * Create a tip message
 *
 * @param sessionId - Chat object ID.
 * @param sessionType session type.
 * @return IMMessage - Generated message object.
 */
public static IMMessage createTipMessage(String sessionId, SessionTypeEnum sessionType);
  • Example
// A tip message is sent to a group, so that the group can be shown immediately on the list of recent contacts (list of sessions) to meet requirements of developers.
Map<String, Object> content = new HashMap<>(1);
content.put("content", "Successfully create an advanced group");
// Create a tip message. teamId must be the group ID of existing group configured by developers.
IMMessage msg = MessageBuilder.createTipMessage(teamId, SessionTypeEnum.Team);
msg.setRemoteExtension(content);
// Configuration option for custom messages.
CustomMessageConfig config = new CustomMessageConfig();
// The message is not included in unread count.
config.enableUnreadCount = false;
msg.setConfig(config);
// Set the sending status of a message to success.
msg.setStatus(MsgStatusEnum.success);
// Save a message to local database, but not send it to server.
NIMClient.getService(MsgService.class).saveMessageToLocal(msg, true).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {

                }

                @Override
                public void onFailed(int code) {
                    
                }

                @Override
                public void onException(Throwable exception) {

                }
            });

Sending a user-defined message

In addition to built-in message types, IM SDK also supports custom message sending and receiving. The SDK will not define and parse content of custom message of which interpretation will be completed by the developer. The SDK will save custom message to message database, which will be shown in message history together with built-in messages.

For convenience of application, a custom message is displayed to the developer in the form of attachment. This is reflected in IMMessage. The content of custom message will be parsed into MsgAttachment object. The SDK does not know format of custom message, so that a third-party app needs to register a custom message parser. When the third-party app calls the interface of querying message history, or SDK informs the third-party app of received message, content of custom message can be transformed into a MsgAttachment object and then custom message can be executed like image message with attachment.

Create custom message prototype

/**
 * Create an app custom message, and provide description field for push and display of message alert in status bar.
 *
 * @param sessionId - Chat object ID.
 * @param sessionType session type.
 * @param content - Simple a message. It can be acquired using IMMessage#getContent() and is mainly used for displaying user push.
 * @param attachment - Message attachment object.
 * @param config - Configuration for custom message.
 * @param nosTokenSceneKey - File resource scene.
 * @return - Custom message.
 */
public static IMMessage createCustomMessage(String sessionId, SessionTypeEnum sessionType, String content, MsgAttachment attachment, CustomMessageConfig config);

//Or: Create an app custom message and specify nos scene used for uploading files (image, audio, video) (if any).
public static IMMessage createCustomMessage(String sessionId, SessionTypeEnum sessionType, String content, MsgAttachment attachment, CustomMessageConfig config, String nosTokenSceneKey)

Example: Rock-Paper-Scissors

In the demo, a Rock-Paper-Scissors game is provided. Custom messages can be used in the game. The following is taken for an example to describe the steps in detail.

Step 1: Define a base class of custom message attachment to resolve public field of your custom message, for example, type. You can also define some public interfaces for convenient invocation.

Note: All members who have created MsgAttachment interface must implement "Serializable".

// Define a base class of attachment for custom message to decode public field of your custom message, for example, type.
public abstract class CustomAttachment implements MsgAttachment {

	// Type of custom message attachment. Different custom messages are distinguished by the field.
    protected int type;

    CustomAttachment(int type) {
        this.type = type;
    }

	// Decode attachment content.
    public void fromJson(JSONObject data) {
        if (data != null) {
            parseData(data);
        }
    }

	// Interface for realizing MsgAttachment. It encapsulates the public field and then invoke encapsulating feature of sub-class.
    @Override
    public String toJson(boolean send) {
        return CustomAttachParser.packData(type, packData());
    }

    // Interface for decoding and encapsulating sub-class.
    protected abstract void parseData(JSONObject data);
    protected abstract JSONObject packData();
}

Step 2: Inherit this base class to implement attachment type of "Rock-Paper-Scissors". Note: The member variables must implement "Serializable".

public class GuessAttachment extends CustomAttachment {

	// Finger-guessing type enumeration.
    public enum Guess {
        Shitou(1),
        Jiandao(2),
        Bu(3),
        ;
    }

    private Guess value;

    public GuessAttachment() {
        super(CustomAttachmentType.Guess);
        random();
    }

	// Decode detailed data of Finger-guessing type.
    @Override
    protected void parseData(JSONObject data) {
        value = Guess.enumOfValue(data.getIntValue("value"));
    }

	// Data packing.
    @Override
    protected JSONObject packData() {
        JSONObject data = new JSONObject();
        data.put("value", value.getValue());
        return data;
    }

    private void random() {
        int value = new Random().nextInt(3) + 1;
        this.value = Guess.enumOfValue(value);
    }
}

Step 3: Implement attachment parser of custom messages.

public class CustomAttachParser implements MsgAttachmentParser {

	// Determine type of attachment object based on decoded message type.
    @Override
    public MsgAttachment parse(String json) {
        CustomAttachment attachment = null;
        try {
            JSONObject object = JSON.parseObject(json);
            int type = object.getInteger("type");
            JSONObject data = object.getJSONObject(KEY_DATA);
            switch (type) {
                case CustomAttachmentType.Guess:
                    attachment = new GuessAttachment();
                    break;
                default:
                    attachment = new DefaultCustomAttachment();
                    break;
            }

            if (attachment != null) {
                attachment.fromJson(data);
            }
        } catch (Exception e) {

        }

        return attachment;
    }

	public static String packData(int type, JSONObject data) {
        JSONObject object = new JSONObject();
        object.put(KEY_TYPE, type);
        if (data != null) {
            object.put(KEY_DATA, data);
        }

        return object.toJSONString();
    }
}

Finally, register the attachment parser to SDK. To correctly parse custom attachment when message history is generated, the registration is generally completed in judgment statement of main process in onCreate of Application.

if (NIMUtil.isMainProcess(this)) {
    // Monitored registration must be in the host process.
    NIMClient.getService(MsgService.class).registerCustomAttachmentParser(new CustomAttachParser()); 
}

Example: snaps

If you need to send a file message, for example, image, you can see "Self-destructing messages". Realization steps are as follows:

Step 1: Define a custom attachment type, and inherit FileAttachment. Note: The member variables must implement "Serializable".

public class SnapChatAttachment extends FileAttachment {

	private static final String KEY_PATH = "path";
    private static final String KEY_SIZE = "size";
    private static final String KEY_MD5 = "md5";
    private static final String KEY_URL = "url";

    public SnapChatAttachment() {
        super();
    }

    public SnapChatAttachment(JSONObject data) {
        load(data);
    }

    @Override
    public String toJson(boolean send) {
        JSONObject data = new JSONObject();
        try {
	        // Re-send and use local path
	        if (!send && !TextUtils.isEmpty(path)) {
                data.put(KEY_PATH, path);
            }

            if (!TextUtils.isEmpty(md5)) {
                data.put(KEY_MD5, md5);
            }
			// Notes: The code is required.
			// When SDK invokes toJson, url of the father FileAttachemnt has a value.
			// The value is assigned automatically by SDK.
            data.put(KEY_URL, url);
            data.put(KEY_SIZE, size);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return CustomAttachParser.packData(CustomAttachmentType.SnapChat, data);
    }

    private void load(JSONObject data) {
	    path = data.getString(KEY_PATH);
        md5 = data.getString(KEY_MD5);
        url = data.getString(KEY_URL);
        size = data.containsKey(KEY_SIZE) ? data.getLong(KEY_SIZE) : 0;
    }
}

Step 2: Implement attachment resolver of custom message.

public class CustomAttachParser implements MsgAttachmentParser {

	// Determine type of attachment object based on decoded message types.
    @Override
    public MsgAttachment parse(String json) {
        CustomAttachment attachment = null;
        try {
            JSONObject object = JSON.parseObject(json);
            int type = object.getInteger("type");
            JSONObject data = object.getJSONObject(KEY_DATA);
            switch (type) {
                case CustomAttachmentType.SnapChat:
                    return new SnapChatAttachment(data);
                default:
                    attachment = new DefaultCustomAttachment();
                    break;
            }

            if (attachment != null) {
                attachment.fromJson(data);
            }
        } catch (Exception e) {

        }

        return attachment;
    }
   ...
}

Finally, register the attachment parser to SDK. To correctly parse custom attachment when message history is generated, the registration is generally completed in onCreate of Application.

if (NIMUtil.isMainProcess(this)) {
    // The registration of the listener must be in the main process.
    NIMClient.getService(MsgService.class).registerCustomAttachmentParser(new CustomAttachParser()); 
}

Message property settings

When sending a message, you can set the message configuration optionsCustomMessageConfig, mainly determine whether the message is stored in the cloud, or whether it is written to roaming.

  • Parameters

Configure CustomMessageConfig attribute for custom messages:

/**
 * It determines to store the message in server.
 * The value is "true" by default.
 */
public boolean enableHistory = true;

/**
 * It determines that a message must be roamed.
 * The value is "true" by default.
 */
public boolean enableRoaming = true;

/**
 * It determines that client must throw the message in the callback for receiving messages when the sender logs in multiple clients synchronously and one message is sent from one client.
 * The value is "true" by default.
 */
public boolean enableSelfSync = true;

/**
 * It determines that push tip is required for the message.
 * The value is "true" by default.
 */
public boolean enablePush = true;

/**
 * It determines that push display name is required for the message.
 * The value is "true" by default.
 */
public boolean enablePushNick = true;

/**
 * It determines that the message must be included in unread count.
 * The value is "true" by default.
 */
public boolean enableUnreadCount = true;

/**
 * It determines that delivery messages are required.
 * The value is "true" by default.
 */
public boolean enableRoute = true;

/**
 *
 * It determines that the message is stored offline. If it is set to "false", the message will not be stored in offline database and message history on cloud database.
 * The value is "true" by default.
*/
public boolean enablePersist = true;
  • Example
// The account is an example. Please register.
String account = "testAccount";
// The one-to-one chat type is taken for an example.
SessionTypeEnum sessionType = SessionTypeEnum.peer-to-peer;
String text = "this is an example";
// Create a text message.
IMMessage textMessage = MessageBuilder.createTextMessage(account, sessionType, text);

// Configuration options for a message.
CustomMessageConfig config = new CustomMessageConfig();
// The message is not stored in server.
config.enableHistory = false;
// The message is not roamed.
config.enableRoaming = false;
// The message is not synchronized.
config.enableSelfSync = false;
textMessage.setConfig(config);

// Send to the other party.
NIMClient.getService(MsgService.class).sendMessage(textMessage, false).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {

                }

                @Override
                public void onFailed(int code) {
                    
                }

                @Override
                public void onException(Throwable exception) {

                }
            });

File resource scenario

The SDK can set the corresponding lifetime of images, audio, videos and files.

  • Preset file resource scenario

When initializing the SDK, you can configure corresponding file resource scenario, with reference codes:


static SDKOptions getSDKOptions(Context context) {
        SDKOptions options = new SDKOptions();
         //Other configurations.
        options.mNosTokenSceneConfig = createNosTokenScene();
        return options;
}

public static final String TEST_NOS_SCENE_KEY="test_nos_scene_key";

private static NosTokenSceneConfig createNosTokenScene() {
      NosTokenSceneConfig nosTokenSceneConfig = new NosTokenSceneConfig();
      
      //Update expiry (day) of the default scene (NimNosSceneKeyConstant.NIM_DEFAULT_IM).
      nosTokenSceneConfig.updateDefaultIMSceneExpireTime(1);
      
      //Update expiry (day) of the default scene (NimNosSceneKeyConstant.NIM_DEFAULT_PROFILE).
      nosTokenSceneConfig.updateDefaultProfileSceneExpireTime(2);
      
      // Set custom scene and related expiry (day). 0 indicates no expiry.
      //We recommend to set sceneKey to a constant. As a result, it can be used conveniently. Now, at most 10 scenes can be customized.
      nosTokenSceneConfig.appendCustomScene(TEST_NOS_SCENE_KEY, 4);
      return nosTokenSceneConfig;
}

List of main parameters of NimNosSceneKeyConstant.

NimNosSceneKeyConstant Meaning
NIM_DEFAULT_IM Send image, audio, video, file message in private chat, group chat, and chat room.
NIM_DEFAULT_PROFILE Upload user and group profile (for example, profile picture) by CommsEase uploading service.

Considerations:

  • If in a nonexistent scenario, the upload will fail (error code: 5).
  • If the file is expired and you download file, then download will fail (error code: 4).

Inserting a local message

If a message must be inserted to local database in service scenario, instead of being sent, then it can be implemented through inserting local messages.

/**
// Insert a message to local database, and notify to update UI interface, but not send it to server. Send a local message that can be set others as senders to yourself.
* If the interface saves a message to the database, it will notify UI, the notification {@link MsgServiceObserve#observeReceiveMessage(Observer, boolean)} will be triggered.
*
* @param msg - Message object to be inserted.
* @param fromAccount - Sender ID.
* @return InvocationFuture - Configurable callback feature. It will be called back when the message is stored in database.
*/
InvocationFuture<Void> insertLocalMessage(IMMessage msg, String fromAccount);

/** Save a message to local database, but not send it to server. It can set the time for saving the message. It can be used for saving local tip message in the third-party APP. When the interface saves a message to the database, if UI must be notified, the parameter notify can be set to true, the notification {@link MsgServiceObserve.observeReceiveMessage(Observer, boolean)} will be triggered.

* @param msg - Message object to be inserted.
* @param notify - It determines to notify.
* @param time - Time for setting the local message.
* @return InvocationFuture - Configurable callback feature. It will be called back when the message is stored in database.
*/
InvocationFuture<java.lang.Void> saveMessageToLocalEx(IMMessage msg,boolean notify,long time);

Updating messages

Updating the extension field

The SDK can update the extension field of messages in client database.

/**
* Update LocalExtension of a message.
* @param message - Messages to be updated.
*/
void updateIMMessage(IMMessage message);

Updating message status

/**
* Update message status.
* @param message - Messages to be updated.
*/
void updateIMMessageStatus(IMMessage message);

Example:

msg.setStatus(MsgStatusEnum.success);
NIMClient.getService(MsgService.class).updateIMMessageStatus(msg);

Note: Please do not update notification type message.

Re-sending messages

If the message is not sent successfully., you can send the message again. The message is sent and re-sent using the same interface, and only parameter settings are different. When "resend" is "true", it indicates that a message is resent.

Forwarding messages

Except notification, audio & video call event, the SDK can forward all other types of messages.

You must create a message to be forwarded using MessageBuilder and then send the message using MsgService#sendMessage interface.

/**
 * Forward a message.
 *
 * @param message - Message to be forwarded.
 * @param sessionId - Chat object ID.
 * @param sessionType session types.
 * @return - Messages to be forwarded.
 */
public static IMMessage createForwardMessage(IMMessage message, String sessionId, SessionTypeEnum sessionType);
  • Parameters
Parameter Description
message Message to be forwarded.
sessionId Chat object ID. It is user account for one-to-one chat and group ID for group chat.
sessionType Chat type. SessionTypeEnum.peer-to-peer is one-to-one chat type and SessionTypeEnum.Group is group chat type.
  • Example
// The account is an example. Please register.
String account = "testAccount";
// The one-to-one chat type is taken for an example.
SessionTypeEnum sessionType = SessionTypeEnum.peer-to-peer;
// forwardMessage - It is the message to be forwarded and generally acquired from context.
IMMessage message = MessageBuilder.createForwardMessage(forwardMessage, account, sessionType);
// Send to the other party.
NIMClient.getService(MsgService.class).sendMessage(textMessage, false).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {

                }

                @Override
                public void onFailed(int code) {
                    
                }

                @Override
                public void onException(Throwable exception) {

                }
            });

Recalling messages

Recalling a message

It allows you can recall a message that you have sent within a specified duration. The default time is 2 minutes, which can be configured on CommsEase console.

  • API prototype
/**
 * Recall a message, and set related third-party push configurations (including push of ISO platform) and change in unread count. If you need to close message return tip in App, see {@link NIMClient#toggleRevokeMessageNotification(boolean on)}.
 *
 * @param message - Message to be recalled.
 * @param customApnsText - Text of the third-party transferred push notification. If it is null, the message will not be pushed.
 * @param pushPayload - The third-party custom push attribute, limited to json type, with length 2048.
 * @param shouldNotifyBeCount - It determines to update unread count when a notification is recalled.
 * @param postscript - Postscript
 * @param attach - Extension field
 *
 * @return InvocationFuture - Configurable callback feature. It can monitor the sending result.
 */
InvocationFuture<Void> recallMessage(IMMessage message, String customApnsText,
                                     Map<String, Object> pushPayload, boolean shouldNotifyBeCount,
                                     String postscript, String attach);
  • Parameters
Parameter Description
message Message to be recalled.
customApnsText Text of the third-party transferred push notification. If null, the message will not be pushed.
pushPayload The third-party defined push property is limited to json type, with length 2048.
shouldNotifyBeCount Determine that unread count of revocation notification must be updated.
postscript P.S.
attach Extension field
  • Example
NIMClient.getService(MsgService.class).recallMessage(message, null, null, true, postscript, attachJson).setCallback(new RequestCallbackWrapper<Void>() {
    @Override
    public void onResult(int code, Void result, Throwable exception) {

    }
});

After the request of revocation message has been called successfully, the SDK will invoke the message to upper developer successfully and then automatically delete the message in local database. If a tip must be shown after revocation, the developer must create a tip message independently and call the interface of insetting local message.

The message will not be recalled successfully, if:

  • The message is null.
  • The message is not sent successfully.
  • The message cannot be recalled due to timeout.

Content requirement for notification bar in revocation scenario: For example, A sends message to B to generate APNs with text content "Hello". Then A recalls this message and "Hello" shown in notification bar becomes default "recalled a message".

A recommended implementation method:

  • When sending message, the user should insert key value with key being apns-collapse-id using NIMMessage - setPushPayload(Map pushPayload). We recommend to fill in character string such as "uuid" in "value" for unique identification.
  • When recalling this message, the user should configure text in transfer parameter "customApnsText" on revocation interface and insert same apns-collapse-id key value with recalled message in pushPayload.

Listening for message recalls

The recipient will receive a notification if a message is recalled.

  • API prototype
/**
 * Register or unregister the observer for recalling messages.
 * @param observer - Observer. The parameter is a recalled message.
 * @param register true indicates registered, and true indicates unregistered
 */
public void observeRevokeMessage(Observer<RevokeMsgNotification> observer, boolean register);
  • RevokeMsgNotification
Methods Description
getMessage() Get recalled messages.
getAttach() Get the field of recalled attachment.
getRevokeAccount() Get revocation account.
getCustomInfo() Get msg field that is configured when the message is recalled (for example, Recall message using server API).
getNotificationType() Get notification type: 1 indicates offline notification; 2 indicates roaming notification; 0 is default.
getRevokeType() Get revocation type: peer-to-peer dual revocation; group dual revocation; Supergroup dual revocation; peer-to-peer one-way revocation, and undefined.
getCallbackExt() Get a third-party extension field.
  • Example
Observer<RevokeMsgNotification> recallMessageObserver = new Observer<RevokeMsgNotification>() {
    @Override
    public void onEvent(RevokeMsgNotification notification) {
       // Notification for listening message revocation. Related operation can be made in the interface.
       // Get recalled messages.
       notification.getMessage();
       // Get revocation account.
       notification.getRevokeAccount();
    }
};

NIMClient.getService(MsgServiceObserve.class).observeRevokeMessage(recallMessageObserver, true);

In addition, if the Message tip feature is enabled, then tip notification bar may also be triggered when revocation message is received. If unnecessary, you can

NIMClient.toggleRevokeMessageNotification(false);

disable this feature using XX. See Tip for recalling notification message.

Filter configuration for recall notification

A filter is configured to determine that notification bar must be displayed based on recalled notification object.
If notification bar must be displayed based on other logics, then you can determine that notification bar must be displayed based on the filter. If notification bar must not be displayed based on other logics, then whatever the filter is configured, and the notification bar must not be displayed.

The filter can be used to reduce the number of recalled messages in upper notification bar.

  • API prototype
/**
 * It determines to show the filter for notifications when a message is recalled during registration.
 */
void registerShouldShowNotificationWhenRevokeFilter(ShowNotificationWhenRevokeFilter filter);
  • ShowNotificationWhenRevokeFilter prototype
public interface ShowNotificationWhenRevokeFilter {
    boolean showNotification(RevokeMsgNotification notification);
}
  • Example
NIMClient.getService(MsgService.class).registerShouldShowNotificationWhenRevokeFilter(notification -> {
    return notification == null || TextUtils.isEmpty(notification.getAttach());
});

File transfer management

Listening for file transfer progress

The SDK can manage file transfer. Developers can monitor file transfer by registering observer for message attachment uploading or downloading process.

/**
 * Register/log out the observer for uploading/downloading progress of message attachment.
 *
 * @param observer - Observer. The parameter is transmission progress of attachment.
 * @param register true indicates registered, and true indicates unregistered
 */
void observeAttachmentProgress(Observer<AttachmentProgress> observer,
                               boolean register);

Cancelling message attachment upload

You can cancel uploading message attachment using MsgService interface.

/**
* Cancel to upload message attachment (image, video, file type). If the attachment has been uploaded successfully, the operation will be failed. If the attachment uploading is canceled successfully, related message cannot be sent successfully, related message status is MsgStatusEnum.fail, and attachment status is AttachStatusEnum.cancel. Notes: This operation is not available to chat room.
* @param imMessage - Message that is to cancel attachment uploading
*/
InvocationFuture<java.lang.Void> cancelUploadAttachment(IMMessage imMessage);

Audio message processing

CommsEase SDK provides a feature of recording and playing high-definition audio to process audio message.

Playback

CommsEase provides AudioPlayer to support audio playing feature.

AudioPlayer interface:

Return AudioPlayer interface Description
long getCurrentPosition() Get current audio playing position.
long getDuration() Get audio duration.
OnPlayListener getOnPlayListener() Get play listener of AudioPlayer.
boolean isPlaying() Query that audio is playing.
void seekTo(int msec) Skip to specified position to continue playing.
void setDataSource(String audioFile) Set audio source.
void setOnPlayListener(OnPlayListener listener) Set play listening.
void start(int audioStreamType) Start play.
void stop() Stop play.

Creating a player instance

  • API prototype
/**
 * Construct a feature for audio player.
 * @param context - Context parameter.
 * @param audioFile - Path of an audio file to be played.
 * @param listener - Play listener.
 */
public AudioPlayer(Context context, String audioFile, OnPlayListener listener);
  • Parameters
Parameter Description
context Context parameter.
audioFile Path of audio files to be played.
listener Play listener.

OnPlayListener interface:

OnPlayListener interface Description
onCompletion() Complete play.
onError(String error) Error in play Cause description for parameter error.
onInterrupt() Interrupt play.
onPlaying(long curPosition) Play report; call back once every 500ms, and notify current position. The parameter is current position (unit: ms) and can be used for updating UI.
onPrepared() Complete file decoding, and prepare to play.
  • Example
// Define a callback for playing progress.
OnPlayListener listener = new OnPlayListener() {

    // The audio file has been transcoded and decoded, and will be played soon.
    public void onPrepared() {}

    // The play is ended.
    public void onCompletion() {}

    // The play is interrupted.
    public void onInterrupt() {}

    // An error occurs in playing process. Cause description for parameter error.
    public void onError(String error){}

    // Play progress report; call back once every 500ms, and notify current position. The parameter is current position (unit: ms) and can be used for updating UI.
    public void onPlaying(long curPosition) {}
};

// Construct player object.
AudioPlayer player = new AudioPlayer(context, filePath, listener);

Playback control

  • Play audio
// Start play The parameter audioStreamType must be input to indicate telephone recipient mode or loudspeaker mode.
// Audioadministrator.STREAM_AUDIO_CALL - Telephone recipient mode.
// Audioadministrator.STREAM_MUSIC - Loudspeaker mode.
player.start(audioStreamType);
  • Designate play position
// If the player is switched during the operation, start must be invoked again and specified audioStreamType must be input. The player will stop automatically and then start again by a new streamType.
// If play must be continued from the stopped position, developers must remember the stopped position and then invoke seekTo in the callback onPrepared.
player.seekTo(pausedPosition);
  • Stop play
player.stop();
  • Other methods
// Get current audio playing position.
player.getCurrentPosition();

// Get audio duration.
player.getDuration();

// Query that an audio file is being played.
player.isPlaying();

// Set the audio source.
player.setDataSource(audioFile);

Recording

SDK provides AudioRecorder to support audio recording.

AudioRecorder interface:

Return AudioRecorder interface Description
void completeRecord(boolean cancel) Complete (end) recording, and make different callback as per parameter cancel.
If "cancel" is "true", IAudioRecordCallback#onRecordCancel is invoked; if it is "false", IAudioRecordCallback#onRecordSuccess is invoked.
void destroyAudioRecorder() Release resource.
int getCurrentRecordMaxAmplitude() Get max. amplitude at current recording; update data every 40ms;
void handleEndRecord(boolean isSuccess, int duration) After end of recording, IAudioRecordCallback#onRecordSuccess is invoked.
boolean isRecording() Determine that recording is being executed.
void startRecord() Start record. If successful, IAudioRecordCallback#onRecordReady and IAudioRecordCallback#onRecordStart will be invoked in order.

Create a recorder instance

  • API prototype
/**
 * Construct a recorder instance.
 *
 * @param context - Context
 * @param recordType - Type of recorded audio file (aac/amr).
 * @param maxDuration - Max. recording duration. The recording will be stopped automatically at the position.
 * @param cb - Call back the recording process.
 */
public AudioRecorder(Context context, RecordType recordType,int maxDuration, IAudioRecordCallback cb);
  • Parameters
Parameter Description
context Context
recordType Type of recorded audio (aac/amr).
maxDuration Max. recording duration. The recording will be stopped automatically at the position.
cb Invoke recording process.
  • IAudioRecordCallback interface:
IAudioRecordCallback interface Description
onRecordCancel() The recording is completed. The user cancels recording actively.
onRecordFail() The recording is completed. It fails.
onRecordReachedMaxTime(int maxTime) Reach specified maximum recording time.
onRecordReady() Recorder is ready. The interface is used to close local audio and video play before recording (optional).
onRecordStart(File audioFile, RecordType recordType) Start recording invocation.
onRecordSuccess(File audioFile, long audioLength, RecordType recordType) The recording is completed. It is successful.
  • Example
// Define callback object of recording process.
IAudioRecordCallback callback = new IAudioRecordCallback () {

	void onRecordReady() {
		// Callback returned after initialization. The interface is used for closing local audio and video play before recording (optional).
	}

    void onRecordStart(File audioFile, RecordType recordType) {
	    // Callback for starting recording.
    }

    void onRecordSuccess(File audioFile, long audioLength, RecordType recordType) {
	    // The recording is completed. It is successful.
    }

    void onRecordFail() {
	    // The recording is completed. It fails.
    }

    void onRecordCancel() {
	    // The recording is completed. The user cancels recording actively.
    }

    void onRecordReachedMaxTime(int maxTime) {
	    // Reach specified maximum recording time.
    }
};

// Initialize recorder
AudioRecorder recorder = new AudioRecorder(
	context,
	RecordType.AAC, // Type of recorded audio file (aac/amr).
	maxDuration, // Max. recording duration. The recording will be stopped automatically at the position. The value is 120s by default.
	callback // Callback for recording process.
);

Recording control

  • Record audio
// Start recording. If it is successful, onRecordReady and onRecordStart will be called back in order.
recorder.startRecord();
  • End or cancel recording
// End recording, end normally, or cancel recording.
// If cancel is set to true, it indicates to cancel recording; if it is set to false, it indicates to end recording.
recorder.completeRecord(cancel);
  • Destruction example
recorder.destroyAudioRecorder();
  • Other methods

// It determines that recording is being executed.
recorder.isRecording();

// Get max. amplitude at current recording; update data every 40ms;
recorder.getCurrentRecordMaxAmplitude();

// When the maximum recording duration is reached, the current recording is confirmed.
recorder.handleEndRecord(true, maxTime) 

Audio-to-text

To enable the audio-to-text feature, please contact our business consultant and apply for "audio recognition". If the interface is called without enabling this feature, return 403.

Principle of audio-to-text:

  • Record audio files (maximum 60 seconds).
  • Upload to the CommsEase storage server and return the file url.
  • Input the url and related parameters through the audio-to-text interface, and return the converted text.

The following method under MsgService interface is used for audio-to-text:

/**
* Transform an audio file into text and specify the scene for uploading file and that the file must be re-uploaded.
* @param audioUrl - Audio url Optional. If there is no such option, SDK will upload nos automatically.
* @param path - Audio path. It is used for getting audio sampling rate. app must  ensure that the audio file has been downloaded to local database.
* @param duration - Audio duration.
* @param sceneKey - nos sceneKey used for uploading a file. The value is NimNosSceneKeyConstant#NIM_DEFAULT_IM by default. For configuration parameter nos token scene, see the chapter of file resource scene.
* @param enableForceUploadFile - It determines to upload the file again if there is same file in the server. The value is false by default.
* AbortableFuture - Callback tracking The callback feature can be configured to stop downloading.
*/
AbortableFuture<java.lang.String> transAudioToTextEnableForce(java.lang.String audioUrl,
                                                              java.lang.String path,
                                                              long duration,
                                                              java.lang.String sceneKey,
                                                              boolean enableForceUploadFile);

Example:

public void audioToText(IMMessage msg, String sceneKey) {
        AudioAttachment attachment = (AudioAttachment) msg.getAttachment();
        String audioUrl = attachment.getUrl();
        String path = attachment.getPath();
        refreshStartUI();
        callFuture = NIMClient.getService(MsgService.class).transAudioToTextEnableForce(audioUrl, path, attachment.getDuration(), sceneKey, false);
        callFuture.setCallback(new RequestCallback<String>() {
            @Override
            public void onSuccess(String param) {
                audioTransText.setText(param);
                updateUI();
            }

            @Override
            public void onFailed(int code) {
                LogUtil.e(TAG, "audio to text failed, code=" + code);
                audioTransText.setText(R.string.trans_audio_failed);
                failIcon.setVisibility(View.VISIBLE);
                updateUI();
            }

            @Override
            public void onException(Throwable exception) {
                LogUtil.e(TAG, "audio to text throw exception, e=" + exception.getMessage());
                audioTransText.setText("Parameter error");
                failIcon.setVisibility(View.VISIBLE);
                updateUI();
            }
        });
        show();
    }
Was this topic helpful?
Yes
No
  • Overview
  • Sending messages
  • Sending a text message
  • Send image messages
  • Send an audio message
  • Send a video message
  • Send a file message
  • Sending a location message
  • Send a tip message
  • Sending a user-defined message
  • Example: Rock-Paper-Scissors
  • Example: snaps
  • Message property settings
  • File resource scenario
  • Inserting a local message
  • Updating messages
  • Updating the extension field
  • Updating message status
  • Re-sending messages
  • Forwarding messages
  • Recalling messages
  • Recalling a message
  • Listening for message recalls
  • Filter configuration for recall notification
  • File transfer management
  • Listening for file transfer progress
  • Cancelling message attachment upload
  • Audio message processing
  • Playback
  • Creating a player instance
  • Playback control
  • Recording
  • Create a recorder instance
  • Recording control
  • Audio-to-text