LZ-Says:相遇,相知,相恋,争执,平淡,压抑,愤懑,该画上句号了。

前言

环信,Enmmm,牛逼,懵 ing ~!

最近这段时间一直围绕环信,在使用的过程中,遇到很多很多问题,自己都感觉蒙圈,烦躁。

还好,明远小哥哥很 nice,点拨给力,到位,赞一个~!

明天要开启新的征程了,希望一切顺利,加油哦~!

今天简单整理下,LZ 所经历到的环信之 “坑” ~~~

Enmmm,环信,你好

首先,列举本文将要描述的内容简述:

  • 查询本地消息历史记录

  • 清空聊天记录保留会话

  • 显示 “输入中。。。”

接着,我们进行逐步说明。

一、查询本地消息历史记录

搜索 API 文档,得出环信官方提供了如下不同类型接口:

经过文哥指点,最终确定使用如下类型接口:

原想着很美好,很 easy,分分钟,嗯,开始的代码如下:

List<EMMessage> resultList = mConversation.searchMsgFromDB(mSearchView.getText().toString(),System.currentTimeMillis(),50,null,EMConversation.EMSearchDirection.UP);
。。。
Adapter 更新即可

But,美滋滋的测试的时候,突然发现一个问题,只能搜索 汉字,输入 单个数字 或者 单个字母,则检索出所有数据。 百思不得其解,内心无数的 MMP,无奈下只能提交工单,嗯,工单好。

为环信敬业赞一个,But,回复的是,我们这边没事。

想问问有什么原因导致,嗯,你自己检查下。

咋检查啊,之前好好地,我就是在这个基础加了一个查询本地消息,怎么破?

文档也看了,度娘也扒光了,无招。项目又比较急,怎么办?

找出共性,逐步解决~!

List<EMMessage> resultList = mConversation.searchMsgFromDB(mSearchView.getText().toString(),System.currentTimeMillis(),50,null,EMConversation.EMSearchDirection.UP);
// 1. 创建临时存储 List
List<EMMessage> tempList = new ArrayList<>();
mMessageIDList = new ArrayList<>();
// 2. 循环遍历 进行手动过滤
for (int i = 0; i < resultList.size(); i++) {if (resultList.get(i).getBody() instanceof EMTextMessageBody) {if (((EMTextMessageBody) resultList.get(i).getBody()).getMessage().contains(mSearchView.getText().toString())) {tempList.add(resultList.get(i));}}
}
// 3. 将最后过滤后的 List 赋值到 RecyclerView 中的 List 并进行 notify 即可
if (mMessageList == null) {mMessageList = tempList;
} else {mMessageList.clear();mMessageList.addAll(tempList);
}

LZ 实属无奈,如有其他小伙伴也曾经遇到过,并完美解决,还望告知~

二、清空聊天记录保留会话

这个,真的比较坑了。

需求就是和小题目一样,聊天记录清空且会话不能删除。

好,那我们开始逐步解决这个问题,官网显示,清除聊天记录需要调用如下 API:

// 删除和某个user会话,如果需要保留聊天记录,传false
EMClient.getInstance().chatManager().deleteConversation(username, true);
// 删除当前会话的某条聊天记录
EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
conversation.removeMessage(deleteMsg.msgId);

二话不说,拷贝进来再说。测试后,发现会话也被移除了,咋整,度娘呗。

经过了度娘以及工单后,发现了如下方法:

/*** clear the conversation history*/
protected void emptyHistory() {String msg = getResources().getString(R.string.Whether_to_empty_all_chats);new EaseAlertDialog(getActivity(), null, msg, null, new EaseAlertDialog.AlertDialogUser() {@Overridepublic void onResult(boolean confirmed, Bundle bundle) {if (confirmed) {if (conversation != null) {conversation.clearAllMessages();}messageList.refresh();haveMoreData = true;}}}, true).show();
}

