对方正在输入 java_iOS SDK 消息体系详解

iOS SDK 消息体系详解

本文档将详细介绍融云的消息体系设计和常用的接口功能说明。阅读本文前,我们假设您已经阅读了融云 iOS 开发指南,并掌握融云 SDK 的基本用法。

会话与消息的关系

融云 SDK 中已经默认包含了消息数据的本地存储机制,开发者不再需要自己进行消息的存储。也就是说,在融云 SDK 收到消息后,先在本地进行了数据存储,然后再通过消息接收事件通知给开发者。开发者可以通过一系列接口读取和操作本地存储的消息数据。

会话实体和消息实体

会话实体类和消息实体类是用来存储本地会话和消息的容器类,除了包含会话内容和消息内容外,还包括了保存在本地的各种状态。

用来存储消息的实体类主要有 RCConversation(会话) 和 RCMessage(消息) 两个实体类,您在客户端读取消息时,获取的对象都和这两个类相关。会话有多种类型,可以是私聊会话,也可以是群组会话等,每一个 RCConversation(会话)包含多条 RCMessage(消息),关系如下图所示:

e3d308138fdb5486cc4555617e7c3e7c.png

如何标识一个会话

通过 conversationType 和 targetId,可以唯一确定一个会话。RCConversationType 枚举值意义和对应的 targetId 意义为:

会话类型枚举 ConversationType

说明

对应的 targetId

ConversationType_PRIVATE

单聊

用户的 Id(userId)。

ConversationType_GROUP

群组

群组的 Id(groupId)。

ConversationType_DISCUSSION

讨论组

讨论组的 Id(discussionId)。

ConversationType_CHATROOM

聊天室

聊天室的 Id(chatroomId)。

ConversationType_CUSTOMER_SERVICE

客服

客服的 Id(customerServiceId)。

ConversationType_SYSTEM

系统会话

系统账户 Id。可以理解为 QQ 的 10000 号的角色。

请注意区分会话类型和消息类型,会话类型是针对会话的分类,不同的会话类型决定了不同的会话逻辑。

另:系统会话类型并不一定代表是“系统消息”,本质上与单聊会话类型没有区别,只是逻辑上做了不同的区分,便于展开不同的产品业务逻辑。

通过一个 conversationType 和 targetId 组合,您可以确定会话列表中一个唯一的对象。以获取某会话的未读消息数举例:获取某会话未读消息数的方法是 RCIM.getInstance().getUnreadCount(ConversationType conversationType, java.lang.String targetId)

获取一个私聊会话未读消息数的代码片段:

String userId = "9527";

// 注意:调用 RCIM.getInstance() 方法前,务必保证调用了 init 和 connect。

int unreadCount = RCIM.getInstance().getUnreadCount(ConversationType.PRIVATE, userId);

获取一个群组会话未读消息数的代码片段:

String groupId = "1234";

// 注意:调用 RCIM.getInstance() 方法前,务必保证调用了 init 和 connect。

int unreadCount = RCIM.getInstance().getUnreadCount(ConversationType.GROUP, groupId);

消息的定义

消息类(RCMessageContent 的子类)不同于消息实体类(RCMessage),消息类代表一条具体的消息内容,消息实体类是消息类的外层容器,消息实体对象是消息对象在本地存储的外层对象,消息实体对象除了包含消息对象外,还包括消息的方向、接收状态、接收时间、发送者等。

消息基类

RCMessageContent 是融云的消息基类,所有消息类都继承于 RCMessageContent 类。需要注意的是,RCMessageContent 类和 RCMessage 类之间的关系:Message 中包含了一个具体的继承自 RCMessageContent 的消息,就是 Content 属性,可以通过 setContent() 和 getContent() 进行存取。

约定:如果您要定义一个内容类消息(需要显示在聊天会话界面中,且不是通知类消息),请从 RCMessageContent 类继承,命名为 XxxxxMessage。

内容消息表示一个用户间发送的包含具体内容的消息,需要展现在聊天界面上,如文字消息、语音消息等。

通知消息基类

RCNotificationMessage 没有具体的功能定义,只是用来保证设计上良好的继承关系。

