先声明:我这里不分析源码,只介绍开发包的使用,欢迎大家交流
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(); } }