差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
im:android:basics:message [2019/11/25 09:58]
huanxinfudh
im:android:basics:message [2022/05/18 09:02] (当前版本)
jennifer.zeng [接收消息]
行 1: 行 1:
 ====== 消息 ====== ====== 消息 ======
  
 +更新时间:2021-12-31
 +
 +新版文档见:[[ccim:​android:​message1|消息管理 Android]]。
 ---- ----
  
行 19: 行 22:
 </​code>​ </​code>​
  
-====发送语音消息==== +====发送表情消息==== 
 +发表情消息实质上是发文本消息。接收方收到文本消息后,首先查询文本消息是否是表情消息,如果是,则显示该文本消息为对应的表情图片。可以参考[[https://​unicode.org/​emoji/​charts/​full-emoji-list.html |emoji列表]]来做表情图片和对应的文本字符串的映射。也可以自行维护表情图片和文本字符串的映射。
 <code java> <code java>
-//filePath为语音件路径length录音时间(秒) +//创建一条表情消息。表情消息实质上是一个字消息。emojiCode是表情图片对应的文本字符串toChatUsername对方用户或者群聊的id,后文皆是如此 
-EMMessage message = EMMessage.createVoiceSendMessage(filePath, length, toChatUsername);​+EMMessage message = EMMessage.createTxtSendMessage(emojiCode, toChatUsername);​
 //​如果是群聊,设置chattype,默认是单聊 //​如果是群聊,设置chattype,默认是单聊
 if (chatType == CHATTYPE_GROUP) if (chatType == CHATTYPE_GROUP)
  message.setChatType(ChatType.GroupChat);​  message.setChatType(ChatType.GroupChat);​
 +//​发送消息
 EMClient.getInstance().chatManager().sendMessage(message);​ EMClient.getInstance().chatManager().sendMessage(message);​
 </​code>​ </​code>​
  
-====发送视频消息====+==== 发送语音消息 ====
  
 <code java> <code java>
-//videoPath视频本地路径thumbPath视频预览图路径,videoLength为视频时间长度 +//voiceUri ​语音文件本地资源标志符length ​录音时间(秒)  
-EMMessage message = EMMessage.createVideoSendMessage(videoPath, thumbPathvideoLength, toChatUsername);​ +EMMessage message = EMMessage.createVoiceSendMessage(voiceUrilength, toChatUsername);​  
-//​如果是群聊,设置chattype,默认是单聊 +//​如果是群聊,设置 chattype,默认是单聊  
-if (chatType == CHATTYPE_GROUP) +if (chatType == CHATTYPE_GROUP)  
- message.setChatType(ChatType.GroupChat);​+    message.setChatType(ChatType.GroupChat); ​
 EMClient.getInstance().chatManager().sendMessage(message);​ EMClient.getInstance().chatManager().sendMessage(message);​
 </​code>​ </​code>​
  
-====发送图片消息====+发送成功后,获取语音消息附件: 
 + 
 +<​code>​ 
 +EMVoiceMessageBody voiceBody = (EMVoiceMessageBody) msg.getBody();​ 
 +//​获取语音文件在服务器的地址 
 +String voiceRemoteUrl = voiceBody.getRemoteUrl();​ 
 +//​本地语音文件的资源路径 
 +Uri voiceLocalUri = voiceBody.getLocalUri();​ 
 +</​code>​ 
 +''​适配 AndroidQ 及以上手机时,获取本地资源请调用 voiceBody.getLocalUri(),相应的 voiceBody.getLocalUrl() 方法已经被废弃!''​ 
 +==== 发送视频消息 ====
  
 <code java> <code java>
-//imagePath图片本地路径false不发送原(默认超过100k的图片会压缩后发给对方)需要发送原图传true +//videoLocalUri ​视频本地资源标志符thumbLocalUri ​视频预览路径videoLength 为视频时间长度 
-EMMessage.createImageSendMessage(imagePathfalse, toChatUsername);​ +EMMessage message = EMMessage.createVideoSendMessage(videoLocalUri,​ thumbLocalUrivideoLength, toChatUsername);​ 
-//​如果是群聊,设置chattype,默认是单聊+//​如果是群聊,设置 chattype,默认是单聊
 if (chatType == CHATTYPE_GROUP) if (chatType == CHATTYPE_GROUP)
- message.setChatType(ChatType.GroupChat);​+   message.setChatType(ChatType.GroupChat);​
 EMClient.getInstance().chatManager().sendMessage(message);​ EMClient.getInstance().chatManager().sendMessage(message);​
 </​code>​ </​code>​
  
 +发送成功后,获取视频消息缩略图及附件
 +
 +<​code>​
 +EMVideoMessageBody videoBody = (EMVideoMessageBody) message.getBody();​
 +//​获取视频文件在服务器的路径
 +String videoRemoteUrl = videoBody.getRemoteUrl();​
 +//​获取缩略图在服务器的路径
 +String thumbnailUrl = videoBody.getThumbnailUrl();​
 +//​本地视频文件的资源路径
 +Uri videoLocalUri = videoBody.getLocalUri();​
 +//​本地视频缩略图资源路径
 +Uri localThumbUri = videoBody.getLocalThumbUri();​
 +</​code>​
 +''​适配 AndroidQ 及以上手机时,获取本地资源请调用 videoBody.getLocalUri(),相应的 videoBody.getLocalUrl() 方法已经被废弃!''​
 +==== 发送图片消息 ====
 +
 +<code java>
 +//imageUri 为图片本地资源标志符,false 为不发送原图(默认超过 100k 的图片会压缩后发给对方),需要发送原图传 true 
 +EMMessage.createImageSendMessage(imageUri,​ false, toChatUsername); ​
 +//​如果是群聊,设置 chattype,默认是单聊 ​
 +if (chatType == CHATTYPE_GROUP) ​
 +    message.setChatType(ChatType.GroupChat); ​
 +EMClient.getInstance().chatManager().sendMessage(message);​
 +</​code>​
 +
 +发送成功后,获取图片消息缩略图及附件
 +
 +<​code>​
 +EMImageMessageBody imgBody = (EMImageMessageBody) message.getBody();​
 +//​获取图片文件在服务器的路径
 +String imgRemoteUrl = imgBody.getRemoteUrl();​
 +//​获取图片缩略图在服务器的路径
 +String thumbnailUrl = imgBody.getThumbnailUrl();​
 +//​本地图片文件的资源路径
 +Uri imgLocalUri = imgBody.getLocalUri();​
 +//​本地图片缩略图资源路径
 +Uri thumbnailLocalUri = imgBody.thumbnailLocalUri();​
 +</​code>​
 +''​适配 AndroidQ 及以上手机时,获取本地资源请调用 imgBody.getLocalUri(),相应的 imgBody.getLocalUrl() 方法已经被废弃!''​
 ====发送地理位置消息==== ====发送地理位置消息====
  
行 63: 行 116:
 </​code>​ </​code>​
  
-====发送文件消息====+==== 发送文件消息 ====
  
 <code java> <code java>
-EMMessage message = EMMessage.createFileSendMessage(filePath, toChatUsername);​ +//​fileLocalUri 为本地资源标志符 
-// 如果是群聊,设置chattype,默认是单聊+EMMessage message = EMMessage.createFileSendMessage(fileLocalUri, toChatUsername);​ 
 +// 如果是群聊,设置 chattype,默认是单聊
 if (chatType == CHATTYPE_GROUP) if (chatType == CHATTYPE_GROUP)
- message.setChatType(ChatType.GroupChat);​+    ​message.setChatType(ChatType.GroupChat);​
 EMClient.getInstance().chatManager().sendMessage(message);​ EMClient.getInstance().chatManager().sendMessage(message);​
 </​code>​ </​code>​
  
 +发送成功后,获取文件消息附件
 +
 +<​code>​
 +EMNormalFileMessageBody fileMessageBody = (EMNormalFileMessageBody) message.getBody();​
 +//​获取文件在服务器的路径
 +String fileRemoteUrl = fileMessageBody.getRemoteUrl();​
 +//​本地文件的资源路径
 +Uri fileLocalUri = fileMessageBody.getLocalUri();​
 +</​code>​
 +''​适配 AndroidQ 及以上手机时,获取本地资源请调用 fileMessageBody.getLocalUri(),相应的 fileMessageBody.getLocalUrl() 方法已经被废弃!''​
 ==== 发送透传消息 ==== ==== 发送透传消息 ====
  
-透传消息能做什么:头像、昵称的更新等。可以把透传消息理解为一条指令,通过发送这条指令给对方,告诉对方要做的 action,收到消息可以自定义处理的一种消息。(透传消息不会存入本地数据库中,所以在 UI 上是不会显示的)。另,以“em_”和“easemob::​”开头的action为内部保留字段,注意不要使用+透传消息能做什么:头像、昵称的更新等。可以把透传消息理解为一条指令,通过发送这条指令给对方,告诉对方要做的 action,收到消息可以自定义处理的一种消息。(透传消息不会存入本地数据库中,所以在 UI 上是不会显示的)。另,以 “em_” 和 “easemob::​” 开头的 action 为内部保留字段,注意不要使用
  
 <code java> <code java>
行 89: 行 153:
 EMClient.getInstance().chatManager().sendMessage(cmdMsg);​ EMClient.getInstance().chatManager().sendMessage(cmdMsg);​
 </​code>​ </​code>​
 +
 +==== 发送自定义类型消息 ====
 +用户可以在以上几种消息之外,自己定义消息类型,方便用户的业务处理。
 +自定义消息类型支持用户自己设置一个消息的类型名称,这样用户可以添加多种自定义消息。
 +自定义消息的内容部分是key,value格式的,用户需要自己添加并解析该内容。
 +
 +<code java>
 +
 +EMMessage customMessage = EMMessage.createSendMessage(EMMessage.Type.CUSTOM);​
 +// event为需要传递的自定义消息事件,比如礼物消息,可以设置event = "​gift"​
 +EMCustomMessageBody customBody = new EMCustomMessageBody(event);​
 +// params类型为Map<​String,​ String>
 +customBody.setParams(params);​
 +customMessage.addBody(customBody);​
 +// to指另一方环信id(或者群组id,聊天室id)
 +customMessage.setTo(to);​
 +// 如果是群聊,设置chattype,默认是单聊
 +customMessage.setChatType(chatType);​
 +EMClient.getInstance().chatManager().sendMessage(customMessage);​
 +        ​
 +</​code>​
 +
 +
 +==== 设置群消息是否需要已读回执(增值服务) ====
 +
 +当消息为群消息时,消息发送方(目前为管理员和群主)可以设置此消息是否需要已读回执,如需要,则设置 EMMessage 的方法 setIsNeedGroupAck() 为 YES,之后发送。
 +
 +<​code>​
 +public EMMessage createDingMessage(String to, String content) {
 +        EMMessage message = EMMessage.createTxtSendMessage(content,​ to);
 +        message.setIsNeedGroupAck(true);​
 +        return message;
 +    }
 +    ​
 + </​code>​
 +
 +
 +==== 发送群消息已读回执 ====
 +
 +<code objc>
 +public void sendAckMessage(EMMessage message) {
 +        if (!validateMessage(message)) {
 +            return;
 +        }
 +
 +        if (message.isAcked()) {
 +            return;
 +        }
 +
 +        // May a user login from multiple devices, so do not need to send the ack msg.
 +        if (EMClient.getInstance().getCurrentUser().equalsIgnoreCase(message.getFrom())) {
 +            return;
 +        }
 +
 +        try {
 +            if (message.isNeedGroupAck() && !message.isUnread()) {
 +                String to = message.conversationId();​ // do not use getFrom() here
 +                String msgId = message.getMsgId();​
 +                EMClient.getInstance().chatManager().ackGroupMessageRead(to,​ msgId, ((EMTextMessageBody)message.getBody()).getMessage());​
 +                message.setUnread(false);​
 +                EMLog.i(TAG,​ "Send the group ack cmd-type message."​);​
 +            }
 +        } catch (Exception e) {
 +            EMLog.d(TAG,​ e.getMessage());​
 +        }
 +    }
 +</​code>​
 +
 +当发送群已读回执后,消息发送方对应 EMMessage 的 groupAckCount 属性会有相应变化;
 +
 +
 +==== 群消息已读回调 ====
 +群消息已读回调在消息监听类EMMessageListener中。
 +<​code>​
 + /**
 + * \~chinese
 + * 接受到群组消息体的已读回执,​ 消息的接收方已经阅读此消息。
 + */
 +         void onGroupMessageRead(List<​EMGroupReadAck>​ groupReadAcks) {
 +        }
 +
 +</​code>​
 +
 +==== 获取群消息已读回执详情 ====
 +如果想实现群消息已读回执的列表显示,可以通过下列接口获取到已读回执的详情。
 +
 +<​code>​
 +/**
 + * \~chinese
 + * 从服务器获取群组消息回执详情
 + * @param msgId 消息id
 + * @param pageSize 获取的页面大小
 + * @param startAckId 已读回执的id,如果为空,从最新的回执向前开始获取
 + * @return 返回消息列表和用于继续获取群消息回执的Cursor
 + */
 + public void asyncFetchGroupReadAcks(final String msgId, final int pageSize,
 + final String startAckId, final EMValueCallBack<​EMCursorResult<​EMGroupReadAck>>​ callBack) {
 +
 + }
 +</​code>​
 +
  
 ==== 发送扩展消息 ==== ==== 发送扩展消息 ====
行 117: 行 282:
  
 <code java> <code java>
-EMClient.getInstance().chatManager().addMessageListener(msgListener);​ 
 EMMessageListener msgListener = new EMMessageListener() { EMMessageListener msgListener = new EMMessageListener() {
   
行 149: 行 313:
  }  }
 }; };
 +EMClient.getInstance().chatManager().addMessageListener(msgListener);​
  
 记得在不需要的时候移除listener,如在activity的onDestroy()时 记得在不需要的时候移除listener,如在activity的onDestroy()时
 EMClient.getInstance().chatManager().removeMessageListener(msgListener);​ EMClient.getInstance().chatManager().removeMessageListener(msgListener);​
 </​code>​ </​code>​
 +===== 下载缩略图及附件 =====
 +
 +==== 下载缩略图 ====
 +
 +如果设置了自动下载,即EMClient.getInstance().getOptions().getAutodownloadThumbnail()为true,SDK接收到消息后会下载缩略图;\\
 +如果没有设置自动下载,需主动调用EMClient.getInstance().chatManager().downloadThumbnail(message)下载。\\
 +下载完成后,调用相应消息body的thumbnailLocalUri()去获取缩略图路径。\\
 +例如:
 +<​code>​
 +EMImageMessageBody imgBody = (EMImageMessageBody) message.getBody();​
 +//​本地图片缩略图资源路径
 +Uri thumbnailLocalUri = imgBody.thumbnailLocalUri();​
 +</​code>​
 +==== 下载附件 ====
 +
 +下载附件的方法为:EMClient.getInstance().chatManager().downloadAttachment(message);​\\
 +下载完成后,调用相应消息body的getLocalUri()去获取附件路径。\\
 +例如:
 +<​code>​
 +EMImageMessageBody imgBody = (EMImageMessageBody) message.getBody();​
 +//​本地图片文件的资源路径
 +Uri imgLocalUri = imgBody.getLocalUri();​
 +</​code>​
 +
 ===== 监听消息状态 ===== ===== 监听消息状态 =====
  