看似很美好,But,EaseUI 中对此进行了拦截,不信?截图为证:

Enmmm,嗨皮不?人给你拦截了,哇咔咔。

有的小伙伴说,你把这个干掉不就好了嘛?

嘿嘿嘿,彩蛋还是要自己去发掘的。

这里还是感谢明远老哥指点,模仿类似群加人,群删人发送时,本地插入消息。

So,开始模仿之路,说白了,我们要为我们的 EaseChatRow 新添加另外一种类型。

Step 1:为 EaseChatRow 新增一种类型

public static final String MESSAGE_PLACEHOLDER = "placeholder";

Step 2:创建 EaseChatRow 布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content" />

Step 3:创建 EaseChatRow 实例类

public class EaseChatRowPlaceHolder extends EaseChatRow {public EaseChatRowPlaceHolder(Context context, EMMessage message, int position, BaseAdapter adapter) {super(context, message, position, adapter);}@Overrideprotected void onInflateView() {inflater.inflate(R.layout.ease_row_place_holder, this);}@Overrideprotected void onFindViewById() {}@Overrideprotected void onViewUpdate(EMMessage msg) {}@Overrideprotected void onSetUpView() {}}

Step 4:来,搞个 P

public class EaseChatPlaceHolderPresenter extends EaseChatRowPresenter {@Overrideprotected EaseChatRow onCreateChatRow(Context cxt, EMMessage message, int position, BaseAdapter adapter) {return new EaseChatRowPlaceHolder(cxt, message, position, adapter);}@Overridepublic void onBubbleClick(EMMessage message) {super.onBubbleClick(message);}@Overrideprotected void handleReceiveMessage(EMMessage message) {if (!message.isAcked() && message.getChatType() == EMMessage.ChatType.Chat) {try {EMClient.getInstance().chatManager().ackMessageRead(message.getFrom(), message.getMsgId());} catch (HyphenateException e) {e.printStackTrace();}return;}EaseDingMessageHelper.get().sendAckMessage(message);}
}

完成了以上几步,接下来,则是要为 EaseChatRow 指明我们定义的消息体类型即可。

Step 5:Adapter 针对特定的类型返回特定的 EaseChatRow

EaseMessageAdapter --> getItemViewType:

// 清除聊天消息 发送空字符
if (message.getBooleanAttribute(EaseConstant.MESSAGE_PLACEHOLDER, false)) {return message.direct() == EMMessage.Direct.RECEIVE ? MessageAdapterConstant.MESSAGE_TYPE_SENT_PLACE_HOLDER : MessageAdapterConstant.MESSAGE_TYPE_SENT_PLACE_HOLDER;
}

EaseMessageAdapter --> createChatRowPresenter:

else if (message.getBooleanAttribute(EaseConstant.MESSAGE_PLACEHOLDER, false)) {presenter = new EaseChatPlaceHolderPresenter();
}

Step 6:最后,发送一条我们指定类型的消息

EMClient.getInstance().chatManager().deleteConversation(group.getId(), true);
EMClient.getInstance().chatManager().getConversation(group.getId(), EMConversation.EMConversationType.GroupChat, true);
// 记得,这边要创建一条发送消息,不然列表会出现小彩蛋 感谢我老哥
EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);
message.setChatType(EMMessage.ChatType.GroupChat);
EMTextMessageBody body = new EMTextMessageBody("");
message.setTo(group.getId());
message.addBody(body);
// 设置当前消息类型
message.setAttribute(MESSAGE_PLACEHOLDER, true);
message.setAttribute("hxId", SPUtils.get(AppConstant.HXID, "").toString());
message.setAttribute("avatar", SPUtils.get(AppConstant.AVATAR, "").toString());
message.setAttribute("groupId", group.getId() != null ? group.getId() : "");
message.setAttribute("cover", group.getCover() != null ? group.getCover() : "");
message.setUnread(false);
EMConversation conversation = EMClient.getInstance().chatManager().getConversation(group.getId());
conversation.appendMessage(message);

