天天看點

XMPP聊天軟體用戶端開發(3)

步驟4:好友清單以及狀态(Roster and Presence)。

Roster:好友清單,但它不是一個表,而是一個比較複雜的類。

Presence:好友的狀态,是Roster中包含的類,但有特殊作用。

大家閱讀源碼,了解Roster 與 Presence包含的資訊。特别注意幾個枚舉類的不同,不要混淆了。

·加載清單:

通過Roster類的

getInstanceFor()

函數和connection就可以獲得執行個體。通過

getEntries

就可以獲得所有Entry,即是獲得好友清單資訊。

通過

getPresence()

函數可以獲得Presence。

·監聽清單:

通過

addRosterListener()

添加監聽器,則可以監聽好友的資訊的變化,如上線下線等。

Roster參考代碼:

roster = Roster.getInstanceFor(connection);
            roster.setSubscriptionMode(Roster.SubscriptionMode.manual);
            roster.addRosterListener(new RosterListener() {
                @Override
                public void entriesAdded(Collection<String> addresses) {
                    for(String jid : addresses){
                        RosterEntry entry= roster.getEntry(jid);
                        entries.put(jid,entry);
                    }
                    rosterChangedListener.rosterChanged();
                }

                @Override
                public void entriesUpdated(Collection<String> addresses) {
                    rosterChangedListener.rosterChanged();
                }

                @Override
                public void entriesDeleted(Collection<String> addresses) {
                    for(String jid : addresses){
                        entries.remove(jid);
                        rosterChangedListener.rosterChanged();
                    }
                }

                @Override
                public void presenceChanged(Presence presence) {
                    presenceHashMap.put(presence.getFrom(),presence);
                    rosterChangedListener.rosterChanged();
                }

            });
           

!注意!

當你直接寫了代碼并運作後,可能會發現Roster的Entries會是空的!這個問題筆者網上找了許久,最後發現是由于用戶端運作過快,在登入後馬上擷取Roster,導緻Roster内容為空,或則說在伺服器還沒有把Roster傳過來時,代碼已經運作完畢了。解決方法是在登入後将線程暫停一下,再擷取一次Roster。

步驟5:多人聊天

多人聊天與單人聊天不同,其是基于XEP協定的,差別之處在于多人聊天要在伺服器上建立聊天室,然後其他加入聊天室中聊天,而單人聊天則隻是兩個節點之間的對話。其實對于這裡的設計有點不太了解,因為這樣使用兩套設計令到實作用戶端時需要進行兩套實作,然而這兩種聊天方式是有很多共性的,因而會導緻很多的重複。我看了看微信的實作方式,微信應該是将兩種聊天方式統一起來的,單人聊天中可以随時添加其他人,也就是說隻使用了XMPP中多人聊天方式這一種實作。

多人聊天中重要的類有:

MultiUserChat:類似單人聊天的Chat,是多人聊天會話類。

MultiUserChatManager:多人聊天會話的管理類。

接口:

MessageListener:消息監聽接口

多人聊天比單人聊天的建立複雜一些,多了建立、發送邀請、加入聊天室三個步驟。

參考代碼:

加入聊天室

public void joinChattingRoom(MultiUserChat multiUserChat,String nickname) throws SmackException.NotConnectedException, XMPPException.XMPPErrorException, SmackException.NoResponseException {
        multiUserChat.join(nickname);
        dataManager.addToChatsList(multiUserChat.getRoom());
        chatsMap.put(multiUserChat.getRoom(), multiUserChat);
        multiUserChat.addMessageListener(new MessageListener() {
            @Override
            public void processMessage(Message message) {
                if(message.getType().equals(Message.Type.groupchat)){
                    dataManager.processMessage(message);
                }
            }
        });
    }
           

邀請監聽

multiUserChatManager.addInvitationListener(new InvitationListener() {
            @Override
            public void invitationReceived(XMPPConnection xmppConnection, MultiUserChat multiUserChat, String inviter, String reason, String s3, Message message) {
                //回調一下activity,彈框
                invitationReceivedListener.onInvitationReceived(multiUserChat, inviter , reason);
            }
        });
           

建立聊天室

public void createMultiUserChat(String roomName,String nickname) throws XMPPException.XMPPErrorException, SmackException {
        String jid = roomName+"@conference.192.168.0.101";
        MultiUserChat muc = multiUserChatManager.getMultiUserChat(jid);
        muc.create(nickname);
        dataManager.addToChatsList(jid);
        chatsMap.put(jid, muc);
        muc.sendConfigurationForm(new Form(DataForm.Type.submit));
        muc.addMessageListener(new MessageListener() {
            @Override
            public void processMessage(Message message) {
                if (message.getType().equals(Message.Type.groupchat)) {
                    dataManager.processMessage(message);
                }
            }
        });
    }
           

以上就是實作XMPP聊天用戶端的核心内容,其他額外的實作就多說,畢竟本人較菜,處于學習中,不值得參考。

項目小結:

基本上隻是簡單地實作了一個文本通信的簡單程式,收獲也頗多。

首先,學會了基于開源的庫怎麼去開發,流程大概是:

讀理論——>讀庫的開發文檔(邊度邊動手)——>讀源碼——>設計子產品——>實作設計。

第二,當程式寫着寫着,發現資料異常亂,原因是沒有将資料剝離出來,後來準備寫一個資料層,寫了一些,發現資料層不好寫,原因是資料類型有多種,以及某些類的耦合性導緻資料剝離會重複做工,例如Roster類,包含了資料。後來大緻看了一下Spark的設計,發現它不是分出資料層,而是将每一種資料設計一個容器,感覺這個思路比集中一個資料層要好一點。

第三,在架構方面比以前小有長進,對比了Spark的架構,發現設計的思路較為類似,都是UI分一層,利用管理類作為控制。

第四,當然就是熟悉了部分網絡程式設計的知識了,了解了一些協定之間的差別。