Android-IM即時通訊關于消息撤回的處理

項目源碼請參考 Android-IM
項目服務端使用極光JMessage

對話撤回的效果圖:

這里只是在對話的界面展示了撤回消息的處理。
其實還有一個地方蝗锥,是會話列表葱蝗,也需要動態(tài)展示撤回消息的通知悼凑。

先說對話列表要進行的操作

  • 發(fā)送方:點擊撤回事件寸莫,本地視圖移除披坏,通知服務端更新
  • 接收方:動態(tài)獲取消息帚屉,當獲取到撤回消息事件,移除視圖槽袄。

然后是會話列表也要同步展示

  • 會話列表只有一個接收方,需要在接收到撤回消息的事件更新視圖

具體實現(xiàn)

發(fā)送方撤回

只能是發(fā)送方才可以撤回

1多搀、首先獲取當前聊天的會話

position這里是從上個頁面?zhèn)鬟f的數(shù)據(jù),上個頁面是指會話列表的索引懊蒸。Conversation就是當前的會話菊碟。
JMessageClient.getConversationList()是獲取所有的會話列表。

Conversation conversation=JMessageClient.getConversationList().get(position);

2靡馁、創(chuàng)建撤回事件

這個事件就是通知服務端的撤回消息结缚。
兩個參數(shù)分別是(需要撤回的消息,服務端返回的結果)稀火。其中Message在長按消息的時候就給返回了斩熊,只需獲取消息就可以了。
conversation.retractMessage(message.getMessage(), new BasicCallback())

3倔叼、接收到撤回成功的事件

當服務器返回撤回成功的事件(i==0)后框弛,通過

//移除當前item
mAdapter.deleteById(message.getMsgId());
//添加一條撤回的item
mAdapter.addToStart(new MyMessage("[你撤回了一條消息]", SEND_TEXT),true);
//更新視圖
mAdapter.notifyDataSetChanged();

new MyMessage第二個參數(shù)是消息類型

完整代碼:

//
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);
        }
    }
});

獲取對方的撤回事件

撤回的目的就是為了讓對方看不到姚淆,而我們作為發(fā)送方媒惕,當收到對方的消息之后,默認是直接在對話窗口展示的但壮。但是這時候對方突然撤回了消息,我們也需要在對話窗口移除掉消息哩盲。

1趣竣、注冊消息接收者

所有的通知码秉,消息都需要注冊汞窗。包括消息事件模捂、撤回事件综看、好友請求事件等等。
注冊的方法是在onCreate中忠寻,一般在android開發(fā)中會定義一個BaseActivity的基類
或者單獨的Activity中也一樣纵朋,添加:
JMessageClient.registerEventReceiver(this);
這里有個需要注意的是收到消息的時候,通知欄也會顯示消息雄家,所以如果是在對話界面,需要關閉通知欄的通知:
userName就是當前對話的對方的用戶名趟济,一般在上個頁面通過數(shù)據(jù)傳遞的方式獲取
JMessageClient.enterSingleConversation(userName);

2乱投、接收撤回消息

onEvent是為了方便JMessage識別的方法,是固定的顷编,里面的參數(shù)如果是接收撤回的消息就是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的第二個參數(shù)就需要改變?yōu)閷Ψ降念愋土恕?br> 在加載消息列表的時候也是通過該方法來判斷消息展示的左右位置。

但是會有一個問題贮庞,因為移除視圖是通過獲取消息存在本地的id峦筒。
當連續(xù)從服務器獲取幾條消息的時候,如果要撤回其中的一條窗慎。還需要對所有的消息遍歷物喷,并且判斷服務端返回的消息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是我們一開始進入頁面獲取的消息列表扇丛。同時要在獲取新消息的事件中動態(tài)添加到集合中。否則當對方發(fā)起撤回的時候尉辑,本地無法更新視圖帆精。
完整代碼:

    /*接收到撤回的消息*/
    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()是獲取會話列表的方法购啄,也就是當前頁面展示的內(nèi)容襟企。
