zoukankan      html  css  js  c++  java
  • XMPP 通信之Asmack(一) 建立连接

      先声明:我这里不分析源码,只介绍开发包的使用,欢迎大家交流

      openfire+spark+smack是java领域的一种即时通信解决方案;

      Openfire是基于Jabber协议(XMPP)实现的即时通信服务器端版本,网上很容易找到开发包,建议使用能找到的最新开发包;

      Spark支持聊天、语音、视频、截屏、会议、文件收发、连接MSN等功能,我未找到android方面的支持,各位博友若有谢谢分享;

      Smack是即时通信客户端编程库,是基于XMPP的java实现,提供了一套可扩展的API,而Asmack是该编程库的android版本,这是本文介绍的重点;

      1.什么是XMPP?

      百度百科上解释的是“XMPP是一种基于标准通用标记语言的子集XML的协议”,简单的说就是一个收发消息的协议,而这个协议就是基于XML;XMPP的前身是jabber,由一个开源组织产生的即时通信协议,后来由IETF完成标准化工作;

      2.IM

      即”即时通信软件“,想现在国内使用人比较多的QQ、微信等等,但他们采用的是这些公司自己的通信协议,并不对外开放,一般的公司没有过于硬性的需求,XMPP协议已经可以满足我们的需求;

     接下来就是正文,即Asmack的使用:

     1.关于开发包,就尽量使用能找到的最新的开发包,如果需要请在评论区留下邮箱

     2.下面就逐步讲解相关使用:

     一、连接,这部分重点是一个类,一个监听接口

      1.ConnectionConfiguration类,这个类是用来配置连接参数的类

      

         try {
                //初始化时传入服务器地址和端口号
                connConfig = new ConnectionConfiguration(ChatRoomInfo.openfireAddress, ChatRoomInfo.openfirePort);
                // 设置登录状态为离线
                connConfig.setSendPresence(false);
                connConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
                //允许重新连接
                connConfig.setReconnectionAllowed(true);
                //服务器名称,这个需要跟后台约定好
                connConfig.setServiceName(ChatRoomInfo.serverName);
                con = new XMPPConnection(connConfig);
    //红色标记的部分请留意,后面会详细讲解 con.addPacketListener(
    new ChatPacketListener(null), new ChatPacketFilter(context));
                connectionListener = new ViConnectionListener(context,mHandler, successful);
                con.addConnectionListener(connectionListener);

    //开始连接 con.connect();
    if (con.isConnected()) { LogUtil.w("conn is conn");//con.addPacketListener(new ChatPacketListener(null),new PacketTypeFilter(Message.class)); } LogUtil.i("XmppTool......连后接22222222222"); } catch (Exception e) { }

      2.ConnectionListener 这个接口监听连接状态,上面ViConnectionListener类则是我的实现该接口,这个接口的作用在于监听XMPP的连接状况,如果连接失败的情况出现,自动进行重连,及其他情况的处理,自己的代码如下;

    package com.bankeys.general.chatroom.Utils;
    
    import android.content.Context;
    
    import com.bankeys.general.chatroom.Handler.GeneralChatRoomHandler;
    import com.bankeys.general.chatroom.Interface.CharRoomCore;
    import com.bankeys.general.chatroom.Log.LogUtil;
    
    import org.jivesoftware.smack.ConnectionListener;
    import org.jivesoftware.smack.packet.Presence;
    
    /**
     * 同账号登录等情况监听
     */
    public class ViConnectionListener implements ConnectionListener {
        private GeneralChatRoomHandler mHandler;
        private CharRoomCore connectSuccessful;
        private Context context;
    
        /**
         *
         * @param context
         * @param mHandler  GeneralChatRoomHandler这个是handler的子类,用来处理这里的各种情况,可以视情况而定
         * @param connectSuccessful  这个接口现在看显得有些多余,毕竟有handler来处理了 就不需要了,不过暂时先放在这里不影响
         */
        public ViConnectionListener(Context context,GeneralChatRoomHandler mHandler, CharRoomCore connectSuccessful) {
            this.mHandler = mHandler;
            this.connectSuccessful = connectSuccessful;
            this.context = context;
        }
    
        @Override
        public void connectionClosed() {
            //连接关闭
            LogUtil.i("---------connectionClosed---------");
        }
    
        @Override
        public void connectionClosedOnError(Exception e) {
            //连接错误关闭,错误连接的情况,参考下就行,这部分目前还没测试
            LogUtil.i("ViConnectionListener-->connectionClosedOnError");
            if (e.getMessage().contains("conflict")) { //
                LogUtil.i("ViConnectionListener-->同一账号登陆");
                if (mHandler != null)
                    mHandler.obtainMessage(4).sendToTarget();
                //关闭连接,由于是被人挤下线,可能是用户自己,所以关闭连接,让用户重新登录是一个比较好的选择
                XmppTool.getInstance().closeConnection();
                // 接下来你可以通过发送一个广播,提示用户被挤下线,提示用户重新登录
            } else if (e.getMessage().contains("Connection timed out")) {// 连接超时
                LogUtil.i("ViConnectionListener 正在重连......ʱ");
    
            } else if (e.getMessage().contains("system-shutdown")) {     // 服务器关闭
                LogUtil.w("服务器关闭");
                if (mHandler != null)
                    mHandler.obtainMessage(5).sendToTarget();
            }
            LogUtil.i(e.getMessage());
        }
    
        @Override
        public void reconnectingIn(int arg0) {
            LogUtil.i("ViConnectionListener-->reconnectingIn 正在重新连接......");
        }
    
        @Override
        public void reconnectionFailed(Exception arg0) {
            LogUtil.i("ViConnectionListener-->reconnectionFailed  重新连接失败......");
        }
    
        @Override
        public void reconnectionSuccessful() {
            LogUtil.i("连接成功/登陆成功......");
            // 设置登录状态:在线
            Presence presence = new Presence(Presence.Type.available);
            XmppTool.getInstance().getConnection(context,mHandler, connectSuccessful).sendPacket(presence);
            if (connectSuccessful != null) {
                connectSuccessful.onConnectSuccessful();
            }
        }
    
    
    }

      这里要添加一点说明,在我们建立连接或者建立连接之前记得加上下面的代码:

        // 静态加载ReconnectionManager ,重连后正常工作
        static {
            try {
                Class.forName("org.jivesoftware.smack.ReconnectionManager");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
  • 相关阅读:
    javap,是 java printer 的缩写,是 JDK 自带的 Java 字节码分析工具
    这段代码的返回值在出现异常和不出现异常的情况下,分别应该是多少?
    strictfp 关键字修饰方法,即 strict float point (精确浮点)
    transient 修饰符修饰属性:不需要序列化的属性
    Java 中的 CAS 操作
    ReentrantLock 与 synchronized 的比较
    线程安全的实现方法:互斥同步、非阻塞同步、无同步方案
    J.U.C包的意义
    synchronized 原理
    什么场景下,使用 final、volatile、Atomic原子类、synchronized、J.U.C 包中的锁?
  • 原文地址:https://www.cnblogs.com/ZhangXiangQian/p/5254840.html
Copyright © 2011-2022 走看看