行 170: 行 359:
 //​获取此会话的所有消息 //​获取此会话的所有消息
 List<​EMMessage>​ messages = conversation.getAllMessages();​ List<​EMMessage>​ messages = conversation.getAllMessages();​
-//​SDK初始化加载的聊天记录为20条,到顶时需要去DB里获取更多+//​SDK初始化每个会话加载的聊天记录为1条,可以去DB里获取更多
 //​获取startMsgId之前的pagesize条消息,此方法获取的messages SDK会自动存入到此会话中,APP中无需再次把获取到的messages添加到会话中 //​获取startMsgId之前的pagesize条消息,此方法获取的messages SDK会自动存入到此会话中,APP中无需再次把获取到的messages添加到会话中
 List<​EMMessage>​ messages = conversation.loadMoreMsgFromDB(startMsgId,​ pagesize); List<​EMMessage>​ messages = conversation.loadMoreMsgFromDB(startMsgId,​ pagesize);
行 221: 行 410:
  * @param conversationId 会话名称  * @param conversationId 会话名称
  * @param type 会话类型  * @param type 会话类型
- * @param pageSize 获取的页面大小+ * @param pageSize 获取的页面大小(一次最多50条)
  * @param startMsgId 漫游消息的开始消息id,如果为空,从最新的消息向前开始获取  * @param startMsgId 漫游消息的开始消息id,如果为空,从最新的消息向前开始获取
  * @return 返回消息列表和用于继续获取历史消息的Cursor  * @return 返回消息列表和用于继续获取历史消息的Cursor
