項目中遇到要用xmpp做通訊,原來在的應用跑在linux上用的gloox,現(xiàn)在需要在android上來實現(xiàn),查了下發(fā)現(xiàn)smack最近做了一次大升級,4.0.0發(fā)布了,最開始用了smack的庫,結果在android上報錯,去https://community.igniterealtime.org/ 社區(qū)問了下,原來還有個asmack,下了庫文件然后寫代碼:
創(chuàng)新互聯(lián)公司于2013年成立,是專業(yè)互聯(lián)網(wǎng)技術服務公司,擁有項目成都網(wǎng)站建設、網(wǎng)站設計網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元太白做網(wǎng)站,已為上家服務,為太白各地企業(yè)和個人服務,聯(lián)系電話:13518219792
根據(jù)asmack-android-8-4.0.0-rc2.jar 的readme,另外需要DNSjava的庫,我用的是dnsjava-2.1.6
最開始發(fā)現(xiàn)logcat有一個關于dns的報錯,網(wǎng)上查了下發(fā)現(xiàn)有說要加下面一句在初始化的時候:
//System.setProperty("sun.net.spi.nameservice.provider.1","dns,dnsjava");
但是后來我發(fā)現(xiàn)沒有這句,好像也沒問題,暫時屏蔽掉了。
asmack的初始化是必須的。
mSmackAndroid = SmackAndroid.init(context);
conf = new ConnectionConfiguration( "wooxonline.com",5222);
SASLAuthentication.supportSASLMechanism("PLAIN",0);
conf.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
conf.setCompressionEnabled(false);
// disable the built-in ReconnectionManager since we handle this
conf.setReconnectionAllowed(false);
conf.setSendPresence(false);
conf.setDebuggerEnabled(true);
XMPPConnection connection = XMPPTCPConnection(conf);
connection.login(g_email, g_password);
最開始少了sasl方式的設置,發(fā)現(xiàn)連接沒問題,但是login的時候總是返回noresponse error,查了發(fā)現(xiàn)asmask對于連接出錯拋的異常比較簡單,不會細分。
log如下:
connect:
06-17 09:39:09.300 19344-19457/com.wooxclound.homedaemonactivity.app D/SMACK﹕ SENT (0):
06-17 09:39:12.500 19344-19458/com.wooxclound.homedaemonactivity.app D/SMACK﹕ RCV (0):
login:
06-17 09:39:21.500 19344-19457/com.wooxclound.homedaemonactivity.app D/SMACK﹕ SENT (0):
06-17 09:39:21.500 19344-19344/com.wooxclound.homedaemonactivity.app I/Woox HomeDaemon﹕ onStartCommand(): Intent com.wooxclound.homedaemon.action.XMPP.CONNECTION_CHANGED
06-17 09:39:22.090 19344-19458/com.wooxclound.homedaemonactivity.app D/SMACK﹕ RCV (0):
06-17 09:39:22.100 19344-19458/com.wooxclound.homedaemonactivity.app D/SMACK﹕ SENT (0):
06-17 09:39:22.490 19344-19458/com.wooxclound.homedaemonactivity.app D/SMACK﹕ RCV (0):
06-17 09:39:22.540 19344-19346/com.wooxclound.homedaemonactivity.app D/dalvikvm﹕ GC_CONCURRENT freed 311K, 8% free 5028K/5408K, paused 4ms+3ms, total 26ms
06-17 09:39:22.560 19344-19457/com.wooxclound.homedaemonactivity.app D/SMACK﹕ SENT (0):
06-17 09:39:23.130 19344-19458/com.wooxclound.homedaemonactivity.app D/SMACK﹕ RCV (0):
06-17 09:39:23.130 19344-19457/com.wooxclound.homedaemonactivity.app D/SMACK﹕ SENT (0):
06-17 09:39:23.720 19344-19458/com.wooxclound.homedaemonactivity.app D/SMACK﹕ RCV (0):
06-17 09:39:23.730 19344-19454/com.wooxclound.homedaemonactivity.app D/SMACK﹕ User logged (0): test11@wooxonline.com@wooxonline.com:0/Smack
在注冊新用戶的時候,可以使用accountmanager也可以使用IQ package,方法如下:
public static final int REGISTER_METHOD_ACCOUNT_MANAGER = 0;
public static final int REGISTER_METHOD_IQ_PACKAGE = 1;
public static final int REGISTER_RESULT_SERVER_NO_RESULT = 0;
public static final int REGISTER_RESULT_SUCCESS = 1;
public static final int REGISTER_RESULT_ACCOUNT_EXIST = 2;
public static final int REGISTER_RESULT_FAIL = 4;
public static final int REGISTER_RESULT_NO_CONNECTION = 4;
/**
* register
*
* @param username
* @param password
* @return 1:success 0:server not return 2:account exist 3:fail 4:no connection
*/
public int register(String username, String password) {
if (!((mConnection != null) && mConnection.isConnected())) {
return REGISTER_RESULT_NO_CONNECTION;
} else {
reg_method = REGISTER_METHOD_ACCOUNT_MANAGER;
Map
attributes.put("username", username);
attributes.put("password", password);
//attributes.put("email", "");
//attributes.put("name", "");
if (reg_method == REGISTER_METHOD_ACCOUNT_MANAGER) {
try {
if (mAccountManager == null) {
mAccountManager = AccountManager.getInstance(mConnection);
}
mAccountManager.createAccount(username, password, attributes);
} catch (Exception ex) {
L.e(TAG, ex);
if (ex.toString().equalsIgnoreCase("conflict")) {
L.i(XmppManager.class, " account exist!");
return REGISTER_RESULT_ACCOUNT_EXIST;
} else {
L.i(XmppManager.class, " register fail");
return REGISTER_RESULT_FAIL;
}
}
L.i(XmppManager.class, " register success!");
return REGISTER_RESULT_SUCCESS;
} else if (reg_method == REGISTER_METHOD_IQ_PACKAGE) {
try {
Registration reg = new Registration();
reg.setType(IQ.Type.SET);
reg.setTo(mConnection.getServiceName());
reg.setAttributes(attributes);
PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()),
new PacketTypeFilter(IQ.class));
PacketCollector collector = mConnection.createPacketCollector(filter);
mConnection.sendPacket(reg);
IQ result = (IQ) collector.nextResult(SmackConfiguration.getDefaultPacketReplyTimeout());
collector.cancel();
//System.out.println(result);
if (result == null) {
L.i(XmppManager.class, " no value return by server!");
return REGISTER_RESULT_SERVER_NO_RESULT;
} else if (result.getType() == IQ.Type.ERROR) {
//
if (result.getError().toString().equalsIgnoreCase("conflict")) {
L.i(XmppManager.class, " account exist!");
return REGISTER_RESULT_ACCOUNT_EXIST;
} else {
L.i(XmppManager.class, " register fail");
return REGISTER_RESULT_FAIL;
}
} else if (result.getType() == IQ.Type.RESULT) {
L.i(XmppManager.class, " register success!");
//Intent intent = new Intent(DaemonService.ACTION_REGISTER);
return REGISTER_RESULT_SUCCESS;
}
L.e(TAG, ":Should not go there for register process!");
} catch (Exception ex) {
L.e(TAG, ex);
}
}
L.e(TAG, ":Should not go there for register process!");
return REGISTER_RESULT_FAIL;
}
}
}
當賬戶存在時,返回如下包:
D/SMACK﹕ RCV (0):
但是geterrorcode()接口似乎在4.0的asmack中被去掉了,所以只能判定error是conflict就認為是賬戶已經(jīng)存在。
由于服務器強制使用TLS認證,所以對于連接做了新的配置,然后再openfire server上測試沒有問題,但是在公司的服務器出問題了,最先我用的是asmak 4.0.0 rc2的庫,在認證challenge的時候服務器似乎沒有響應,log如下:
D/SMACK﹕ SENT (0):
D/SMACK﹕ RCV (0):
D/SMACK﹕ SENT (0):
D/SMACK﹕ RCV (0):
W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:501)
W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:648)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader.parsePackets(PacketReader.java:223)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader.access$000(PacketReader.java:48)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader$1.run(PacketReader.java:82)
W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:501)
W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:648)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader.parsePackets(PacketReader.java:223)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader.access$000(PacketReader.java:48)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader$1.run(PacketReader.java:82)
D/SMACK﹕ SENT (0):
D/SMACK﹕ RCV (0):
D/SMACK﹕ RCV (0):
D/SMACK﹕ SENT (0):
D/SMACK﹕ RCV (0):
D/SMACK﹕ SENT (0):
W/XMPPConnection﹕ Connection closed with error
java.lang.NullPointerException
at com.novell.sasl.client.DigestMD5SaslClient.DigestCalcHA1(DigestMD5SaslClient.java:447)
at com.novell.sasl.client.DigestMD5SaslClient.createDigestResponse(DigestMD5SaslClient.java:646)
at com.novell.sasl.client.DigestMD5SaslClient.evaluateChallenge(DigestMD5SaslClient.java:356)
at org.jivesoftware.smack.sasl.SASLMechanism.challengeReceived(SASLMechanism.java:190)
at org.jivesoftware.smack.SASLAuthentication.challengeReceived(SASLAuthentication.java:427)
at org.jivesoftware.smack.tcp.PacketReader.parsePackets(PacketReader.java:252)
at org.jivesoftware.smack.tcp.PacketReader.access$000(PacketReader.java:48)
at org.jivesoftware.smack.tcp.PacketReader$1.run(PacketReader.java:82)
翻了一下asmack社區(qū)的帖子https://community.igniterealtime.org/message/240015#240015上說rc3的庫解決了這個問題,down下來一試,果然,但是認證還是通不過:
D/SMACK﹕ SENT (0):
D/SMACK﹕ RCV (0):
D/SMACK﹕ SENT (0):
D/SMACK﹕ RCV (0):
W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:501)
W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:648)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader.parsePackets(PacketReader.java:223)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader.access$000(PacketReader.java:48)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader$1.run(PacketReader.java:82)
W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnection.java:501)
W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnection.java:648)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader.parsePackets(PacketReader.java:223)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader.access$000(PacketReader.java:48)
W/System.err﹕ at org.jivesoftware.smack.tcp.PacketReader$1.run(PacketReader.java:82)
D/SMACK﹕ SENT (0):
D/SMACK﹕ RCV (0):
D/SMACK﹕ RCV (0):
D/SMACK﹕ SENT (0):
D/SMACK﹕ RCV (0):
D/SMACK﹕ SENT (0):
D/SMACK﹕ RCV (0):
D/SMACK﹕ SENT (1):
D/SMACK﹕ RCV (1):
D/SMACK﹕ SENT (1):
D/SMACK﹕ RCV (1):
D/SMACK﹕ SENT (1):
D/SMACK﹕ RCV (1):
D/SMACK﹕ RCV (1):
D/SMACK﹕ SENT (1):
D/SMACK﹕ RCV (1):
D/SMACK﹕ SENT (1):
D/SMACK﹕ RCV (1):
繼續(xù)翻壇子,https://code.google.com/p/gtalksms/issues/detail?id=262有人發(fā)現(xiàn)登陸ID不使用@域名就沒有問題,太暈了。
程序跑起來以后,使用xmpp客戶端聊天消息接收沒問題,但是通過CGI網(wǎng)頁pass過來的信息接收不到,初步認為應該是packetfilter的配置不對引起的。
先抓包:
From HTML page:
D/SMACK﹕ RCV (0):
From XMPP client:
D/SMACK﹕ RCV (0):
但是從http://xmpp.org/extensions/xep-0201.html xmpp協(xié)議上來看似乎,所有的message都應該有type和thread段。
最后將filter的配置改了一下,就能抓到了。
//PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class));