該方法是封裝后存在于本地的,所以不需要做進一步的處理狮含。
只是加載后做進一步的解析-展示處理就行了顽悼。

1、解析會話列表

解析相對于來說比較簡單几迄,解析需要的實體類可以自己創(chuàng)建蔚龙。將需要用到的參數(shù)解析出來就可以了。
在接收到撤回消息的時候或者其他消息乓旗,需要我們刷新數(shù)據(jù)府蛇。

這里需要注意的是在解析消息的時候,要對其做判斷屿愚,由于目前只設置了文字消息和撤回消息兩種,所以暫時只對這兩種消息做了額外的處理务荆。
后期還需要對圖片消息妆距,語音消息等做進一步的判斷。

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() {
                //重新加載數(shù)據(jù)
                updataData();
            }
        },500);
    }

總結

在做消息功能的時候盅惜,大多數(shù)都是參照文檔來開發(fā)中剩,所以做的時候,需要對相關的類有一定的了解抒寂。知道其用法结啼。
而且會話也是一個即時通訊的最基礎的功能。涉及的范圍也比較廣屈芜,目前項目只實現(xiàn)了文字的會話郊愧,更高級的對話方式還需要進一步的開發(fā)朴译。

項目地址:https://github.com/wapchief/Android-IM

相關閱讀推薦:

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末属铁,一起剝皮案震驚了整個濱河市眠寿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌焦蘑,老刑警劉巖盯拱,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異例嘱,居然都是意外死亡狡逢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門蝶防,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甚侣,“玉大人渠啤,你說我怎么就攤上這事践剂〔⑵耄” “怎么了蹦误?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵乙濒,是天一觀的道長嘱腥。 經(jīng)常有香客問我殿雪,道長钧栖,這世上最難降的妖魔是什么嘿悬? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任实柠,我火速辦了婚禮,結果婚禮上善涨,老公的妹妹穿的比我還像新娘窒盐。我一直安慰自己,他們只是感情好钢拧,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布蟹漓。 她就那樣靜靜地躺著,像睡著了一般源内。 火紅的嫁衣襯著肌膚如雪葡粒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天膜钓,我揣著相機與錄音嗽交,去河邊找鬼。 笑死颂斜,一個胖子當著我的面吹牛夫壁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播焚鲜,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼掌唾,長吁一口氣:“原來是場噩夢啊……” “哼放前!你這毒婦竟也來了?” 一聲冷哼從身側響起糯彬,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤凭语,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后撩扒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體似扔,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年搓谆,在試婚紗的時候發(fā)現(xiàn)自己被綠了炒辉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡泉手,死狀恐怖黔寇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情斩萌,我是刑警寧澤缝裤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站颊郎,受9級特大地震影響憋飞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜姆吭,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一榛做、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧内狸,春花似錦检眯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瘪撇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間港庄,已是汗流浹背倔既。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鹏氧,地道東北人渤涌。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像把还,于是被迫代替她去往敵國和親实蓬。 傳聞我的和親對象是個殘疾皇子茸俭,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 點擊查看原文 Web SDK 開發(fā)手冊 SDK 概述 網(wǎng)易云信 SDK 為 Web 應用提供一個完善的 IM 系統(tǒng)...
    layjoy閱讀 13,786評論 0 15
  • https://github.com/coderMyy/MYCoreTextLabel 圖文混排 , 實現(xiàn)圖片文...
    saman0閱讀 2,949評論 1 19
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,444評論 0 17
  • 關于聊天室項目 聊天室項目安皱,也被稱為即時通訊(IM)调鬓。 其原理是服務器是一直在啟動狀態(tài)的線程,不斷的從客戶端(Ap...
    八怪不姓丑閱讀 41,738評論 52 241
  • 2017.02.22 可以練習酌伊,每當這個時候腾窝,腦袋就犯困,我這腦袋真是神奇呀居砖,一說讓你做事情虹脯,你就犯困,你可不要太...
    Carden閱讀 1,349評論 0 1