约定:如果需要定义一个通知类消息,请从 RCNotificationMessage 类继承,命名为 XxxxxNotificationMessage。

通知消息表示一个通知信息,可能展现在聊天界面上,如信息条通知;也可能是一个。

状态消息基类

RCStatusMessage 没有具体的功能定义,只是用来保证设计上良好的继承关系。

约定:如果需要定义一个状态类消息,请从 RCStatusMessage 类继承,命名为 XxxxxStatusMessage。

状态消息表示一个状态,用来实现如“对方正在输入”的功能。

消息的分类

消息分类

消息行为状态标识

内容类消息

表示一个用户间发送的包含具体内容的消息,需要展现在聊天界面上,如文字消息、语音消息等。

通知类消息

表示一个通知信息,可能展现在聊天界面上,如信息条通知;也可能是一个。

状态类消息

表示一个状态,用来实现如“对方正在输入”的功能。

内置内容类消息

文字消息

用来发送文字类消息,其中可以包括超链接,会自动识别。

消息 ObjectName:RC:TxtMsg

消息状态行为标识:MessageTag.ISPERSISTED | MessageTag.ISCOUNTED

消息的结构:{"content":"Hello world!","extra":""}

其中 content 为文字消息的文字内容,extra 可以放置任意的数据内容,也可以去掉此属性。

语音消息

用来发送语音片段消息,其中可以包括超链接,会自动识别。

消息 ObjectName:RC:VcMsg

消息状态行为标识:MessageTag.ISPERSISTED | MessageTag.ISCOUNTED

消息的结构:{"content":"bhZPzJXimRwrtvc=","duration":7,"extra":""}

其中 content 为语音消息录制转码成 AMR 格式后,进行 Base64 编码的结果值,duration 为语音消息的时长(单位:秒),extra 可以放置任意的数据内容,也可以去掉此属性。

图片消息

用来发送图片类消息。

消息 ObjectName:RC:ImgMsg

消息状态行为标识:MessageTag.ISPERSISTED | MessageTag.ISCOUNTED

消息的结构:{"content":"bhZPzJXimRwrtvc=","imageUri":"http://p1.cdn.com/fds78ruhi.jpg","extra":""}

图片消息包括两个主要部分:缩略图和大图,缩略图直接 Base64 编码后放入 content 中,大图首先上传到文件服务器(融云 SDK 中默认上传到七牛云存储),然后将云存储上的大图地址放入消息体中。流程示意如下:

App -> App: 压缩原图到大图尺寸

App -> File Server: 上传大图

File Server --> App: 返回上传大图的地址

App -> App: 压缩大图到缩略图并进行 Base64 转码

App -> RongCloud IM Server: 发送图片消息(内附缩略图内容和大图地址)

其中 content 为图片内容进行 Base64 编码的结果值,imageUri 为图片上传到图片存储服务器后的地址,extra 可以放置任意的数据内容,也可以去掉此属性。

缩略图尺寸为:240 x 240 像素,以宽度和高度中较长的边不超过 240 像素等比压缩。

大图尺寸为:960 x 960 像素,以宽度和高度中较长的边不超过 960 像素等比压缩。

图文消息

用来发送图文消息,包含一个标题,一段文字内容和一张图片。

消息 ObjectName:RC:ImgTextMsg

消息状态行为标识:MessageTag.ISPERSISTED | MessageTag.ISCOUNTED

消息的结构:{"title":"Big News","content":"I'm Ironman.","imageUri":"http://p1.cdn.com/fds78ruhi.jpg","extra":""}

其中 title 为消息的标题,content 为消息的文字内容,imageUri 为图片的地址,extra 可以放置任意的数据内容,也可以去掉此属性。

图片尺寸为:120 x 120 像素。

位置消息

用来发送地理位置消息。

消息 ObjectName:RC:LBSMsg

消息状态行为标识:MessageTag.ISPERSISTED | MessageTag.ISCOUNTED

消息的结构:{"content":"bhZPzJXimRwrtvc=","latitude":39.9139,"longitude":116.3917,"poi":"北京市朝阳区北苑路北辰泰岳大厦","extra":""}