三、显示 “输入中。。。”

首先,我们先了解下有关输入状态官网简述:

监听用户 A 输入状态,一旦有文字输入,就每隔几秒通过透传消息将输入状态发送到聊天接受方 B,B 客户端收到输入状态透传后,提示用户 A 正在输入。

  • 用户 A 向用户B 发一条表示输入状态透传消息;
  • 用户 B 在收到消息后,判断当前是否在与 A 聊天的页面,如果在,显示 A 的输入状态;
  • 当隔几秒后没有再次收到 A 的输入状态,自动取消显示。

注:“透传消息”是一种特殊类型的消息,收发双方不会存数据库,同时用户离线时也不会有推送,比较适合配合业务来处理一些功能。 并且 A 用户不需要不停的向 B 发送消息,可以设置一个时间,判断发送间隔。

So,我们这个代码很 Easy。

Step 1:编写我们发送透传消息体

/*** 自定义时间间隔发送状态消息(单位:ms)*/
public int time = 2000;/*** 文本框第一次输入内容变化的时间*/
public long firstTime = System.currentTimeMillis();/*** 发送输入状态的透传消息*/
private void sendInputMsg(String inputState) {// 这里需要判断if (chatType == EaseConstant.CHATTYPE_SINGLE) {EMMessage cmdMsg = EMMessage.createSendMessage(EMMessage.Type.CMD);// 如果是群聊,需要设置 chattype,默认是单聊String action;if ("input".equals(inputState)) {action = "input";} else {action = "stopInput";}EMCmdMessageBody cmdBody = new EMCmdMessageBody(action);// 设置消息bodycmdMsg.addBody(cmdBody);// 设置要发给谁,用户username 或者群聊groupidcmdMsg.setTo(toChatUsername);EMClient.getInstance().chatManager().sendMessage(cmdMsg);}
}

Step 2:EaseChatMenu 添加监听

这里需要注意,什么时候发送 input,什么时候发送 inputStop。

if (TextUtils.isEmpty(s)) {// 发送 inputStop 状态listener.onInputStatusListener("inputStop");
} else {// 发送 input 状态listener.onInputStatusListener("input");
}

Step 3:实现监听

 @Overridepublic void onInputStatusListener(String inputStatus) {if ("input".equals(inputStatus)) {if (System.currentTimeMillis() - firstTime > time) {sendInputMsg("input");firstTime = System.currentTimeMillis();}} else {sendInputMsg("inputStop");}}

结束

目前而言,LZ 经历的以上问题总结完成,如有遗漏,请指明,谢谢~

剩下的以后遇到再补充吧~

个人公众号

不定期发布博文,最近有点忙,感谢老铁理解,欢迎关注~

参考资料

  1. Android SDK API Doc:http://docs-im.easemob.com/im/android/sdk/apidoc;
  2. 删除会话及聊天记录:http://docs-im.easemob.com/im/android/basics/message#删除会话及聊天记录;
  3. 输入状态提示:http://docs-im.easemob.com/im/other/integrationcases/inputstatus#输入状态提示;

