近期,由于公司新开项目,涉及即时通讯,几经对比,选择了环信平台。话不多说,进入正题。
大纲:
1.环信SDK集成,http://docs.easemob.com/im/200androidclientintegration/10androidsdkimport,打开链接,完成最基础的sdk集成,并且初始化SDK,这一步我就略过了。
2.聊天准备,注册,登录,退出登录,设置环信服务连接监听,设置消息接收监听
3.添加好友
4.好友消息列表处理(根据最后聊天发送时间排序)
5.聊天界面消息发送,接收处理
以下是项目中使用环信sdk完成的功能清单:
聊天界面(1对1好友聊天):
发送消息类别:文字,语音,图片,位置。
好友列表:聊天好友会话列表。
2.聊天准备,注册,登录,退出登录,设置环信服务连接监听,设置消息接收监听
2.1-注册
注册环信聊天账号,密码,用于app客户端基于环信服务器聊天。这一块,本项目是由后台接口注册,登录后返回,也就是说环信聊天账号的注册交由后台创建,客户端只需在登录成功后返回接收即可。当然可以根据自身需求,也可自己创建。
环信sdk文档是这样描述的:
注册模式分两种,开放注册和授权注册。只有开放注册时,才可以客户端注册。
开放注册是为了测试使用,正式环境中不推荐使用该方式注册环信账号;
授权注册的流程应该是您服务器通过环信提供的 RESTAPI注册,之后保存到您的服务器或返回给客户端。
注册用户名会自动转为小写字母,所以建议用户名均以小写注册。(强烈建议开发者通过后台调用 REST 接口去注册环信 ID,客户端注册方法不提倡使用。)
//注册失败会抛出HyphenateException
EMClient.getInstance().createAccount(username, pwd);//同步方法 (不推荐客户端注册)
2.2-登录
app登录成功之后,获取后台创建好的username,password。值得注意的是,回调的三个方法都是位于子线程,不能够在方法体内做ui操作。
调用环信api,EMClient.getInstance().login(userName,password,new EMCallBack());进行环信账号登录。
EMClient.getInstance().groupManager().loadAllGroups();
EMClient.getInstance().chatManager().loadAllConversations();
以上两个方法是为了保证进入主页面后本地会话和群组都 load 完毕,根据自身业务调用,除登录api成功回调使用,建议每次启动app都在启动页调用一次。
退出登录,直接调用 EMClient.getInstance().logout(true)即可;
环信登录成功后,默认为自动登录,可按需求取消自动登录options.setAutoLogin(false)。
EMClient.getInstance().isLoggedInBefore(),判断环信账号登录状态
2.3-(成功登录环信后)设置环信服务连接监听
注册连接监听,可用作监听设备登录唯一,发生多点登录,作出提示。只需在注册一次即可,建议在应用首页注册,这样首页不销毁就可以做到全局监听的效果,进入app注册监听。
退出app时,调用EMClient.getInstance().removeConnectionListener(MyConnectionListener);销毁监听。MyConnectionListener类实现了EMConnectionListener接口
2.3-(成功登录环信后)设置环信消息接收监听
EMClient.getInstance().chatManager().addMessageListener(msgListener);只需在注册一次即可,建议在应用首页注册,这样首页不销毁就可以做到全局监听的效果,进入app注册监听,退出app调用EMClient.getInstance().chatManager().removeMessageListener(msgListener);
值得注意的是,EMMessageListener的众多回调方法中, onMessageReceived(List messages)是最重要的方法,所有消息接收都在此方法中,但是看方法的参数,竟然是list集合,这里面我们只需要获取list里面的第一个数据即可,List
首先是注册监听,我是在MainActivity首页设置的,UserBiz.isLogin() && EMClient.getInstance().isLoggedInBefore()双重判断用户是否已登录,环信账号登录。EMReceiveBiz是我自己写一个处理消息接收的业务类,全局只在MainActivity注册一次监听,避免收到多次消息。
关于MyConnectionListener,上面已经有介绍。与消息监听同理。
然后是销毁监听,当退出app时,把注册的2个监听销毁
EMClient.getInstance().removeConnectionListener(eMConnectionListener);
EMClient.getInstance().chatManager().removeMessageListener(emReceiveBiz.msgListener);
EMReceiveBiz里面用到了handler,所以为了防止内存泄露,把handler监听销毁。
3.添加好友
EMClient.getInstance().contactManager().setContactListener(newEMContactListener()); 注册好友监听
//参数为要添加的好友的username和添加理由
EMClient.getInstance().contactManager().addContact(toAddUsername, reason);
一般添加好友除了环信平台添加好友,本地接口也需要添加到好友列表,所以reason根据需求设置参数,比如本地接口添加好友需要用户userId,那么可以将reason设置为自己的userId,发送成功后,对方将在onContactInvited方法中获取到你的环信账号,与你的userId,这样再处理接收好友请求,调用本地接口添加好友。
4.好友消息列表处理(根据最后聊天发送时间排序)
我们看到QQ,微信也好,消息列表的排序,都是按发送时间为基准,发送时间距离当前时间越近排序越靠前。
这里面环信并没有直接提供这样的api。所以需要我们自己基于环信api做排序处理。
我把自己处理的代码发出来,List
EMClientMsgBiz clientBiz1 =newEMClientMsgBiz();
clientBiz1.setImAccount(o1.getFriendImAccount());
List lastMsgInfo1 = clientBiz1.getMessage(1);
o1.getFriendImAccount()是该好友的环信账号,然后 调取环信api,getMessage(pagerNum),pagerNum代表获取多少条数据,这里我们只需要获取最新的消息记录,所以设置为1即可获得与该好友的最后一条聊天EMMessage,如果没有一个消息记录,则conversation==null,所以new 一个集合返回,否则有空指针异常。
EMMessage 环信聊天消息实体类,我们调用EMMessage.getMsgTime(,获取消息发送时间,然后把整个列表的会话排序即可。下面的方法便是比对消息发送时间的进行排序。Collections.sort(List list,Comparator c);是java.util中Collections类中的方法,不了解的可以去查看一下。这样好友消息会话列表的排序就处理好了
接下来处理会话列表的显示问题。我这里的处理方式是在adapter里面处理的。
处理方式大同小异,通过UserFriend里面的friendImAccount,调取环信api,获取未读消息数量getUnreadMsgCount,获取最后消息发送时间getMsgTime(消息类型为long,时间戳为毫秒数,如何显示按需求处理),获取最后消息发送内容 EaseCommonUtils.getMessageDigest(lastMsgInfo1.get(0))。
EaseCommonUtils环信easeui demo里面的工具类,专门处理环信消息类型简写。
5.聊天界面消息发送,接收处理。
到了这一步,聊天准备工作都做好了,接下来可以选择聊天对象,发送聊天消息和接收聊天消息。
上一步说到UserFriend,这个好友实体,是本地接口返回的数据,这是我自己项目中定义的变量,下面三个是自己定义的,接口不返回这些数据,而是由环信api获取到的,用于好友消息列表展示
有了UserFriend这个实体,我们带入聊天界面,就可以通过好友的环信账号,调用历史消息记录,未读消息数量清零,发送聊天消息环信api等等。接下来会讲到。
EMClientChatBiz 是专门处理聊天界面调用环信api的业务类,进入聊天界面显进行初始化,并且设置消息发送监听。OnSendMsgListener是自定义的回调接口。
emClientBiz.setChatUsernameId(userFriendInfo); 把好友的环信账号传入EMClientChatBiz,这样可以调用相关api方法。
5.1-EMClientChatBiz,聊天业务处理类,会一一详细介绍
现在,发送各类消息,MessageInfo实体是本地定义的,根据发送内容设置,并且转换成相应类型的EMMessage实体。
各类消息的创建,其中发送地理位置,携带了定位截图,是以EMMessage.createImageSendMessage()方法创建的,因为环信api中创建位置消息,并不能携带图片,因此才通过创建图片消息,附带自定义属性将经纬度等信息发送。这个有点投巧,暂时没想出好的办法。
首先设置消息发送监听,message.setMessageStatusCallback(newEMCallBack(){}); 每条消息的发送都需要设置消息监听,以便正确显示发送状态,显示相应的ui。
消息发送,并设立监听,设置消息为发送中
根据发送监听回调修改消息状态
EMCallBack,其回调方法都是子线程,所以采用handler,更新ui
通过自定义监听,返回消息状态,更新ui
发送消息处理完,接下来就是聊天界面接收消息处理了。接收消息上面有说道,在首页设置了消息接收的全局监听,现在我们就利用消息监听,来处理聊天界面的消息接收。还是拿之前的图来讲。ActivityTask,FragmentTask是管理类,存放堆栈的实例,不理解的可以查看这篇博客
http://blog.csdn.net/u010635353/article/details/49681659
,sendDataToActivity类似于EventBus或者广播通知,携带参数。
这里主要将收到的消息传递到三个地方,如果当前界面是在聊天界面,那么将EMMessage传递到聊天界面。这里只介绍聊天界面的消息接收。
收到消息后,取出EMMessage,然后emMessage.getFrom(),获取发送人的环信账号,与当前聊天对象的环信账号比对,一致则加入消息列表,这样处理主要防止好友消息乱入,比如你与A聊天,好友B发你的消息你也可以接收到,如果正在聊天界面,不做处理,这条消息就会插入到聊天界面的消息列表中。
msgId也是同样道理,如果出现同一时间收到多条重复消息,那么他的msgId必定是一致的,所以也做了过滤处理。
6.消息展示处理
文字消息获取
图片消息获取
位置消息获取,由于位置消息是通过图片类型发送的,因此接收还是图片类型,但是先判断自定义的属性是否为null,null会产生异常,所以这个图片消息不是位置消息。
语音消息
最后,还有几条实用的api,可以使用。
EMClientChatBiz:聊天界面使用,发送消息
EMClientFriendBiz:添加好友,好友相关api
EMClientLoginBiz:登录,退出环信账号
EMClientMsgBiz:环信消息相关api,未读,获取消息数,主要用于好友会话列表
EMClientReceiveBiz:聊天消息接收,消息分发
这样结合自身需求,一个基础聊天功能就出来了。还没有使用过环信并且有这方面需求的的朋友可以自己动手试试,有什么不明白的地方可以留言。