基于xmpp协议,openfire服务器,处理被挤下线,或因网络掉线,第二次无法登录的问题

出自:http://my.eoe.cn/699035/archive/4818.html


奉献一个Log类,大家以后不用在烦恼每次都要去写TAG了,这个类用到了单例模式的饿汉式,有心的同学可以改成完美式:

public class LogUtil {
    private final static String tag = "[你想取啥名,就取啥名]";
     public static int logLevel = Log.VERBOSE;
    //public static int logLevel = Log.ERROR;
    //private static boolean logFlag = true;
    private static LogUtil logger = new LogUtil();;

    public static LogUtil getLogger() {

        return logger;
    }

    private LogUtil() {

    }

    private String getFunctionName() {

        StackTraceElement[] sts = Thread.currentThread().getStackTrace();
        if (sts == null) {
            return null;
        }

        for (StackTraceElement st : sts) {

            if (st.isNativeMethod()) {
                continue;
            }
            if (st.getClassName().equals(Thread.class.getName())) {
                continue;
            }

            if (st.getClassName().equals(this.getClass().getName())) {
                continue;
            }
            return "[ " + Thread.currentThread().getName() + ": "
                    + st.getFileName() + ":" + st.getLineNumber() + " ]";
        }
        return null;
    }

    public void i(Object str) {
        if (!AppConfig.DEBUG)
            return;
        if (logLevel <= Log.INFO) {
            String name = getFunctionName();
            if (name != null) {
                Log.i(tag, name + " - " + str);
            } else {
                Log.i(tag, str.toString());
            }
        }
    }

    public void v(Object str) {
        if (!AppConfig.DEBUG)
            return;
        if (logLevel <= Log.VERBOSE) {
            String name = getFunctionName();
            if (name != null) {
                Log.v(tag, name + " - " + str);
            } else {
                Log.v(tag, str.toString());
            }
        }
    }

    public void w(Object str) {
        if (!AppConfig.DEBUG)
            return;
        if (logLevel <= Log.WARN) {
            String name = getFunctionName();
            if (name != null) {
                Log.w(tag, name + " - " + str);
            } else {
                Log.w(tag, str.toString());
            }
        }
    }

    public void e(Object str) {
        if (!AppConfig.DEBUG)
            return;
        if (logLevel <= Log.ERROR) {
            String name = getFunctionName();
            if (name != null) {
                Log.e(tag, name + " - " + str);
            } else {
                Log.e(tag, str.toString());
            }
        }
    }

    public void e(Exception ex) {
        if (!AppConfig.DEBUG)
            return;
        if (logLevel <= Log.ERROR) {
            Log.e(tag, "error", ex);
        }
    }

    public void d(Object str) {
        if (!AppConfig.DEBUG)
            return;
        if (logLevel <= Log.DEBUG) {
            String name = getFunctionName();
            if (name != null) {
                Log.d(tag, name + " - " + str);
            } else {
                Log.d(tag, str.toString());
            }
        }
    }

}

接着我们需要一个单例类来管理XMPPConnection,这次用的好像是懒汉式,为什么会使用单例呢,原因是你不想你的应用中出现多个XMPPConnection对象吧,当中出现红色X的时候可能是因为转义的问题,那个X代表的是(":"+ x + ":")

public class XmppConnManager {

    public static int    SERVER_PORT = 5222;//服务端口 可以在openfire上设置
    public static String SERVER_HOST = "42.121.17.115";//你openfire服务器所在的ip
    public static  String SERVER_NAME = "helloworld";//设置openfire时的服务器名
    private static XMPPConnection connection = null;
    private static XmppConnManager connManager = null;

    public static  XmppConnManager getInstance(){
        if(connManager == null){
            connManager = new XmppConnManager();
        }
        return connManager;
    }

    private  void openConnection() {
        try {
            if (null == connection || !connection.isAuthenticated()) {
                XMPPConnection.DEBUG_ENABLED = true;//开启DEBUG模式
                //配置连接
            /*  ConnectionConfiguration config = new ConnectionConfiguration(
                        SERVER_HOST, SERVER_PORT,
                        SERVER_NAME);*/
                ConnectionConfiguration config = new ConnectionConfiguration(
                        SERVER_HOST, SERVER_PORT);
                config.setReconnectionAllowed(true);
                config.setSendPresence(false);
/*              config.setSASLAuthenticationEnabled(false);
                config.setSecurityMode(SecurityMode.disabled);
                config.setCompressionEnabled(false);*/
                connection = new XMPPConnection(config);
                connection.connect();//连接到服务器
                //配置各种Provider
                configureConnection(ProviderManager.getInstance());
            }
        } catch (XMPPException xe) {
            xe.printStackTrace();
        }
    }

    /**
     * 创建连接
     */ 
    public  XMPPConnection getConnection() {
        if (connection == null) {
            openConnection();
        }
        return connection;
    }

    /**
     * 关闭连接
     */ 
    public  void closeConnection() {
        if(connection!=null){
            connection.disconnect();
            connection = null;
            LogUtil.getLogger().e("執行closeConnection操作");
        }
    }