工作篇 之 简单聊下有关环信的 “坑” ...相关推荐

  1. Esp8266 进阶之路25【高级篇】深聊下esp8266的串口 Uart 通讯中断编程,为您准备好了 NONOS 版本 和 RTOS 系统的串口驱动文件。(附带Demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板.仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 序号 SDK版本 内容 链接 1 nonos2.0 搭建 ...

  2. android 环信集成,Android Studio下的环信即时通讯简单集成

    环信即时通讯云是全球最大的即时通讯云 PaaS 平台,可以快速实现APP的即时通讯的功能,官方的DEMO是基于Eclipse开发的,对于新版本的Android Studio支持不太好,下面就简单说一下 ...

  3. Android环信爬坑指北(二)头像昵称好友备注显示

      在上一篇文章中提到了要在初始化的时候,设置用户信息提供者类--EaseUserProfileProvider,用以获取用户信息.下面我们来看一下 EaseUserProfileProvider 是 ...

  4. 简单聊下STM32F103的GPIO

    GPIO是芯片和外界沟通的桥梁,GPIO有很多模式,不同的模式有不同的配置,应用于不同的场合. STM32F103系列的I/O引脚共有8种工作模式, 输入模式有四种 浮空输入 上拉输入 下拉输入 模拟 ...

  5. 简单聊下中台概念与发展

    什么是中台 中台可以视作是支持多个前台业务中具有公共业务属性的能力组织. 所以他有组织+系统两个层面的事情.需要有个自运营的组织,对外提供的是抽象的服务. 钟华老师说:中台是将企业核心能力以服务化形式 ...

  6. 简单聊下STM32F103的时钟

    对于芯片而言,电源和时钟是缺一不可的. 电源为芯片提供能量,时钟则提供时间基准,芯片好按照这个tick依次执行指令. STM32F103是一款性价比很好的芯片,它的时钟树长这样: 它有4个时钟源,不同 ...

  7. 简单聊下STM32F103的串口

    串口是单片机嵌入式必不可少的外设,它上手简单,使用方便,很受小伙伴的欢迎. 用STM32CubeMX体验下STM32F103的串口,硬件平台采用百问网STM32F103mini开发板. 生成的一些代码 ...

  8. 简单聊下5G与V2X

    V2X是将车辆与一切事物相连接的新一代信息通信技术,其中V代表车辆,X代表任何与车交互信息的对象,包括车.人.交通路侧基础设施和网络.V2X是通过专用通信协议和频谱实现一定区域内.一定条件下的数据互通 ...

  9. 简单聊下STM32F103的中断

    中断 当cpu在执行指令时,遇到一些突发状况,不得不先处理这些突发状况,处理完毕后再返回原来执行指令处继续执行,这里的突然状况被称为中断或异常. 中断示意图如下: STM32F103的中断系统很强大, ...

最新文章

  1. C#中静态方法的运用和字符串的常用方法(seventh day)
  2. 在Win7下利用VirtualBox和Vagrant安装Docker
  3. tensorflow随笔-文件数据读取
  4. [蓝桥杯][基础练习VIP]芯片测试-思维
  5. IDEA上Debug调试全流程
  6. 雷军被重新任命为金山软件董事会副主席
  7. 第41章 实施数据库审计
  8. HDU 5912 Fraction (2016-ccpc-长春)
  9. spring催办业务_业务后台系统之流程设计
  10. node.js学习之npm 入门 —8.《怎样创建,发布,升级你的npm,node模块》
  11. Java语言程序设计基础篇第10版第5章习题答案
  12. 毕设-周报-20150520
  13. Spring常用注解
  14. Python打包exe文件并换图标【最强版教程】
  15. 操作系统 - 沙箱(sandboxing)技术
  16. 详解统计套利交易系统模型
  17. 2022年2月语音合成(TTS)和语音识别(ASR)论文月报
  18. 我们采访了三位学生:他们写代码、95 后、来自大陆和台湾
  19. 黑帽SEO关键字堆砌的原理以及作用
  20. 数据科学家:为什么我要离职……

热门文章

  1. 顺序表ADT模板设计及简单应用:将顺序表中前 m 个元素和后 n 个元素进行互换
  2. 单招计算机Windows7知识点,计算机单招考试试题
  3. exit和_exit,fock和vfock
  4. c51中sbit/sfr 用法
  5. ElasticSearch—冷热(hotwarm)架构部署
  6. Docker Swarm集群与Kubernetes的搭建与试用
  7. 利用JS实现短信验证码倒计时案例
  8. BP 神经网络的数据分类
  9. 【Matlab】如何使用Simulink进行电池建模和SOC预估
  10. 刚刚,2022中科院分区表发布(附下载)