先聲明:我這里不分析源碼,只介紹開發包的使用,歡迎大家交流
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(); } }