    /**
     * xmpp配置
     */
    private  void configureConnection(ProviderManager pm) {
        // Private Data Storage
        pm.addIQProvider("query", "jabber:iq:private",new PrivateDataManager.PrivateDataIQProvider());
        // Time
        try {
            pm.addIQProvider("query", "jabber:iq:time",Class.forName("org.jivesoftware.smackx.packet.Time"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Roster Exchange
        pm.addExtensionProvider("x", "jabberroster",new RosterExchangeProvider());
        // Message Events
        pm.addExtensionProvider("x", "jabberevent",new MessageEventProvider());
        // Chat State
        pm.addExtensionProvider("active","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());
        pm.addExtensionProvider("composing","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());
        pm.addExtensionProvider("paused","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());
        pm.addExtensionProvider("inactive","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());
        pm.addExtensionProvider("gone","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());
        // XHTML
        pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im",new XHTMLExtensionProvider());
        // Group Chat Invitations
        pm.addExtensionProvider("x", "jabberconference",new GroupChatInvitation.Provider());
        // Service Discovery # Items //解析房间列表
        pm.addIQProvider("query", "http://jabber.org/protocol/disco#items",new DiscoverItemsProvider());
        // Service Discovery # Info //某一个房间的信息
        pm.addIQProvider("query", "http://jabber.org/protocol/disco#info",new DiscoverInfoProvider());
        // Data Forms
        pm.addExtensionProvider("x", "jabberdata", new DataFormProvider());
        // MUC User
        pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user",new MUCUserProvider());
        // MUC Admin
        pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin",new MUCAdminProvider());
        // MUC Owner
        pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner",new MUCOwnerProvider());
        // Delayed Delivery
        pm.addExtensionProvider("x", "jabberdelay",new DelayInformationProvider());
        // Version
        try {
            pm.addIQProvider("query", "jabber:iq:version",Class.forName("org.jivesoftware.smackx.packet.Version"));
        } catch (ClassNotFoundException e) {
            // Not sure what's happening here.
        }
        // VCard
        pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());
        // Offline Message Requests
        pm.addIQProvider("offline", "http://jabber.org/protocol/offline",new OfflineMessageRequest.Provider());
        // Offline Message Indicator
        pm.addExtensionProvider("offline","http://jabber.org/protocol/offline",new OfflineMessageInfo.Provider());
        // Last Activity
        pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider());
        // User Search
        pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider());
        // SharedGroupsInfo
        pm.addIQProvider("sharedgroup","http://www.jivesoftware.org/protocol/sharedgroup",new SharedGroupsInfo.Provider());
        // JEP-33: Extended Stanza Addressing
        pm.addExtensionProvider("addresses","http://jabber.org/protocol/address",new MultipleAddressesProvider());
        pm.addIQProvider("si", "http://jabber.org/protocol/si",new StreamInitiationProvider());
        pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
        pm.addIQProvider("command", "http://jabber.org/protocol/commands",new AdHocCommandDataProvider());
        pm.addExtensionProvider("malformed-action","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.MalformedActionError());
        pm.addExtensionProvider("bad-locale","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.BadLocaleError());
        pm.addExtensionProvider("bad-payload","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.BadPayloadError());
        pm.addExtensionProvider("bad-sessionid","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.BadSessionIDError());
        pm.addExtensionProvider("session-expired","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.SessionExpiredError());
    }
}


接下来要写一个服务类来监听XMPPConnecttion:


public class MessageService extends Service {

    private LogUtil log = LogUtil.getLogger();
    private ChatManager cm;
    private OfflineMessageManager offlineManager;
    public static XMPPConnection con = null;

    static{   
        try{  
           Class.forName("org.jivesoftware.smack.ReconnectionManager");  
        }catch(Exception e){  
            e.printStackTrace();  
        }  
    }  
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @SuppressWarnings("deprecation")
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        new Thread(new Runnable() {

            @Override
            public void run() {
                if(NetWorkUtil.netState(MessageService.this)!=false) {
                    con = XmppConnManager.getInstance().getConnection();
                    con.addConnectionListener(new ConnectionListener(){

                        @Override
                        public void connectionClosed() {
                            log.e("来自连接监听,conn正常关闭");
                        }
                        @Override
                        public void connectionClosedOnError(Exception arg0) {
                             //这里就是网络不正常或者被挤掉断线激发的事件
                            if(arg0.getMessage().contains("conflict")){ //被挤掉线
                /*              log.e("来自连接监听,conn非正常关闭");
                                log.e("非正常关闭异常:"+arg0.getMessage());
                                log.e(con.isConnected());*/
                            //关闭连接,由于是被人挤下线,可能是用户自己,所以关闭连接,让用户重新登录是一个比较好的选择                           
                            XmppConnManager.getInstance().closeConnection();
                            //接下来你可以通过发送一个广播,提示用户被挤下线,重连很简单,就是重新登录
                            }else if(arg0.getMessage().contains("Connection timed out")){//连接超时
                                // 不做任何操作,会实现自动重连
                            }
                        }
                        @Override
                        public void reconnectingIn(int arg0) {
                             //重新连接的动作正在进行的动作,里面的参数arg0是一个倒计时的数字,如果连接失败的次数增多,数字会越来越大,开始的时候是9
                            log.e("来自连接监听,conn重连中..."+arg0);
                        }

                        @Override
                        public void reconnectionFailed(Exception arg0) {
                             //重新连接失败
                            log.e("来自连接监听,conn失败:"+arg0.getMessage());
                        }
                        @Override
                        public void reconnectionSuccessful() {
                            //当网络断线了,重新连接上服务器触发的事件
                            log.e("来自连接监听,conn重连成功");
                        }

                    });




        }).start();
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        return super.onStartCommand(intent, flags, startId);
    }

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值