行 237: 行 426:
  */  */
  public void asyncFetchHistoryMessage(String conversationId,​ EMConversationType type, int pageSize, String startMsgId, EMValueCallBack<​EMCursorResult<​EMMessage>>​ callBack) ​  public void asyncFetchHistoryMessage(String conversationId,​ EMConversationType type, int pageSize, String startMsgId, EMValueCallBack<​EMCursorResult<​EMMessage>>​ callBack) ​
 +</​code>​
 +
 +===== 从服务器获取会话列表 =====
 +
 +''​该功能需联系商务进行开通,开通后默认用户可以拉取 7 天内的 10 个会话和每个会话中最新一条聊天记录,如需调整会话数量请联系环信商务经理(您可以在环信通讯云管理后台首页,扫描二维码联系您的商务经理)。''​
 +
 +建议此 API 在首次安装应用时或者本地没有会话的时候调用,其他时候使用本地的会话 API 即可。
 +
 +
 +<​code>​
 +EMClient.getInstance().chatManager().asyncFetchConversationsFromServer(new EMValueCallBack<​Map<​String,​ EMConversation>>​() {
 +    @Override
 +    public void onSuccess(Map<​String,​ EMConversation>​ value) {
 +        // 获取会话成功后的处理逻辑
 +    }
 +    @Override
 +    public void onError(int error, String errorMsg) {
 +        // 获取会话失败处理逻辑
 +    }
 +});
 </​code>​ </​code>​
  
 ===== 撤回消息功能 ===== ===== 撤回消息功能 =====
