android移动端xmpp开发入门

来源:互联网 发布:seo排名软件免费 编辑:程序博客网 时间:2024/05/01 21:59

引入

即时通信技术现在已经广泛应用到各种app中了,那么他到底是怎么实现的呢。前段时间因为项目开发的需要,了解学习过一些这方面。这篇文章记录的是我个人了解的一些这方面的知识,如果有错误的地方还请斧正指出,非常感谢。
另外 慕课网中 郭大神的关于xmpp的这个课程也对我学习起到了很大的帮助:http://www.imooc.com/learn/223

xmpp

  • XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。XMPP目前被IETF国际标准组织完成了标准化工作。标准化的核心结果分为两部分; 核心的XML流传输协议 基于XML流传输的即时通讯扩展应用 XMPP的核心XML流传输协议的定义使得XMPP能够在一个比以往网络通信协议更规范的平台上。借助于XML易于解析和阅读的特性,使得XMPP的协议能够非常漂亮。 XMPP的即时通讯扩展应用部分是根据IETF在这之前对即时通讯的一个抽象定义的,与其他业已得到广泛使用的即时通讯协议,诸如AIM,QQ等有功能完整,完善等先进性。
  • 上面是xmpp的官方解释,其实我每次看完官方解释,总是懵懵的。好像什么都知道了,也好像什么都不知道。不过在我了解过之后简单总结看来,xmpp就像上面说的,是一套协议。里面定义了很多xml格式的文本。比如当我们要登录到服务器时,怎么告诉服务器呢。按照xmpp协议中的规范封装一段xml的字符串以流的方式传给服务器就好了。以最简单的发送一个消息举例:
    这里写图片描述
    1. suke 发送给 beta 一条消息,消息的类型是chat(聊天),消息的内容是 who are you ?。
  • 总结以上,在我理解看来,xmpp 就像是我们平时说话使用的语言,服务器和客户端都遵循这样的规范,比我message 代表一个消息。这样到客户端想给服务器发送一条消息时,就拼装一个以message开头的xml字符串流到服务器。服务器按照xmpp的协议,就知道这是一条消息。听起来感觉傻乎乎的。可是xmpp就是这样的。
  • 如果想深入了解xmpp协议,请搜索《xmpp权威指南》,英文版本和中文版本的都有。

IM即时通信软件该怎么做

  • 目前网上比较主流的是采用开源的 openfire服务器+smack sdk 进行开发。smack是一个封装了tcp连接和xmpp协议解析的sdk。
    smack的资料可以移步github:https://github.com/igniterealtime/Smack/wiki/Smack-4.2-Readme-and-Upgrade-Guide
    里面提供了详尽的API,对应的,我也写了一个小demo,连接地址 : https://github.com/Lilee902/mXmpp
  • 我们都知道即时通信是需要做长连接的,而openfire和smack之间的连接采用的是tcp长连接。大家一定都知道心跳包和保持在线,断线重连之类的,我刚开始入手的时候也不知道怎么弄。看了文章开头郭大神的那个基于xmpp的推送后,对于其中的原理不能说豁然开朗吧,也算窥探到了一二。我在这里就不赘述了,那个视频已经讲的很明白了。

