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

来源:互联网 发布:淘宝代付超限 编辑:程序博客网 时间:2024/05/21 11:04

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

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

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

[java] view plaincopy
  1. public class LogUtil {  
  2.     private final static String tag = "[你想取啥名,就取啥名]";  
  3.      public static int logLevel = Log.VERBOSE;  
  4.     //public static int logLevel = Log.ERROR;  
  5.     //private static boolean logFlag = true;  
  6.     private static LogUtil logger = new LogUtil();;  
  7.   
  8.     public static LogUtil getLogger() {  
  9.   
  10.         return logger;  
  11.     }  
  12.   
  13.     private LogUtil() {  
  14.   
  15.     }  
  16.   
  17.     private String getFunctionName() {  
  18.   
  19.         StackTraceElement[] sts = Thread.currentThread().getStackTrace();  
  20.         if (sts == null) {  
  21.             return null;  
  22.         }  
  23.   
  24.         for (StackTraceElement st : sts) {  
  25.   
  26.             if (st.isNativeMethod()) {  
  27.                 continue;  
  28.             }  
  29.             if (st.getClassName().equals(Thread.class.getName())) {  
  30.                 continue;  
  31.             }  
  32.   
  33.             if (st.getClassName().equals(this.getClass().getName())) {  
  34.                 continue;  
  35.             }  
  36.             return "[ " + Thread.currentThread().getName() + ": "  
  37.                     + st.getFileName() + ":" + st.getLineNumber() + " ]";  
  38.         }  
  39.         return null;  
  40.     }  
  41.   
  42.     public void i(Object str) {  
  43.         if (!AppConfig.DEBUG)  
  44.             return;  
  45.         if (logLevel <= Log.INFO) {  
  46.             String name = getFunctionName();  
  47.             if (name != null) {  
  48.                 Log.i(tag, name + " - " + str);  
  49.             } else {  
  50.                 Log.i(tag, str.toString());  
  51.             }  
  52.         }  
  53.     }  
  54.   
  55.     public void v(Object str) {  
  56.         if (!AppConfig.DEBUG)  
  57.             return;  
  58.         if (logLevel <= Log.VERBOSE) {  
  59.             String name = getFunctionName();  
  60.             if (name != null) {  
  61.                 Log.v(tag, name + " - " + str);  
  62.             } else {  
  63.                 Log.v(tag, str.toString());  
  64.             }  
  65.         }  
  66.     }  
  67.   
  68.     public void w(Object str) {  
  69.         if (!AppConfig.DEBUG)  
  70.             return;  
  71.         if (logLevel <= Log.WARN) {  
  72.             String name = getFunctionName();  
  73.             if (name != null) {  
  74.                 Log.w(tag, name + " - " + str);  
  75.             } else {  
  76.                 Log.w(tag, str.toString());  
  77.             }  
  78.         }  
  79.     }  
  80.   
  81.     public void e(Object str) {  
  82.         if (!AppConfig.DEBUG)  
  83.             return;  
  84.         if (logLevel <= Log.ERROR) {  
  85.             String name = getFunctionName();  
  86.             if (name != null) {  
  87.                 Log.e(tag, name + " - " + str);  
  88.             } else {  
  89.                 Log.e(tag, str.toString());  
  90.             }  
  91.         }  
  92.     }  
  93.   
  94.     public void e(Exception ex) {  
  95.         if (!AppConfig.DEBUG)  
  96.             return;  
  97.         if (logLevel <= Log.ERROR) {  
  98.             Log.e(tag, "error", ex);  
  99.         }  
  100.     }  
  101.   
  102.     public void d(Object str) {  
  103.         if (!AppConfig.DEBUG)  
  104.             return;  
  105.         if (logLevel <= Log.DEBUG) {  
  106.             String name = getFunctionName();  
  107.             if (name != null) {  
  108.                 Log.d(tag, name + " - " + str);  
  109.             } else {  
  110.                 Log.d(tag, str.toString());  
  111.             }  
  112.         }  
  113.     }  
  114.   
  115. }  

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

