Android-IM即时通讯关于消息撤回的处理
来源:互联网 发布:哈萨克歌曲下载软件 编辑:程序博客网 时间:2024/04/30 11:20
项目源码请参考 Android-IM
项目服务端使用极光JMessage
对话撤回的效果图:
这里只是在对话的界面展示了撤回消息的处理。
其实还有一个地方,是会话列表,也需要动态展示撤回消息的通知。
先说对话列表要进行的操作
- 发送方:点击撤回事件,本地视图移除,通知服务端更新
- 接收方:动态获取消息,当获取到撤回消息事件,移除视图。
然后是会话列表也要同步展示
- 会话列表只有一个接收方,需要在接收到撤回消息的事件更新视图
具体实现
发送方撤回
只能是发送方才可以撤回
1、首先获取当前聊天的会话
position这里是从上个页面传递的数据,上个页面是指会话列表的索引。Conversation就是当前的会话。
JMessageClient.getConversationList()是获取所有的会话列表。
Conversation conversation=JMessageClient.getConversationList().get(position);
2、创建撤回事件
这个事件就是通知服务端的撤回消息。
两个参数分别是(需要撤回的消息,服务端返回的结果)。其中Message在长按消息的时候就给返回了,只需获取消息就可以了。 conversation.retractMessage(message.getMessage(), new BasicCallback())
3、接收到撤回成功的事件
当服务器返回撤回成功的事件(i==0)后,通过
//移除当前itemmAdapter.deleteById(message.getMsgId());//添加一条撤回的itemmAdapter.addToStart(new MyMessage("[你撤回了一条消息]", SEND_TEXT),true);//更新视图mAdapter.notifyDataSetChanged();
new MyMessage第二个参数是消息类型
完整代码:
//conversation.retractMessage(message.getMessage(), new BasicCallback() { @Override public void gotResult(int i, String s) { if (i==0){ showToast(ChatMsgActivity.this,"撤回了一条消息"); mAdapter.deleteById(message.getMsgId()); mAdapter.addToStart(new MyMessage("[你撤回了一条消息]", SEND_TEXT),true); mAdapter.notifyDataSetChanged(); }else { showToast(ChatMsgActivity.this,"撤回失败:"+s); } }});
获取对方的撤回事件
撤回的目的就是为了让对方看不到,而我们作为发送方,当收到对方的消息之后,默认是直接在对话窗口展示的。但是这时候对方突然撤回了消息,我们也需要在对话窗口移除掉消息。
1、注册消息接收者
所有的通知,消息都需要注册。包括消息事件、撤回事件、好友请求事件等等。
注册的方法是在onCreate中,一般在android开发中会定义一个BaseActivity的基类
或者单独的Activity中也一样,添加: JMessageClient.registerEventReceiver(this);
这里有个需要注意的是收到消息的时候,通知栏也会显示消息,所以如果是在对话界面,需要关闭通知栏的通知:
userName就是当前对话的对方的用户名,一般在上个页面通过数据传递的方式获取 JMessageClient.enterSingleConversation(userName);
2、接收撤回消息
onEvent是为了方便JMessage识别的方法,是固定的,里面的参数如果是接收撤回的消息就是MessageRetractEvent,如果是正常的会话消息就是MessageEvent,当然还有好友请求的消息ContactNotifyEvent等等。具体可以去查看api文档。
由于这个是独立的类,在移除视图的时候需要我们传一个消息id。
这个id的获取也需要在两个地方获取:
a) 在加载消息列表的时候,我们要把筛选出来正常的消息(非撤回)设置id。
b) 在接收到新消息时,也需要我们获取id。
需要注意的是被撤回的消息是没有ID的,不能再次被撤回 msgID = myMessage.getMsgId();
移除完视图之后,可以选择再添加一个新的撤回消息的视图
mAdapter.addToStart(new MyMessage("[对方撤回了一条消息]", IMessage.MessageType.RECEIVE_TEXT),true);
这里new MyMessage的第二个参数就需要改变为对方的类型了。
在加载消息列表的时候也是通过该方法来判断消息展示的左右位置。
但是会有一个问题,因为移除视图是通过获取消息存在本地的id。
当连续从服务器获取几条消息的时候,如果要撤回其中的一条。还需要对所有的消息遍历,并且判断服务端返回的消息id(messageId)和本地消息id(msgID)是否一致,当一致的时候撤回,并移除本地视图。
//日志message: Message{_id=7, messageId=413528998, createTimeInMillis=1504165079011, direct=receive, status=receive_success, content={"promptText":"1006自动回复机器人撤回了一条消息","extras":{}}, version=1, fromName='1006自动回复机器人', contentType=prompt, contentTypesString='prompt', targetType=single, targetID='null', targetName='null', fromType='user', atList=null, fromID=1006, notification=null, isSetFromName=0, suiMTime=0}Mymessage: MyMessage{id=-7007385618142453134, text='2', timeString='08-31 15:37', type=RECEIVE_TEXT, user=com.wapchief.jpushim.entity.DefaultUser@cc2c2e9, mediaFilePath='null', duration=0, progress='null', position=0, msgID=413528998}
这里的list是我们一开始进入页面获取的消息列表。同时要在获取新消息的事件中动态添加到集合中。否则当对方发起撤回的时候,本地无法更新视图。
完整代码:
/*接收到撤回的消息*/ public void onEvent(MessageRetractEvent event){ final Message message = event.getRetractedMessage(); runOnUiThread(new Runnable() { @Override public void run() { for (int i=0;i<=list.size();i++){ if (list.get(i).getMsgID()==message.getServerMessageId()){ mAdapter.delete(list.get(i)); MyMessage message1=new MyMessage("[对方撤回了一条消息]", IMessage.MessageType.RECEIVE_TEXT); mAdapter.addToStart(message1,true); mAdapter.notifyDataSetChanged(); mAdapter.updateMessage(message1); } } } }); }
3、注销消息接收者、退出会话
在onDestroy中
@Override protected void onDestroy() { //接收事件解绑 JMessageClient.unRegisterEventReceiver(this); //退出会话 JMessageClient.exitConversation(); super.onDestroy(); }
上面就完成了对话消息列表的撤回处理。
接下来还有个地方需要处理。
会话列表接收撤回
效果图:
上面提到过JMessageClient.getConversationList()是获取会话列表的方法,也就是当前页面展示的内容。
该方法是封装后存在于本地的,所以不需要做进一步的处理。
只是加载后做进一步的解析-展示处理就行了。
1、解析会话列表
解析相对于来说比较简单,解析需要的实体类可以自己创建。将需要用到的参数解析出来就可以了。
在接收到撤回消息的时候或者其他消息,需要我们刷新数据。
这里需要注意的是在解析消息的时候,要对其做判断,由于目前只设置了文字消息和撤回消息两种,所以暂时只对这两种消息做了额外的处理。
后期还需要对图片消息,语音消息等做进一步的判断。
getLatestMessage()
是获取最后一条消息的意思。
if (list.get(i).getLatestMessage().getContent().getContentType()== ContentType.prompt) { bean.setContent(((PromptContent) (list.get(i).getLatestMessage()).getContent()).getPromptText()); }else { bean.setContent(((TextContent) (list.get(i).getLatestMessage()).getContent()).getText()); }
部分代码:
for (int i = 0; i < list.size(); i++) { bean = new MessageBean(); try { //这里进行撤回消息的判断// Log.e("type", list.get(i).getTitle()+","+list.get(i).getLatestMessage().getContent().getContentType()); if (list.get(i).getLatestMessage().getContent().getContentType()== ContentType.prompt) { bean.setContent(((PromptContent) (list.get(i).getLatestMessage()).getContent()).getPromptText()); }else { bean.setContent(((TextContent) (list.get(i).getLatestMessage()).getContent()).getText()); } } catch (Exception e) { bean.setContent("最近没有消息!"); Log.e("Exception:MessageFM", e.getMessage()); } bean.setMsgID(list.get(i).getId()); bean.setUserName(((UserInfo) list.get(i).getTargetInfo()).getUserName()); bean.setTitle(list.get(i).getTitle()); bean.setTime(list.get(i).getUnReadMsgCnt() + ""); bean.setConversation(list.get(i));// Log.e("Log:Conversation", list.get(i).getAllMessage()+""); try { bean.setImg(list.get(i).getAvatarFile().toURI() + ""); } catch (Exception e) { } data.add(bean); } } mFragmentMainRf.setRefreshing(false); adapter.notifyDataSetChanged();
2、接收撤回消息
和前面接收消息的方法一样
/*接收撤回消息*/ public void onEvent(MessageRetractEvent event) { handler.postDelayed(new Runnable() { @Override public void run() { //重新加载数据 updataData(); } },500); }
总结
在做消息功能的时候,大多数都是参照文档来开发,所以做的时候,需要对相关的类有一定的了解。知道其用法。
而且会话也是一个即时通讯的最基础的功能。涉及的范围也比较广,目前项目只实现了文字的会话,更高级的对话方式还需要进一步的开发。
项目地址:https://github.com/wapchief/Android-IM
相关阅读推荐:
- Android-IM从零开始开发一个即时通讯项目
- Android-IM给即时通讯添加一个自动聊天机器人
- Android-IM使用极光即时通讯发送、接收好友请求
- Android-IM即时通讯关于消息撤回的处理
- 关于常用IM 即时通讯软件的安全问题
- Android 环信IM即时通讯 自定义扩展消息 注意点
- Android IM即时通讯初期调研
- Android-IM即时通讯:环信
- IM 即时通讯单例发送消息
- Android中开发IM即时通讯功能的方案
- 即时通讯IM的安全性比较
- 即时通讯(IM)软件的开发
- IM即时通讯实现的原理
- 关于IM(即时通讯开发)技术问题
- layim的websocket消息撤回功能实现
- IM(即时通讯)
- IM即时通讯
- IM/即时通讯
- 即时通讯IM
- 即时通讯(IM)
- 即时通讯-im
- [leetcode] 668 Kth Smallest Number in Multiplication Table
- 分布式之分布式事务的消息队列模式实现
- postgresql双机热备(流复制)及主备切换
- EasyUI的datagrid获取所有正在编辑状态的行的行编号
- 函数的bind方法
- Android-IM即时通讯关于消息撤回的处理
- [笔记分享] [Display] MIPI 协议之Overview
- JS限制小数点前几位后几位
- pymongo操作 和 mongodb 集群认证操作
- Kotlin初体验
- Java常见面试题—Callable与Runnable接口
- Halcon 与 c# 混合编程读取并显示一张图片
- 九度[1007]-奥运排序问题
- Win10下在VirtualBox中安装WinXP