前言
环信,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() {
@Override
public 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);
}
@Override
protected void onInflateView() {
inflater.inflate(R.layout.ease_row_place_holder, this);
}
@Override
protected void onFindViewById() {
}
@Override
protected void onViewUpdate(EMMessage msg) {
}
@Override
protected void onSetUpView() {
}
}
Step 4:来,搞个 P
public class EaseChatPlaceHolderPresenter extends EaseChatRowPresenter {
@Override
protected EaseChatRow onCreateChatRow(Context cxt, EMMessage message, int position, BaseAdapter adapter) {
return new EaseChatRowPlaceHolder(cxt, message, position, adapter);
}
@Override
public void onBubbleClick(EMMessage message) {
super.onBubbleClick(message);
}
@Override
protected 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 发送消息,可以设置一个时间,判断发送间隔。
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);
// 设置消息body
cmdMsg.addBody(cmdBody);
// 设置要发给谁,用户username 或者群聊groupid
cmdMsg.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:实现监听
@Override
public void onInputStatusListener(String inputStatus) {
if ("input".equals(inputStatus)) {
if (System.currentTimeMillis() - firstTime > time) {
sendInputMsg("input");
firstTime = System.currentTimeMillis();
}
} else {
sendInputMsg("inputStop");
}
}
结束
目前而言,LZ 经历的以上问题总结完成,如有遗漏,请指明,谢谢~
剩下的以后遇到再补充吧~