asmack登录冲突(多端登录冲突)处理 博客分类: android
功能:登录冲突;
效果:弹出对话框,您的账号在xxx设备登录,您已下载;
实现步骤:
asmack给我们提拱了一整套连接错误方案,其中就包括了登录冲突;
开始的时候,我还自己去写了一个,原理是上线的时候发送一个自定义的packet出去告诉登陆上的那个用户下线,后来发现这个方法行不通,因为另一端已经下线了,根本拿不到这条消息。
后来我想会不会在ConnectionListener里面就有呢?之前我实现登录的时候密码错误用的是捕获登录失败的时候抛出来的异常,所以这次变聪明了,首先从带异常的方法入手;找到以下两个方法:
public void connectionClosedOnError(Exception e)
public void reconnectionFailed(Exception e)
然后我知道异常都封装在exception,要获取到消息,只要从这些异常对象里面取就行了。因为是xmpp相关的异常,所以肯定是属于XMPPException;于是我把光标停留在这个类,出现如下提示:
org.jivesoftware.smack.XMPPException A generic exception that is thrown when an error occurs performing an XMPP operation. XMPP servers can respond to error conditions with an error code and textual description of the problem, which are encapsulated in the XMPPError class. When appropriate, an XMPPError instance is attached instances of this exception. When a stream error occured, the server will send a stream error to the client before closing the connection. Stream errors are unrecoverable errors. When a stream error is sent to the client an XMPPException will be thrown containing the StreamError sent by the server. Author: Matt Tucker See Also: XMPPError
最后面有个,同看XMPPError,于是我又把光标停在XMPPError,出现了如下信息:
org.jivesoftware.smack.packet.XMPPError Represents a XMPP error sub-packet. Typically, a server responds to a request that has problems by sending the packet back and including an error packet. Each error has a code, type, error condition as well as as an optional text explanation. Typical errors are: -------------------------------------------------------------------------------- Code XMPP Error Type 500 interna-server-error WAIT 403 forbidden AUTH 400bad-request MODIFY > 404 item-not-found CANCEL 409 conflict CANCEL 501 feature-not-implemented CANCEL 302 gone MODIFY 400 jid-malformed MODIFY 406 no-acceptable MODIFY 405 not-allowed CANCEL 401 not-authorized AUTH 402 payment-required AUTH 404 recipient-unavailable WAIT 302 redirect MODIFY 407 registration-required AUTH 404 remote-server-not-found CANCEL 504 remote-server-timeout WAIT 502 remote-server-error CANCEL 500 resource-constraint WAIT 503 service-unavailable CANCEL 407 subscription-required AUTH 500 undefined-condition WAIT 400 unexpected-condition WAIT 408 request-timeout CANCEL Author: Matt Tucker
发现了有登录冲突的错误代码,然后我加进去这么一段:
@Override public void reconnectionFailed(Exception e) { if (!PubUtil.volidateNet(mContext)) return; if (e instanceof XMPPException) { XMPPException xe = (XMPPException) e; final XMPPError error = xe.getXMPPError(); int errorCode = 0; if (error != null) { errorCode = error.getCode();// larosn 0930 Log.v("IMXmppManager", "连接断开,错误码" + errorCode); if (errorCode == 409) {// 被踢下线 mContext.sendBroadcast(new Intent( IMPubConstant.ACTION_LOGIN_CONFLICT)); } else if (errorCode == 502) {// 与远程服务器断开 } } }else reconnectionBrodcat(true); }
然而并没啥用,这时候我就把希望放在了剩下的connectionClosedOnError方法中,同时配合xmpp协议看到了登录冲突的时候服务器是返回这个StreamError节点的xml流,我跟踪进去找到了StreamError是org.jivesoftware.smack.packet.StreamError包下的,开始我以为StreamError也是packet,计划用监听packet的方式捕获到这个异常;点击进去源码我傻眼了,这个StreamError不是packet的子类;然后我把目标转向了XMPPException,果然在XMPPException下有这个方法:xe.getStreamError();,这就获取到StreamError了,然后在他下面有errorCode,不过这个是字符串方式,我对比了协议,写了这么一段,然后,it works!
if (e instanceof XMPPException) { XMPPException xe = (XMPPException) e; final StreamError error = xe.getStreamError(); String errorCode = ""; if (error != null) { errorCode = error.getCode();// larosn 0930 Log.v("IMXmppManager", "连接断开,错误码" + errorCode); if (errorCode.equalsIgnoreCase("conflict")) {// 被踢下线 mContext.sendBroadcast(new Intent( IMPubConstant.ACTION_LOGIN_CONFLICT)); return; } }
好了,登录冲突的实现就这样完成了。有啥疑问可以在下面提问。尊重作者的劳动成果,装载请注明出处,谢谢;