-消息撤回功能可以撤回一定时间内发送出去的消息,目前只能是两分钟,不能修改。+消息撤回功能可以撤回一定时间内发送出去的消息,消息撤回时限默认2分钟,可根据开发者需求以AppKey为单位进行单独设置,如需修改请联系环信商务
  
 消息撤回为增值功能,请联系环信商务开通。 消息撤回为增值功能,请联系环信商务开通。
行 248: 行 457:
 </​code>​ </​code>​
  
 +===== 消息已读回执 =====
 +消息已读回执功能目前仅适用于单聊(ChatType.Chat),推荐使用方案为会话已读回执(conversation ack)+单条消息已读回执(read ack)结合实现,可减少发送read ack消息量。\\
 +**''​注:群消息已读回执功能为增值服务,具体使用请跳转到[[http://​docs-im.easemob.com/​im/​android/​basics/​message#​%E8%AE%BE%E7%BD%AE%E7%BE%A4%E6%B6%88%E6%81%AF%E6%98%AF%E5%90%A6%E9%9C%80%E8%A6%81%E5%B7%B2%E8%AF%BB%E5%9B%9E%E6%89%A7_%E5%A2%9E%E5%80%BC%E6%9C%8D%E5%8A%A1|群消息已读回执]]。''​**
 +==== 发送已读回执消息 ====
 +推荐进入会话首先发送会话已读回执(conversation ack)。
 +<code java>
 +try {
 +    EMClient.getInstance().chatManager().ackConversationRead(conversationId);​
 +} catch (HyphenateException e) {
 +    e.printStackTrace();​
 +}
 +</​code>​
 +在会话页面,可以在接收到消息时,根据消息类型发送消息已读回执(read ack),如下所示
 +<code java>
 +EMClient.getInstance().chatManager().addMessageListener(new EMMessageListener() {
 +    ......
 +    ​
 +    @Override
 +    public void onMessageReceived(List<​EMMessage>​ messages) {
 +        ......
 +        sendReadAck(message);​
 +        ......
 +    }
 +    ​
 +    ......
 +});
 +
 +/**
 +* 发送已读回执
 +* @param message
 +*/
 +public void sendReadAck(EMMessage message) {
 +    //​是接收的消息,未发送过read ack消息且是单聊
 +    if(message.direct() == EMMessage.Direct.RECEIVE
 +            && !message.isAcked()
 +            && message.getChatType() == EMMessage.ChatType.Chat) {
 +        EMMessage.Type type = message.getType();​
 +        //​视频,语音及文件需要点击后再发送,​这个可以根据需求进行调整
 +        if(type == EMMessage.Type.VIDEO || type == EMMessage.Type.VOICE || type == EMMessage.Type.FILE) {
 +            return;
 +        }
 +        try {
 +            EMClient.getInstance().chatManager().ackMessageRead(message.getFrom(),​ message.getMsgId());​
 +        } catch (HyphenateException e) {
 +            e.printStackTrace();​
 +        }
 +    }
 +}
 +</​code>​
 +
 +==== 监听已读回执回调 ====
 +(1)设置会话已读回执的监听
 +<code java>
 +EMClient.getInstance().chatManager().addConversationListener(new EMConversationListener() {
 +    ......
 +
 +    @Override
 +    public void onConversationRead(String from, String to) {
 +        //​添加刷新页面通知等逻辑
 +    }
 +});
 +</​code>​
 +接收到会话已读回执(channel ack)回调后,SDK会在内部将会话相关消息置为对方已读,开发者需要在接收到此回调后,进行页面刷新等操作。\\
 +
 +(2)设置消息已读回执的监听
 +<code java>
 +EMClient.getInstance().chatManager().addMessageListener(new EMMessageListener() {
 +    ......
 +
 +    @Override
 +    public void onMessageRead(List<​EMMessage>​ messages) {
 +        //​添加刷新消息等逻辑
 +    }
 +
 +    ......
 +});
 +</​code>​
 +接收到read ack回调后,SDK会在内部将消息置为对方已读,开发者需要在接收到此回调后,进行消息刷新等操作。
 +
 +**注:判断是否对方已读根据消息的''​isAcked()''​方法进行判断,返回true为对方已读,开发者可以根据此字段进行UI界面的展示及刷新。**
 +
 +===== 会话已读回执 =====
 +
 +会话已读回执用于需要获知接收方是否阅读消息的场景,目前仅适用于单聊(ChatType.Chat)。\\
 +**''​注:群消息已读回执功能为增值服务,具体使用请跳转到[[http://​docs-im.easemob.com/​im/​android/​basics/​message#​%E8%AE%BE%E7%BD%AE%E7%BE%A4%E6%B6%88%E6%81%AF%E6%98%AF%E5%90%A6%E9%9C%80%E8%A6%81%E5%B7%B2%E8%AF%BB%E5%9B%9E%E6%89%A7_%E5%A2%9E%E5%80%BC%E6%9C%8D%E5%8A%A1|群消息已读回执]]。''​**
 +
 +==== 发送已读回执消息 ====
 +
 +推荐进入会话页面,根据会话是否有未读消息,发送会话已读回执(conversation ack),有则发送,没有则不再发送。\\
 +<code java>
 +try {
 +    EMClient.getInstance().chatManager().ackConversationRead(conversationId);​
 +} catch (HyphenateException e) {
 +    e.printStackTrace();​
 +}
 +</​code>​
 +注:该方法为异步方法,需要捕捉异常。
 +
 +==== 监听已读回执回调 ====
 +
 +<code java>
 +EMClient.getInstance().addConversationListener(new EMConversationListener() {
 +    ……
 +
 +    @Override
 +    public void onConversationRead(String from, String to) {
 +        //​添加刷新页面通知等逻辑
 +    }
 +});
 +</​code>​
 +注:onConversationRead中的from和to与消息(EMMessage)中的定义相同。\\
 +
 +会回调onConversationRead的场景:\\
 +(1)消息被接收方阅读,且发送了已读回执(conversation ack);\\
 +(2)多端多设备登录场景下,一端发送会话已读回执(conversation ack),服务器端会将未读消息数置为0,同时其他端会回调此方法;\\
 +
 +==== 最佳实践 ====
  
 +推荐使用方案为会话已读回执(conversation ack)+[[im:​android:​basics:​message#​消息已读回执|单条消息已读回执(read ack)]]结合实现,可减少发送read ack消息量。\\
 +(1)未启动聊天页面的情况下,有未读消息,点击进入聊天页面,调用会话已读回执(conversation ack);\\
 +(2)已经启动聊天页面内的情况下,接收到消息,即发送单条消息已读回执 (read ack) ,具体实现可参考:[[im:​android:​basics:​message#​发送已读回执消息|发送 read ack 消息]]。\\
 ===== 分页获取历史消息记录 ===== ===== 分页获取历史消息记录 =====
  
行 269: 行 598:
 } }
 </​code>​ </​code>​
-===== 获取所有会话 =====+===== 获取本地所有会话 =====
 <code java> <code java>
 Map<​String,​ EMConversation>​ conversations = EMClient.getInstance().chatManager().getAllConversations();​ Map<​String,​ EMConversation>​ conversations = EMClient.getInstance().chatManager().getAllConversations();​
 </​code>​ </​code>​
 如果出现偶尔返回的conversations的sizi为0,那很有可能是没有调用''​EMClient.getInstance().chatManager().loadAllConversations()''​,或者调用顺序不对,具体用法请参考[[30androidsdkbasics#​登录|登录]]章节。 如果出现偶尔返回的conversations的sizi为0,那很有可能是没有调用''​EMClient.getInstance().chatManager().loadAllConversations()''​,或者调用顺序不对,具体用法请参考[[30androidsdkbasics#​登录|登录]]章节。
-    ​+===== 从服务器获取会话列表 ===== 
 + 
 +''​该功能需联系商务开通,开通后,用户默认可拉取 7 天内的 10 个会话(每个会话包含最新一条历史消息),如需调整会话数量请联系环信商务经理(您可以在环信通讯云管理后台首页,扫描二维码联系您的商务经理)。''​ 
 + 
 +建议此 API 在首次安装应用时或者本地没有会话的时候调用,其他时候使用本地的会话 API 即可。 
 + 
 +使用该功能需要联系您的商务经理进行开通。(您可以在环信通讯云管理后台首页,扫描二维码联系您的商务经理) 
 +<​code>​ 
 +EMClient.getInstance().chatManager().asyncFetchConversationsFromServer(new EMValueCallBack<​Map<​String,​ EMConversation>>​() { 
 +    @Override 
 +    public void onSuccess(Map<​String,​ EMConversation>​ value) { 
 +        // 获取会话成功后的处理逻辑 
 +    } 
 +    @Override 
 +    public void onError(int error, String errorMsg) { 
 +        // 获取会话失败处理逻辑 
 +    } 
 +}); 
 +</​code>​ 
 ===== 删除会话及聊天记录 ===== ===== 删除会话及聊天记录 =====
  
行 291: 行 639:
  
 ===== 导入消息到数据库 ===== ===== 导入消息到数据库 =====
 +如果有从2.x SDK或者其他第三方SDK升级到目前3.x SDK的需要,可以使用下面的接口,构造EMMessage 对象,将历史消息导入到本地数据库中。
 <code java> <code java>
 EMClient.getInstance().chatManager().importMessages(msgs);​ EMClient.getInstance().chatManager().importMessages(msgs);​
行 307: 行 655:
 </​code>​ </​code>​
  
 +===== 更新消息到 SDK 本地数据库 =====
 +
 +<code java>
 +/**
 +  *  更新消息到 SDK 本地数据库。
 +  *  消息更新后,会话的 latestMessage 等属性进行相应更新,不能更新消息 ID。
 +  *
 +  *  @param msg 要更新的消息。
 +  */
 +    public boolean updateMessage(EMMessage msg) 
 +</​code>​
 +
 +
 +===== 翻译 =====
 +
 +翻译功能使用微软翻译服务实现,用户可将文本翻译为所有微软翻译服务支持的语言,并提供译文存储功能。
 +
 +使用翻译功能需要满足以下条件:
 +  - 已完成环信IM''​(3.8.9以上版本)''​基本集成,账户登录成功
 +  - 已创建微软翻译服务资源,并获取到翻译参数,创建过程参见https://​docs.microsoft.com/​zh-cn/​azure/​cognitive-services/​translator/​translator-how-to-signup
 +
 +使用过程如下:
 +  - 翻译模块初始化
 +  - 获取支持的语言/​翻译文本消息
 +
 +==== 翻译模块初始化 ====
 +
 +需要将创建微软翻译资源生成的参数(subscriptionKey、endpoint、location)设置到SDK中并初始化,调用如下
 +<​code>​
 +EMTranslateParams params = new EMTranslateParams(subscriptionKey,​ endpoint, location);
 +
 +EMClient.getInstance().translationManager().init(params);​
 +</​code>​
 +
 +==== 获取翻译服务支持的语言 ====
 +SDK支持所有微软翻译服务支持的语言,获取支持的语言的过程如下:
 +<​code>​
 +//​获取到支持的翻译语言
 +List<​EMLanguage>​ emLanguageList = EMClient.getInstance().translationManager().getSupportedLanguages();​
 +</​code>​
 +
 +==== 文本翻译 ====
 +设置完翻译参数后,用户可以调用消息翻译接口,进行翻译。每一条翻译信息,都有一个所属的会话conversationId,相当于译文所属的分组。翻译调用过程如下:
 +<​code>​
 +EMClient.getInstance().translationManager().translate("​msgId",​
 +         "​conversationId",​
 +         "​要翻译的文本内容",​
 +         "​en-us",​
 +         new EMValueCallBack<​EMTranslationResult>​() {});
 +</​code>​
 +
 +翻译成功之后,SDK会将译文存储到本地数据库。用户可根据译文的msgId从数据库获取译文,不存在则返回空。获取过程如下:
 +<​code>​
 +EMTranslationResult result = EMClient.getInstance().translationManager().getTranslationResult("​msgId"​);​
 +</​code>​
 +
 +==== 退出 ====
 +当账户退出时,需要清理缓存中当前账户的译文信息,需要调用如下接口
 +<​code>​
 +EMClient.getInstance().translationManager().logout();​
 +</​code>​
 +
 +==== 进阶 ====
 +
 +SDK会将译文信息保存到本地数据库,当保存的译文太多时,会数据库文件增大,打开数据库变慢,因此需要定期进行清理。
 +
 +SDK提供了以下三种清理方式
 +  * 按会话清理译文
 +按会话清理译文方式如下:
 +<​code>​
 +EMClient.getInstance().translationManager().removeResultsByConversationId("​conversationId"​);​
 +</​code>​
 +
 +  * 按消息Id清理译文
 +按消息清理译文方式如下:
 +<​code>​
 +EMClient.getInstance().translationManager().removeTranslationResult("​msgId"​);​
 +</​code>​
 +
 +  * 清除所有译文
 +清理所有译文方式如下:
 +<​code>​
 +EMClient.getInstance().translationManager().clearTranslations();​
 +</​code>​
  
 ===== Demo 及 SDK 下载 ===== ===== Demo 及 SDK 下载 =====