Smack怎么用

  • 连接到服务器。

    • Constant.HOST_SERVER 为服务器IP地址,运行demo时需要修改。
                      InetAddress addr = InetAddress.getByName(Constant.HOST_SERVER);                HostnameVerifier verifier = new HostnameVerifier() {                    @Override                    public boolean verify(String hostname, SSLSession session) {                        return false;                    }                };                DomainBareJid serviceName = JidCreate.domainBareFrom(Constant.HOST_SERVER);                XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()                        .setHost(Constant.HOST_SERVER) // it will be resolved by setHostAddress method                        .setUsernameAndPassword(username, pwd)                        .setPort(Constant.HOST_PORT)                        .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)                        .setXmppDomain(serviceName)                        .setHostnameVerifier(verifier)                        .setHostAddress(addr)                        .setDebuggerEnabled(true)                        .build();                connection = new XMPPTCPConnection(config);                connection.connect();
  • 连接之后,就是登录和获取好友列表(花名册)了。具体的实现

    • roster.addRosterLoadedListener(new RosterLoadedListener() {});这个是添加一个监听,因为再刚登录的时候,直接去获取花名册,服务器返回的经常为空集合。网上有人建议在登录成功之后让线程睡100毫秒,不过还是添加listener优雅一点。

         if (connection.isConnected()) {                try {                    connection.login();                } catch (Exception e) {                    android.os.Message msg = android.os.Message.obtain();                    msg.what = LOGIN_FAILED;                    handler.sendMessage(msg);                }                // Thread.sleep(100);                Roster roster = Roster.getInstanceFor(connection);                roster.addRosterLoadedListener(new RosterLoadedListener() {                    @Override                    public void onRosterLoaded(Roster roster) {                        Logger.e(TAG,"Get roster success ... " );                        android.os.Message msg = android.os.Message.obtain();                        msg.what = LOGIN_SUCCESS;                        msg.obj = roster;                        handler.sendMessage(msg);                    }                    @Override                    public void onRosterLoadingFailed(Exception exception) {                        Logger.e(TAG,"Get roster failed : " + exception.getMessage());                    }                });                android.os.Message msg = android.os.Message.obtain();                msg.what = LOGIN_SUCCESS;                msg.obj = roster;                handler.sendMessage(msg);            } else {                android.os.Message msg = android.os.Message.obtain();                msg.what = CONNECTION_FAILED;                handler.sendMessage(msg);            }        } catch (Exception e) {            e.printStackTrace();        }
  • 创建聊天室

        private void createChatRoom() {        // 设置聊天监听器,监听聊天消息        chatManager = ChatManager.getInstanceFor(connection);        chatManager.addIncomingListener(mIncomingChatMessageListener);    }IncomingChatMessageListener mIncomingChatMessageListener = new IncomingChatMessageListener() {//接收消息    @Override    public void newIncomingMessage(EntityBareJid from, Message message, org.jivesoftware.smack.chat2.Chat chat) {        String str = chatMap.get(from.toString());        String name = from.getLocalpart().toString();        String msg = message.getBody();        String type = message.getType().toString();        if (str == null) {            str = name + " : " + type + " : " + msg + "\n";        } else {            str += name + " : " + type + " : " + msg + "\n";        }        chatMap.put(from.toString(), str);        mainBinding.tvChatCon.setText(str);    }};//发送消息private void sendmsg(String msg, RosterEntry rosterEntry, Message.Type type) {    Chat currentChat;    try {        String jidStr = rosterEntry.getJid().toString();        EntityBareJid jid = JidCreate.entityBareFrom(jidStr);        currentChat = chatManager.chatWith(jid);        Message newMessage = new Message();        newMessage.setBody(msg);        newMessage.setType(type);        currentChat.send(newMessage);        String str = chatMap.get(jidStr);        if (str == null) {            str = username + " : " + msg + "\n";        } else {            str += username + " : " + msg + "\n";        }        chatMap.put(jidStr, str);        mainBinding.tvChatCon.setText(str);        mainBinding.etWillSendMsg.setText("");    } catch (SmackException.NotConnectedException e) {        e.printStackTrace();    } catch (InterruptedException e) {        e.printStackTrace();    } catch (XmppStringprepException e) {        e.printStackTrace();    }}

    总结

    其实对于xmpp,我现在也只是略微了解一些,上面这些,希望对有这方面需求的同学有所帮助。郭大神的那个视频和xmpp权威指南真的很值得阅读。视频有助于理解客户端与服务器的连接实现,而xmpp权威指南中会告诉你xmpp协议都定义了那些功能(节的概念,发送消息,出席状态,状态订阅,多设备登录哪个优先,发送文件是怎么实现的,为什么只能发送小文件等等很多很多),了解了这些功能也有助于使用smack这个sdk,同时给扩展做好准备。
    好了,希望以上这些,可以对大家有些许帮助,谢谢。

原创粉丝点击