其中 content 为地图缩略图内容进行 Base64 编码的结果值,latitude 为位置的纬度值,longitude 为位置的经度值,poi 为位置兴趣点名称,extra 可以放置任意的数据内容,也可以去掉此属性。

图片尺寸为:

内置通知类消息

提示条(小灰条)通知消息

用来发送在聊天会话页面显示的提示条(小灰条)通知。

消息 ObjectName:RC:InfoNtf

消息状态行为标识:MessageTag.ISPERSISTED

消息的结构:{"message":"请在聊天中注意人身财产安全",extra:""}

其中 message 为提示条消息内容,extra 可以放置任意的数据内容,也可以去掉此属性。

联系人(好友)通知消息

用来发送联系人操作(加好友等)的通知消息。

消息 ObjectName:RC:ContactNtf

消息状态行为标识:MessageTag.ISPERSISTED

消息的结构:{"operation":"Request","sourceUserId":"123","targetUserId":"456","message":"我是小艾,能加一下好友吗?","extra":""}

其中 operation 为联系人操作的指令,sourceUserId 为发出通知的用户 Id,targetUserId 为接收通知的用户 Id,message 为通知附带的消息内容,extra 可以放置任意的数据内容,也可以去掉此属性。

官方针对 operation 属性定义了 "Request", "AcceptResponse", "RejectResponse" 几个常量,也可以由开发者自行扩展。

资料通知消息

用来发送用户资料变更通知消息。

消息 ObjectName:RC:ProfileNtf

消息状态行为标识:MessageTag.ISPERSISTED

消息的结构:{"operation":"Update","data":"{\"nickname\":\"韩梅梅\", \"hometown\":\"beijing\"}","extra":""}

其中 operation 为资料通知操作,可以自行定义,data 为操作的数据,extra 可以放置任意的数据内容,也可以去掉此属性。

通用命令通知消息

用来发送通用的指令通知消息,消息内可以定义任意 JSON 内容。

消息 ObjectName:RC:CmdNtf

消息状态行为标识:MessageTag.ISPERSISTED

消息的结构:{"name":"AtPerson","data":"{\"sourceId\":\"9527\"}"}

其中 name 为命令名称,可以自行定义,data 为命令的内容。

内置状态类消息

对方正在输入的状态消息

用来发送对方正在输入的状态消息。

消息 ObjectName:RC:TypSts

消息状态行为标识:MessageTag.None

消息的结构:(空值。因为除了消息本身,不需要传递任何信息)

消息用来表示对方正在输入的状态,消息体内容为空。

自定义消息

要想自行定义消息,首先要了解 ObjectName 和 MessageTag 两个概念:

ObjectName 属性

ObjectName 是消息的全局标识,用来在各种场景下判断和区分不同的消息类型。

融云系统内置消息的命名规范为:RC:XxxMsg(内容类消息)或 RC:XxxNtf(通知类消息)或 RC:XxxSts(状态类消息),您在自定义消息时需要注意,不要以 "RC:" 开头,以避免与融云系统内置消息的 ObjectName 重名。

MessageTag 注解类型

MessageTag 定义约定了消息在客户端的行为和表现。MessageTag 的第一个参数为该消息的 ObjectName,第二个参数定义消息行为状态标识,可以对传值进行或运算:

枚举值

说明

MessageTag.NONE

为空值,不表示任何意义。

MessageTag.ISCOUNTED

表示客户端收到消息后,要进行未读消息计数(未读消息数增加 1),所有内容型消息都应该设置此值。非内容类消息暂不支持消息计数。

MessageTag.ISPERSISTED

表示客户端收到消息后,要进行存储,并在之后可以通过接口查询。

消息类型

消息基类

消息行为状态标识

内容类消息

MessageContent

MessageTag.ISPERSISTED | MessageTag.ISCOUNTED

通知类消息

NotificationMessage

MessageTag.ISPERSISTED

状态类消息

StatusMessage

MessageTag.NONE

定义消息

以文字消息的定义举例,定义如下:

