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分一层,利用管理类作为控制。

第四,当然就是熟悉了部分网络编程的知识了,了解了一些协议之间的区别。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值