[java] view plaincopy
  1. public class XmppConnManager {  
  2.   
  3.     public static int    SERVER_PORT = 5222;//服务端口 可以在openfire上设置  
  4.     public static String SERVER_HOST = "42.121.17.115";//你openfire服务器所在的ip  
  5.     public static  String SERVER_NAME = "helloworld";//设置openfire时的服务器名  
  6.     private static XMPPConnection connection = null;  
  7.     private static XmppConnManager connManager = null;  
  8.   
  9.     public static  XmppConnManager getInstance(){  
  10.         if(connManager == null){  
  11.             connManager = new XmppConnManager();  
  12.         }  
  13.         return connManager;  
  14.     }  
  15.   
  16.     private  void openConnection() {  
  17.         try {  
  18.             if (null == connection || !connection.isAuthenticated()) {  
  19.                 XMPPConnection.DEBUG_ENABLED = true;//开启DEBUG模式  
  20.                 //配置连接  
  21.             /*  ConnectionConfiguration config = new ConnectionConfiguration( 
  22.                         SERVER_HOST, SERVER_PORT, 
  23.                         SERVER_NAME);*/  
  24.                 ConnectionConfiguration config = new ConnectionConfiguration(  
  25.                         SERVER_HOST, SERVER_PORT);  
  26.                 config.setReconnectionAllowed(true);  
  27.                 config.setSendPresence(false);  
  28. /*              config.setSASLAuthenticationEnabled(false); 
  29.                 config.setSecurityMode(SecurityMode.disabled); 
  30.                 config.setCompressionEnabled(false);*/  
  31.                 connection = new XMPPConnection(config);  
  32.                 connection.connect();//连接到服务器  
  33.                 //配置各种Provider  
  34.                 configureConnection(ProviderManager.getInstance());  
  35.             }  
  36.         } catch (XMPPException xe) {  
  37.             xe.printStackTrace();  
  38.         }  
  39.     }  
  40.   
  41.     /** 
  42.      * 创建连接 
  43.      */   
  44.     public  XMPPConnection getConnection() {  
  45.         if (connection == null) {  
  46.             openConnection();  
  47.         }  
  48.         return connection;  
  49.     }  
  50.   
  51.     /** 
  52.      * 关闭连接 
  53.      */   
  54.     public  void closeConnection() {  
  55.         if(connection!=null){  
  56.             connection.disconnect();  
  57.             connection = null;  
  58.             LogUtil.getLogger().e("執行closeConnection操作");  
  59.         }  
  60.     }  
  61.   
  62.   
  63.     /** 
  64.      * xmpp配置 
  65.      */  
  66.     private  void configureConnection(ProviderManager pm) {  
  67.         // Private Data Storage  
  68.         pm.addIQProvider("query""jabber:iq:private",new PrivateDataManager.PrivateDataIQProvider());  
  69.         // Time  
  70.         try {  
  71.             pm.addIQProvider("query""jabber:iq:time",Class.forName("org.jivesoftware.smackx.packet.Time"));  
  72.         } catch (Exception e) {  
  73.             e.printStackTrace();  
  74.         }  
  75.         // Roster Exchange  
  76.         pm.addExtensionProvider("x""jabberroster",new RosterExchangeProvider());  
  77.         // Message Events  
  78.         pm.addExtensionProvider("x""jabberevent",new MessageEventProvider());  
  79.         // Chat State  
  80.         pm.addExtensionProvider("active","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());  
  81.         pm.addExtensionProvider("composing","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());  
  82.         pm.addExtensionProvider("paused","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());  
  83.         pm.addExtensionProvider("inactive","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());  
  84.         pm.addExtensionProvider("gone","http://jabber.org/protocol/chatstates",new ChatStateExtension.Provider());  
  85.         // XHTML  
  86.         pm.addExtensionProvider("html""http://jabber.org/protocol/xhtml-im",new XHTMLExtensionProvider());  
  87.         // Group Chat Invitations  
  88.         pm.addExtensionProvider("x""jabberconference",new GroupChatInvitation.Provider());  
  89.         // Service Discovery # Items //解析房间列表  
  90.         pm.addIQProvider("query""http://jabber.org/protocol/disco#items",new DiscoverItemsProvider());  
  91.         // Service Discovery # Info //某一个房间的信息  
  92.         pm.addIQProvider("query""http://jabber.org/protocol/disco#info",new DiscoverInfoProvider());  
  93.         // Data Forms  
  94.         pm.addExtensionProvider("x""jabberdata"new DataFormProvider());  
  95.         // MUC User  
  96.         pm.addExtensionProvider("x""http://jabber.org/protocol/muc#user",new MUCUserProvider());  
  97.         // MUC Admin  
  98.         pm.addIQProvider("query""http://jabber.org/protocol/muc#admin",new MUCAdminProvider());  
  99.         // MUC Owner  
  100.         pm.addIQProvider("query""http://jabber.org/protocol/muc#owner",new MUCOwnerProvider());  
  101.         // Delayed Delivery  
  102.         pm.addExtensionProvider("x""jabberdelay",new DelayInformationProvider());  
  103.         // Version  
  104.         try {  
  105.             pm.addIQProvider("query""jabber:iq:version",Class.forName("org.jivesoftware.smackx.packet.Version"));  
  106.         } catch (ClassNotFoundException e) {  
  107.             // Not sure what's happening here.  
  108.         }  
  109.         // VCard  
  110.         pm.addIQProvider("vCard""vcard-temp"new VCardProvider());  
  111.         // Offline Message Requests  
  112.         pm.addIQProvider("offline""http://jabber.org/protocol/offline",new OfflineMessageRequest.Provider());  
  113.         // Offline Message Indicator  
  114.         pm.addExtensionProvider("offline","http://jabber.org/protocol/offline",new OfflineMessageInfo.Provider());  
  115.         // Last Activity  
  116.         pm.addIQProvider("query""jabber:iq:last"new LastActivity.Provider());  
  117.         // User Search  
  118.         pm.addIQProvider("query""jabber:iq:search"new UserSearch.Provider());  
  119.         // SharedGroupsInfo  
  120.         pm.addIQProvider("sharedgroup","http://www.jivesoftware.org/protocol/sharedgroup",new SharedGroupsInfo.Provider());  
  121.         // JEP-33: Extended Stanza Addressing  
  122.         pm.addExtensionProvider("addresses","http://jabber.org/protocol/address",new MultipleAddressesProvider());  
  123.         pm.addIQProvider("si""http://jabber.org/protocol/si",new StreamInitiationProvider());  
  124.         pm.addIQProvider("query""jabber:iq:privacy"new PrivacyProvider());  
  125.         pm.addIQProvider("command""http://jabber.org/protocol/commands",new AdHocCommandDataProvider());  
  126.         pm.addExtensionProvider("malformed-action","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.MalformedActionError());  
  127.         pm.addExtensionProvider("bad-locale","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.BadLocaleError());  
  128.         pm.addExtensionProvider("bad-payload","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.BadPayloadError());  
  129.         pm.addExtensionProvider("bad-sessionid","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.BadSessionIDError());  
  130.         pm.addExtensionProvider("session-expired","http://jabber.org/protocol/commands",new AdHocCommandDataProvider.SessionExpiredError());  
  131.     }  
  132. }  


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


[java] view plaincopy
  1. public class MessageService extends Service {  
  2.   
  3.     private LogUtil log = LogUtil.getLogger();  
  4.     private ChatManager cm;  
  5.     private OfflineMessageManager offlineManager;  
  6.     public static XMPPConnection con = null;  
  7.   
  8.     static{     
  9.         try{    
  10.            Class.forName("org.jivesoftware.smack.ReconnectionManager");    
  11.         }catch(Exception e){    
  12.             e.printStackTrace();    
  13.         }    
  14.     }    
  15.     @Override  
  16.     public IBinder onBind(Intent arg0) {  
  17.         return null;  
  18.     }  
  19.   
  20.     @Override  
  21.     public void onCreate() {  
  22.         super.onCreate();  
  23.     }  
  24.   
  25.     @SuppressWarnings("deprecation")  
  26.     @Override  
  27.     public void onStart(Intent intent, int startId) {  
  28.         super.onStart(intent, startId);  
  29.         new Thread(new Runnable() {  
  30.   
  31.             @Override  
  32.             public void run() {  
  33.                 if(NetWorkUtil.netState(MessageService.this)!=false) {  
  34.                     con = XmppConnManager.getInstance().getConnection();  
  35.                     con.addConnectionListener(new ConnectionListener(){  
  36.   
  37.                         @Override  
  38.                         public void connectionClosed() {  
  39.                             log.e("来自连接监听,conn正常关闭");  
  40.                         }  
  41.                         @Override  
  42.                         public void connectionClosedOnError(Exception arg0) {  
  43.                              //这里就是网络不正常或者被挤掉断线激发的事件  
  44.                             if(arg0.getMessage().contains("conflict")){ //被挤掉线  
  45.                 /*              log.e("来自连接监听,conn非正常关闭"); 
  46.                                 log.e("非正常关闭异常:"+arg0.getMessage()); 
  47.                                 log.e(con.isConnected());*/  
  48.                             //关闭连接,由于是被人挤下线,可能是用户自己,所以关闭连接,让用户重新登录是一个比较好的选择                             
  49.                             XmppConnManager.getInstance().closeConnection();  
  50.                             //接下来你可以通过发送一个广播,提示用户被挤下线,重连很简单,就是重新登录  
  51.                             }else if(arg0.getMessage().contains("Connection timed out")){//连接超时  
  52.                                 // 不做任何操作,会实现自动重连  
  53.                             }  
  54.                         }  
  55.                         @Override  
  56.                         public void reconnectingIn(int arg0) {  
  57.                              //重新连接的动作正在进行的动作,里面的参数arg0是一个倒计时的数字,如果连接失败的次数增多,数字会越来越大,开始的时候是9  
  58.                             log.e("来自连接监听,conn重连中..."+arg0);  
  59.                         }  
  60.   
  61.                         @Override  
  62.                         public void reconnectionFailed(Exception arg0) {  
  63.                              //重新连接失败  
  64.                             log.e("来自连接监听,conn失败:"+arg0.getMessage());  
  65.                         }  
  66.                         @Override  
  67.                         public void reconnectionSuccessful() {  
  68.                             //当网络断线了,重新连接上服务器触发的事件  
  69.                             log.e("来自连接监听,conn重连成功");  
  70.                         }  
  71.   
  72.                     });  
  73.   
  74.   
  75.   
  76.   
  77.         }).start();  
  78.     }  
  79.   
  80.   
  81.     @Override  
  82.     public int onStartCommand(Intent intent, int flags, int startId) {  
  83.         // TODO Auto-generated method stub  
  84.         return super.onStartCommand(intent, flags, startId);  
  85.     }  
  86.   
  87. }  

0 0