@MessageTag(value = "RC:TxtMsg", flag = MessageTag.ISCOUNTED | MessageTag.ISPERSISTED)

public class TextMessage extends RongIMClient.MessageContent {

private String content;

private String extra;

/**

* 默认构造函数。

*/

protected TextMessage() {

}

/**

* 构造函数。

*

* @param in 初始化传入的 Parcel。

*/

public TextMessage(Parcel in) {

setExtra(ParcelUtils.readFromParcel(in));

setContent(ParcelUtils.readFromParcel(in));

setPushContent(ParcelUtils.readFromParcel(in));

}

/**

* 构造函数。

*

* @param data 初始化传入的二进制数据。

* @param message 此参数代码中并没有调用,后续将废弃。

*/

public TextMessage(byte[] data, RongIMClient.Message message) {

String jsonStr = null;

try {

jsonStr = new String(data, "UTF-8");

} catch (UnsupportedEncodingException e) {

RLog.e("JSONException", e.getMessage());

}

try {

JSONObject jsonObj = new JSONObject(jsonStr);

if (jsonObj.has("content"))

setContent(jsonObj.getString("content"));

if (jsonObj.has("extra"))

setExtra(jsonObj.getString("extra"));

} catch (JSONException e) {

RLog.e("JSONException", e.getMessage());

}

}

/**

* 构建一个文字消息实例。

*

* @return 文字消息实例。

*/

public static TextMessage obtain(String text) {

TextMessage model = new TextMessage();

model.setContent(text);

return model;

}

/**

* 描述了包含在 Parcelable 对象排列信息中的特殊对象的类型。

*

* @return 一个标志位,表明 Parcelable 对象特殊对象类型集合的排列。

*/

public int describeContents() {

return 0;

}

/**

* 将本地消息对象序列化为消息数据。

*

* @return 消息数据。

*/

@Override

public byte[] encode() {

JSONObject jsonObj = new JSONObject();

try {

jsonObj.put("content", getContent());

if (!TextUtils.isEmpty(getExtra()))

jsonObj.put("extra", getExtra());

} catch (JSONException e) {

RLog.e("JSONException", e.getMessage());

}

try {

return jsonObj.toString().getBytes("UTF-8");

} catch (UnsupportedEncodingException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return null;

}

/**

* 将类的数据写入外部提供的 Parcel 中。

*

* @param dest 对象被写入的 Parcel。

* @param flags 对象如何被写入的附加标志,可能是 0 或 PARCELABLE_WRITE_RETURN_VALUE。

*/

@Override

public void writeToParcel(Parcel dest, int flags) {

ParcelUtils.writeToParcel(dest, getExtra());

ParcelUtils.writeToParcel(dest, content);

ParcelUtils.writeToParcel(dest, pushContent);

}

/**

* 读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。

*/

public static final Creator CREATOR = new Creator() {

@Override

public TextMessage createFromParcel(Parcel source) {

return new TextMessage(source);

}

@Override

public TextMessage[] newArray(int size) {

return new TextMessage[size];

}

};

/**

* 获取文字消息的内容。

*

* @return 文字消息的内容。

*/

public String getContent() {

return content;

}

/**

* 设置文字消息的内容。

*

* @param content 文字消息的内容。

*/

public void setContent(String content) {

this.content = content;

}

/**

* 获取文字消息的内容。

*

* @return 文字消息的内容。

*/

public String getExtra() {

return extra;

}

/**

* 设置消息的附加内容。

*

* @param extra 消息的附加内容。

*/

public void setExtra(String extra) {

this.extra = extra;

}

}

注意:整个消息编码后的大小不要超过 128 KByte。

附带上传操作的消息

此处文档还暂未完成。

消息的发送

从客户端发送消息

发送消息的方法很简单,你只需要调用 RCIM 的 sendMessage(ConversationType conversationType,

java.lang.String targetId,

MessageContent message,

SendMessageCallback callback) 方法,传入相应的参数即可。

conversationType 为要发送的会话类型,targetId 是要发送的目标 Id,即消息接收者的 Id,message 参数就是要发送的消息类,参见本文消息定义节,callback 是发送消息后的回调。

我们对客户端消息发送的频率进行了限制,当前登录用户每秒中最多发送 5 条消息,超过频率后消息发送会失败。

代码如下:

// 发送文本消息。

private void sendTextMessage() {

TextMessage txtMsg = TextMessage.obtain("Hello honey. " + new Date(System.currentTimeMillis()));

sendMessage(txtMsg);

}

// 发送语音消息。

private void sendVoiceMessage() {

File voiceFile = new File(getCacheDir(), "voice.amr");

try {

// 读取音频文件。

InputStream is = getAssets().open("BlackBerry.amr");

OutputStream os = new FileOutputStream(voiceFile);

byte[] buffer = new byte[1024];

int bytesRead;

// 写入缓存文件。

while((bytesRead = is.read(buffer)) !=-1){

os.write(buffer, 0, bytesRead);

}

is.close();

os.flush();

os.close();

} catch (IOException e) {

e.printStackTrace();

}

VoiceMessage vocMsg = VoiceMessage.obtain(Uri.fromFile(voiceFile), 10);

sendMessage(vocMsg);

}

// 发送图片消息。

private void sendImageMessage() {

File imageFileSource = new File(getCacheDir(), "source.jpg");

File imageFileThumb = new File(getCacheDir(), "thumb.jpg");

try {

// 读取图片。

InputStream is = getAssets().open("emmy.jpg");

Bitmap bmpSource = BitmapFactory.decodeStream(is);

imageFileSource.createNewFile();

FileOutputStream fosSource = new FileOutputStream(imageFileSource);

// 保存原图。

bmpSource.compress(Bitmap.CompressFormat.JPEG, 100, fosSource);

// 创建缩略图变换矩阵。

Matrix m = new Matrix();

m.setRectToRect(new RectF(0, 0, bmpSource.getWidth(), bmpSource.getHeight()), new RectF(0, 0, 160, 160), Matrix.ScaleToFit.CENTER);

// 生成缩略图。

Bitmap bmpThumb = Bitmap.createBitmap(bmpSource, 0, 0, bmpSource.getWidth(), bmpSource.getHeight(), m, true);

imageFileThumb.createNewFile();

FileOutputStream fosThumb = new FileOutputStream(imageFileThumb);

// 保存缩略图。

bmpThumb.compress(Bitmap.CompressFormat.JPEG, 60, fosThumb);

} catch (IOException e) {

e.printStackTrace();

}

ImageMessage imgMsg = ImageMessage.obtain(Uri.fromFile(imageFileThumb), Uri.fromFile(imageFileSource));

sendMessage(imgMsg);

}

// 发送地理位置消息

private void sendLocationMessage() {

LocationMessage locMsg = LocationMessage.obtain(0, 0, "世界的原点", Uri.parse("http://map.com/map.jpg"));

sendMessage(locMsg);

}

// 发送图文消息。

private void sendRichContentMessage() {

RichContentMessage richMsg = RichContentMessage.obtain(

"Iron Man",

"Iron Man (Tony Stark) is a fictional character, a superhero that appears in books published by Marvel Comics.",

"http://news.com/news.jpg"

);

sendMessage(richMsg);

}

// 发送消息的封装。

private void sendMessage(RongIMClient.MessageContent messageContent) {

RCIM.getInstance().sendMessage(RongIMClient.ConversationType.PRIVATE, "1", messageContent, new RongIMClient.SendMessageCallback() {

@Override

public void onSuccess(int messageId) {

Log.d("Send:", "success: " + messageId);

}

@Override

public void onError(int messageId, ErrorCode errorCode) {

Log.d("Send:", "error: " + messageId);

}

@Override

public void onProgress(int messageId, int percent) {

Log.d("Send:", "on progress: " + messageId + ", " + percent + "%");

}

});

}

从服务端发送消息

从服务端发送消息,需要调用融云的服务端 API 接口。详细的文档说明请参见:Server 开发指南

服务端发消息目前共分如下几种类型:

会话类型

API 方法

用途

私聊 (PRIVATE)

/message/private/publish (/message/publish)

向某用户发送消息。

群组 (GROUP)

/message/group/publish

向某群组内发送消息,发送者可以为非群组成员。

聊天室 (CHATROOM)

/message/chatroom/publish

向某聊天室内发送消息,发送者可以为非聊天室成员。

系统 (SYSTEM)

/message/system/publish

向某用户发送消息。和私聊表现完全一致,只是会话类型不同。

代码示例如下(CoffeeScript 语言):

# 引用外部库

request = require 'request'

sha1 = require 'node-sha1'

# 开发者后台申请的 App Key 和 App Secret。

appKey = 'qd46yzrf4lf7f'

appSecret = 'v9phDBG9KoBG8e'

# 通用的 API 接口调用签名。

nonce = Math.floor(Math.random() * 100000 + 100000); # 生成随机数

timestamp = Math.floor(Date.now() / 1000) # 提取时间戳

signature = sha1(appSecret + nonce + timestamp) # 计算 SHA1 签名

# 定义消息类型。

objectName = 'RC:TxtMsg'

# 定义消息体。

jsonContent =

'content': '你好!',

'extra': '附加信息'

# 将消息体 JSON 转换为字符串。

content = JSON.stringify jsonContent

# 向服务器发送请求。

request.post

url: 'https://api.cn.ronghub.com/message/publish.json', # API 接口地址。

form: # 请求参数。

'fromUserId': '2'

'toUserId': '1'

'objectName': objectName

'content': content

'pushContent': '这里是推送显示的内容。'

'pushData': '{ "key": "这里是 APNS 的 payload 扩展。"}'

headers: # 请求头签名。

'App-Key': appKey

'Nonce': nonce

'Timestamp': timestamp

'Signature': signature

,

(error, response, body) -> # 请求回调。

# 显示返回结果。

console.log body

消息的编码

对于图片消息,需要在发送前生成一张小尺寸的缩略图,然后将缩略图文件的字节流进行 Base64 编码后放在 JSON 的 content 中发出。

对于语音消息,需要在发送前将录制的音频转为 AMR 格式,然后将 AMR 格式文件的字节流进行 Base64 编码后放在 JSON 的 content 中发出。

消息的接收

要想接收消息,主要是实现接收消息的监听器;另外,就是要注册接收到的消息,只有注册后的消息,系统才会识别。

注册消息类型

只有注册过的消息,系统才会正确的识别和分发。所以,接收消息前需要先注册消息。注意:系统内置的消息不需要注册,我们已经做了注册。

public class App extends Application {

@Override

public void onCreate() {

super.onCreate();

/**

* 初始化 SDK。

*/

RongIMClient.init(this);

try {

// 注册一个自定义消息类型。

RongIMClient.registerMessageType(GroupInvitationNotification.class);

} catch (AnnotationNotFoundException e) {

e.printStackTrace();

}

}

}

注册监听器

注册监听器就是调用 RCIM.getInstance().setReceiveMessageListener(RCIM.OnReceiveMessageListener listener) 方法。

注意:当消息监听器声明在 Activity 或 Fragment 中的时候,注意在 onDestroy 时设置为 null,否则会造成内存无法回收或内存溢出。

代码如下:

// 声明消息监听器,建议在 Application 中声明为成员变量。

final RCIM.OnReceiveMessageListener listener = new RCIM.OnReceiveMessageListener() {

@Override

public void onReceived(RongIMClient.Message message, int left) {

// 输出消息类型。

Log.d("Receive:", message.getObjectName());

// 此处输出判断是否是文字消息,并输出,其他消息同理。

if (message.getContent() instanceof TextMessage) {

final TextMessage textMessage = (TextMessage) message.getContent();

Log.d("onReceived", "Text Message: " + textMessage.getContent());

}

}

};

// 连接融云服务器。

RCIM.connect(token, new RongIMClient.ConnectCallback() {

@Override

public void onSuccess(String s) {

// 此处处理连接成功。

Log.d("Connect:", "Login successfully.");

// 设置消息监听器。

RCIM.getInstance().setReceiveMessageListener(listener);

}

@Override

public void onError(ErrorCode errorCode) {

// 此处处理连接出错。

Log.d("Connect:", "Login failed.");

}

});

判断消息类型

接收到消息后,需要对消息的类型进行判断,判断的方法主要依赖于 ObjectName。

本节完整的代码如下:

public class App extends Application {

@Override

public void onCreate() {

super.onCreate();

// 初始化。

RCIM.init(this, "qdds9jifewf7f", R.drawable.ic_launcher);

// 从您的应用服务器请求,以获取 Token。在本示例中我们直接在下面 hardcode 给 token 赋值。

// String token = getTokenFromAppServer();

// 声明消息监听器,建议在 Application 中声明为成员变量。

final RCIM.OnReceiveMessageListener listener = new RCIM.OnReceiveMessageListener() {

@Override

public void onReceived(RongIMClient.Message message, int left) {

// 输出消息类型。

Log.d("Receive:", message.getObjectName());

// 此处输出判断是否是文字消息,并输出,其他消息同理。

if (message.getContent() instanceof TextMessage) {

final TextMessage textMessage = (TextMessage) message.getContent();

Log.d("onReceived", "Text Message: " + textMessage.getContent());

}

}

};

// 此处直接 hardcode 给 token 赋值,请替换为您自己的 Token。

String token = "ptGbXapcyr+w8jTRzykWDBViWrePIfq0GuT89sdfDDgX+cDua7sRBAu4T2Id/k8vs/+ZK4KVTDkv4AhfjCAKgQ==";

// 连接融云服务器。

try {

RCIM.connect(token, new RongIMClient.ConnectCallback() {

@Override

public void onSuccess(String s) {

// 此处处理连接成功。

Log.d("Connect:", "Login successfully.");

// 设置消息监听器。

RCIM.getInstance().setReceiveMessageListener(listener);

}

@Override

public void onError(ErrorCode errorCode) {

// 此处处理连接出错。

Log.d("Connect:", "Login failed.");

}

});

} catch (Exception e) {

e.printStackTrace();

}

}

}

消息的解码

消息解码过程及代码示例同消息编码。

消息的读取和管理

获取会话列表和会话

会话列表就是最近聊天的联系人(好友)集合。

获取所有会话列表的方法是调用 RongIMClient.getInstance().getConversationList()

获取群组会话列表的方法是调用 RongIMClient.getInstance().getGroupConversationList()

获取某一会话的方法是调用 RongIMClient.getInstance().getConversation(RongIMClient.ConversationType conversationType, java.lang.String targetId)

移除会话

移除会话只是将会话从会话列表中移除,并不会移除会话中的消息,如果该会话收到新的消息,会重新在会话列表中显示出来。

移除会话的方法是调用 RongIMClient.getInstance().removeConversation(RongIMClient.ConversationType conversationType, java.lang.String targetId)

清空会话

清空会话不但会将会话从会话列表中移除,还会删除会话中的所有消息。注意区别于删除会话。

清空某一类或几类会话的方法是调用 RongIMClient.getInstance().clearConversations(RongIMClient.ConversationType... conversationTypes)

获取消息列表

消息列表就是一个会话中所有消息的集合。

获取最近历史消息的方法是调用 RongIMClient.getInstance().getLatestMessages(RongIMClient.ConversationType conversationType, java.lang.String targetId, int count)

获取分页的历史消息的方法是调用 RongIMClient.getInstance().getHistoryMessages(RongIMClient.ConversationType conversationType, java.lang.String targetId, int oldestMessageId, int count)

还可以按照消息的类型(ObjectName)获取分页的历史消息的方法 RongIMClient.getInstance().getHistoryMessages(RongIMClient.ConversationType conversationType, java.lang.String targetId, java.lang.String objectName, int oldestMessageId, int count)

删除消息

删除消息不同于删除会话,会直接清空本地的消息记录数据。

删除一条或多条消息的方法是调用 RongIMClient.getInstance().deleteMessages(int[] messageIds)

也可以直接清空某一个会话的所有消息 RongIMClient.getInstance().clearMessages(RongIMClient.ConversationType conversationType, java.lang.String targetId)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值