近期,由于公司新開項目添怔,涉及即時通訊湾戳,幾經(jīng)對比,選擇了環(huán)信平臺广料。話不多說砾脑,進入正題。
大綱:
1.環(huán)信SDK集成艾杏,http://docs.easemob.com/im/200androidclientintegration/10androidsdkimport韧衣,打開鏈接,完成最基礎(chǔ)的sdk集成购桑,并且初始化SDK汹族,這一步我就略過了。
2.聊天準(zhǔn)備其兴,注冊顶瞒,登錄,退出登錄元旬,設(shè)置環(huán)信服務(wù)連接監(jiān)聽榴徐,設(shè)置消息接收監(jiān)聽
3.添加好友
4.好友消息列表處理(根據(jù)最后聊天發(fā)送時間排序)
5.聊天界面消息發(fā)送守问,接收處理
以下是項目中使用環(huán)信sdk完成的功能清單:
聊天界面(1對1好友聊天):
發(fā)送消息類別:文字,語音坑资,圖片耗帕,位置。
好友列表:聊天好友會話列表袱贮。
2.聊天準(zhǔn)備仿便,注冊,登錄攒巍,退出登錄嗽仪,設(shè)置環(huán)信服務(wù)連接監(jiān)聽,設(shè)置消息接收監(jiān)聽
2.1-注冊
注冊環(huán)信聊天賬號柒莉,密碼闻坚,用于app客戶端基于環(huán)信服務(wù)器聊天。這一塊兢孝,本項目是由后臺接口注冊窿凤,登錄后返回,也就是說環(huán)信聊天賬號的注冊交由后臺創(chuàng)建跨蟹,客戶端只需在登錄成功后返回接收即可雳殊。當(dāng)然可以根據(jù)自身需求,也可自己創(chuàng)建窗轩。
環(huán)信sdk文檔是這樣描述的:
注冊模式分兩種相种,開放注冊和授權(quán)注冊。只有開放注冊時品姓,才可以客戶端注冊。
開放注冊是為了測試使用箫措,正式環(huán)境中不推薦使用該方式注冊環(huán)信賬號腹备;
授權(quán)注冊的流程應(yīng)該是您服務(wù)器通過環(huán)信提供的 RESTAPI注冊,之后保存到您的服務(wù)器或返回給客戶端斤蔓。
注冊用戶名會自動轉(zhuǎn)為小寫字母植酥,所以建議用戶名均以小寫注冊。(強烈建議開發(fā)者通過后臺調(diào)用 REST 接口去注冊環(huán)信 ID弦牡,客戶端注冊方法不提倡使用友驮。)
//注冊失敗會拋出HyphenateException
EMClient.getInstance().createAccount(username, pwd);//同步方法 (不推薦客戶端注冊)
2.2-登錄
app登錄成功之后,獲取后臺創(chuàng)建好的username驾锰,password卸留。值得注意的是,回調(diào)的三個方法都是位于子線程椭豫,不能夠在方法體內(nèi)做ui操作耻瑟。
調(diào)用環(huán)信api旨指,EMClient.getInstance().login(userName,password,new EMCallBack());進行環(huán)信賬號登錄。
EMClient.getInstance().groupManager().loadAllGroups();
EMClient.getInstance().chatManager().loadAllConversations();
以上兩個方法是為了保證進入主頁面后本地會話和群組都 load 完畢喳整,根據(jù)自身業(yè)務(wù)調(diào)用谆构,除登錄api成功回調(diào)使用,建議每次啟動app都在啟動頁調(diào)用一次框都。
退出登錄搬素,直接調(diào)用 EMClient.getInstance().logout(true)即可;
環(huán)信登錄成功后,默認為自動登錄魏保,可按需求取消自動登錄options.setAutoLogin(false)熬尺。
EMClient.getInstance().isLoggedInBefore(),判斷環(huán)信賬號登錄狀態(tài)
2.3-(成功登錄環(huán)信后)設(shè)置環(huán)信服務(wù)連接監(jiān)聽
注冊連接監(jiān)聽囱淋,可用作監(jiān)聽設(shè)備登錄唯一猪杭,發(fā)生多點登錄,作出提示妥衣。只需在注冊一次即可皂吮,建議在應(yīng)用首頁注冊,這樣首頁不銷毀就可以做到全局監(jiān)聽的效果税手,進入app注冊監(jiān)聽蜂筹。
退出app時,調(diào)用EMClient.getInstance().removeConnectionListener(MyConnectionListener);銷毀監(jiān)聽芦倒。MyConnectionListener類實現(xiàn)了EMConnectionListener接口
2.3-(成功登錄環(huán)信后)設(shè)置環(huán)信消息接收監(jiān)聽
EMClient.getInstance().chatManager().addMessageListener(msgListener);只需在注冊一次即可艺挪,建議在應(yīng)用首頁注冊,這樣首頁不銷毀就可以做到全局監(jiān)聽的效果兵扬,進入app注冊監(jiān)聽麻裳,退出app調(diào)用EMClient.getInstance().chatManager().removeMessageListener(msgListener);
值得注意的是,EMMessageListener的眾多回調(diào)方法中器钟, onMessageReceived(List messages)是最重要的方法津坑,所有消息接收都在此方法中,但是看方法的參數(shù)傲霸,竟然是list集合疆瑰,這里面我們只需要獲取list里面的第一個數(shù)據(jù)即可,List<EMMessage> message = messages.get(0);昙啄,這條是最新的消息穆役。EMMessageListener的回調(diào)方法依然是在子線程中,所以需要配合handler進行ui操作梳凛。
首先是注冊監(jiān)聽耿币,我是在MainActivity首頁設(shè)置的,UserBiz.isLogin() && EMClient.getInstance().isLoggedInBefore()雙重判斷用戶是否已登錄韧拒,環(huán)信賬號登錄掰读。EMReceiveBiz是我自己寫一個處理消息接收的業(yè)務(wù)類秘狞,全局只在MainActivity注冊一次監(jiān)聽,避免收到多次消息蹈集。
關(guān)于MyConnectionListener烁试,上面已經(jīng)有介紹。與消息監(jiān)聽同理拢肆。
然后是銷毀監(jiān)聽,當(dāng)退出app時郭怪,把注冊的2個監(jiān)聽銷毀
EMClient.getInstance().removeConnectionListener(eMConnectionListener);
EMClient.getInstance().chatManager().removeMessageListener(emReceiveBiz.msgListener);
EMReceiveBiz里面用到了handler支示,所以為了防止內(nèi)存泄露,把handler監(jiān)聽銷毀鄙才。
3.添加好友
EMClient.getInstance().contactManager().setContactListener(newEMContactListener()); 注冊好友監(jiān)聽
//參數(shù)為要添加的好友的username和添加理由
EMClient.getInstance().contactManager().addContact(toAddUsername, reason);
一般添加好友除了環(huán)信平臺添加好友颂鸿,本地接口也需要添加到好友列表,所以reason根據(jù)需求設(shè)置參數(shù)攒庵,比如本地接口添加好友需要用戶userId嘴纺,那么可以將reason設(shè)置為自己的userId,發(fā)送成功后浓冒,對方將在onContactInvited方法中獲取到你的環(huán)信賬號栽渴,與你的userId,這樣再處理接收好友請求稳懒,調(diào)用本地接口添加好友闲擦。
4.好友消息列表處理(根據(jù)最后聊天發(fā)送時間排序)
我們看到QQ,微信也好场梆,消息列表的排序墅冷,都是按發(fā)送時間為基準(zhǔn),發(fā)送時間距離當(dāng)前時間越近排序越靠前或油。
這里面環(huán)信并沒有直接提供這樣的api寞忿。所以需要我們自己基于環(huán)信api做排序處理。
我把自己處理的代碼發(fā)出來装哆,List<UserFriend> dataList 是項目中調(diào)取本地好友接口獲取的好友列表。
EMClientMsgBiz clientBiz1 =newEMClientMsgBiz();
clientBiz1.setImAccount(o1.getFriendImAccount());
List lastMsgInfo1 = clientBiz1.getMessage(1);?
o1.getFriendImAccount()是該好友的環(huán)信賬號定嗓,然后 調(diào)取環(huán)信api蜕琴,getMessage(pagerNum),pagerNum代表獲取多少條數(shù)據(jù)宵溅,這里我們只需要獲取最新的消息記錄凌简,所以設(shè)置為1即可獲得與該好友的最后一條聊天EMMessage,如果沒有一個消息記錄恃逻,則conversation==null雏搂,所以new 一個集合返回藕施,否則有空指針異常。
EMMessage? 環(huán)信聊天消息實體類凸郑,我們調(diào)用EMMessage.getMsgTime(裳食,獲取消息發(fā)送時間,然后把整個列表的會話排序即可芙沥。下面的方法便是比對消息發(fā)送時間的進行排序诲祸。Collections.sort(List list,Comparator c);是java.util中Collections類中的方法,不了解的可以去查看一下而昨。這樣好友消息會話列表的排序就處理好了
接下來處理會話列表的顯示問題救氯。我這里的處理方式是在adapter里面處理的。
處理方式大同小異歌憨,通過UserFriend里面的friendImAccount着憨,調(diào)取環(huán)信api,獲取未讀消息數(shù)量getUnreadMsgCount务嫡,獲取最后消息發(fā)送時間getMsgTime(消息類型為long甲抖,時間戳為毫秒數(shù),如何顯示按需求處理)植袍,獲取最后消息發(fā)送內(nèi)容 EaseCommonUtils.getMessageDigest(lastMsgInfo1.get(0))惧眠。
EaseCommonUtils環(huán)信easeui demo里面的工具類,專門處理環(huán)信消息類型簡寫于个。
5.聊天界面消息發(fā)送氛魁,接收處理。
到了這一步厅篓,聊天準(zhǔn)備工作都做好了秀存,接下來可以選擇聊天對象,發(fā)送聊天消息和接收聊天消息羽氮。
上一步說到UserFriend或链,這個好友實體,是本地接口返回的數(shù)據(jù)档押,這是我自己項目中定義的變量澳盐,下面三個是自己定義的,接口不返回這些數(shù)據(jù)令宿,而是由環(huán)信api獲取到的叼耙,用于好友消息列表展示
有了UserFriend這個實體,我們帶入聊天界面粒没,就可以通過好友的環(huán)信賬號筛婉,調(diào)用歷史消息記錄,未讀消息數(shù)量清零癞松,發(fā)送聊天消息環(huán)信api等等爽撒。接下來會講到入蛆。
EMClientChatBiz 是專門處理聊天界面調(diào)用環(huán)信api的業(yè)務(wù)類,進入聊天界面顯進行初始化硕勿,并且設(shè)置消息發(fā)送監(jiān)聽哨毁。OnSendMsgListener是自定義的回調(diào)接口。
emClientBiz.setChatUsernameId(userFriendInfo); 把好友的環(huán)信賬號傳入EMClientChatBiz首尼,這樣可以調(diào)用相關(guān)api方法挑庶。
5.1-EMClientChatBiz,聊天業(yè)務(wù)處理類软能,會一一詳細介紹
現(xiàn)在迎捺,發(fā)送各類消息,MessageInfo實體是本地定義的查排,根據(jù)發(fā)送內(nèi)容設(shè)置凳枝,并且轉(zhuǎn)換成相應(yīng)類型的EMMessage實體。
各類消息的創(chuàng)建跋核,其中發(fā)送地理位置岖瑰,攜帶了定位截圖,是以EMMessage.createImageSendMessage()方法創(chuàng)建的砂代,因為環(huán)信api中創(chuàng)建位置消息蹋订,并不能攜帶圖片,因此才通過創(chuàng)建圖片消息刻伊,附帶自定義屬性將經(jīng)緯度等信息發(fā)送露戒。這個有點投巧,暫時沒想出好的辦法捶箱。
首先設(shè)置消息發(fā)送監(jiān)聽智什,message.setMessageStatusCallback(newEMCallBack(){}); 每條消息的發(fā)送都需要設(shè)置消息監(jiān)聽,以便正確顯示發(fā)送狀態(tài)丁屎,顯示相應(yīng)的ui荠锭。
消息發(fā)送,并設(shè)立監(jiān)聽晨川,設(shè)置消息為發(fā)送中
根據(jù)發(fā)送監(jiān)聽回調(diào)修改消息狀態(tài)
EMCallBack共虑,其回調(diào)方法都是子線程愧怜,所以采用handler,更新ui
通過自定義監(jiān)聽看蚜,返回消息狀態(tài)叫搁,更新ui
發(fā)送消息處理完赔桌,接下來就是聊天界面接收消息處理了供炎。接收消息上面有說道渴逻,在首頁設(shè)置了消息接收的全局監(jiān)聽,現(xiàn)在我們就利用消息監(jiān)聽音诫,來處理聊天界面的消息接收夯缺。還是拿之前的圖來講瑟啃。ActivityTask,F(xiàn)ragmentTask是管理類,存放堆棧的實例俯抖,不理解的可以查看這篇博客
http://blog.csdn.net/u010635353/article/details/49681659
,sendDataToActivity類似于EventBus或者廣播通知牛欢,攜帶參數(shù)铭拧。
這里主要將收到的消息傳遞到三個地方,如果當(dāng)前界面是在聊天界面庇茫,那么將EMMessage傳遞到聊天界面港粱。這里只介紹聊天界面的消息接收。
收到消息后旦签,取出EMMessage查坪,然后emMessage.getFrom(),獲取發(fā)送人的環(huán)信賬號宁炫,與當(dāng)前聊天對象的環(huán)信賬號比對偿曙,一致則加入消息列表,這樣處理主要防止好友消息亂入羔巢,比如你與A聊天望忆,好友B發(fā)你的消息你也可以接收到,如果正在聊天界面朵纷,不做處理炭臭,這條消息就會插入到聊天界面的消息列表中。
msgId也是同樣道理袍辞,如果出現(xiàn)同一時間收到多條重復(fù)消息鞋仍,那么他的msgId必定是一致的,所以也做了過濾處理搅吁。
6.消息展示處理
文字消息獲取
圖片消息獲取
位置消息獲取谎懦,由于位置消息是通過圖片類型發(fā)送的肚豺,因此接收還是圖片類型,但是先判斷自定義的屬性是否為null界拦,null會產(chǎn)生異常吸申,所以這個圖片消息不是位置消息。
語音消息??
最后日丹,還有幾條實用的api走哺,可以使用。
EMClientChatBiz:聊天界面使用束凑,發(fā)送消息
EMClientFriendBiz:添加好友晒旅,好友相關(guān)api
EMClientLoginBiz:登錄,退出環(huán)信賬號
EMClientMsgBiz:環(huán)信消息相關(guān)api汪诉,未讀敢朱,獲取消息數(shù),主要用于好友會話列表
EMClientReceiveBiz:聊天消息接收摩瞎,消息分發(fā)
這樣結(jié)合自身需求拴签,一個基礎(chǔ)聊天功能就出來了。還沒有使用過環(huán)信并且有這方面需求的的朋友可以自己動手試試旗们,有什么不明白的地方可以留言蚓哩。