Smack是XMPP协议的的实现库,Smack库易于使用,仅仅几行代码就能实现客户端连接,登陆,发送即时消息。但是由于使用XMPP协议,所以不适合用在高并发的场合。
而且值得注意的是:Android网络连接需要在子线程中进行。
如果运行在PC端则不需要以上要求。也可以设置监听连接的状态
connection.addConnectionListener(newConnectionListener() { @Override public void connected(XMPPConnection connection) { //已连接上服务器 } @Override public void authenticated(XMPPConnection connection, boolean resumed) { //已认证 } @Override public void connectionClosed() { //连接已关闭 } @Override public void connectionClosedOnError(Exception e) { //关闭连接发生错误 } @Override public void reconnectionSuccessful() { //重连成功 } @Override public void reconnectingIn(int seconds) { //重连中 } @Override public void reconnectionFailed(Exception e) { //重连失败 } });发送消息也可以添加消息体!比如加个字体颜色字段
Message msg=new Message(); msg.setBody("你好啊");//消息主体 msg.addBody("textColor","#f00");//字体颜色字段 chat.sendMessage(msg);//发送一个文本消息应用场景:当我们想扩展自己聊天软件的功能的时候,就会用到自定义数据包。比如,实现匹配陌生人聊天,与服务进行通信等。
在Smack中,要想发送IQ包。先写一个类,然后继承IQ类,然后重写getIQChildElementBuilder方法,在这个方法里拼接我们的IQ包。
比如:
@Override protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { //TODO Auto-generated method stub xml.xmlnsAttribute("match:info");//设置xml的命名空间 xml.attribute("type","iq");//设置字段 xml.rightAngleBracket();//插入一个“>” xml.element("data","其他数据");//插入一个节点<data>其他数据</data> //注意!这里不要调用closeEmptyElement //xml.closeEmptyElement(); returnxml; }然后就可以发送了,比如我们刚才创建的继承IQ类的类是NonChatMsgIQ:
NonChatMsgIQ msg=new NonChatMsgIQ("info");//设置iq节点的子节点的名称 msg.setFrom(connection.getUser());//设置包的来源 msg.setTo("openfire/MatchUserPlugin");//设置包发送的去处 connection.sendStanza(msg);//发送msg.setTo("openfire/MatchUserPlugin");中的openfire/MatchUserPlugin,openfire是指服务器的名称,MatchUserPlugin是插件的名称,如果要发送IQ包到openfire的某个插件,请遵循这个规则。而不要写成主机地址!
在服务端我们也可能自定义IQ包,然后发给客户端,或者客户端与客户端之间相互发包。所以来看一下怎么接收发来的自定义的IQ包。(IQ是Stanza子类,在文中看到Stanza不要奇怪。)
首先设置过滤器和监听器。
StanzaFilter filter =new AndFilter( new StanzaTypeFilter(NonChatMsgIQ.class) ,new ToFilter(connection.getUser()));//配置过滤器 connection.addSyncStanzaListener(stanzaListener,filter);//设置监听器 private StanzaListener stanzaListener=new StanzaListener() { @Override public void processPacket(Stanza packet) { // TODO Auto-generated method stub //在这里就可以处理出去和进来的数据包 } };过滤器有这几种:
StanzaIdFilter
根据包的ID过滤
StanzaTypeFilter
根据包的类型过滤
AndFilter
按逻辑”并”过滤
OrFilter
按逻辑”或”过滤
NotFilter
按逻辑“非”过滤
ToFilter
按包的发送方向过滤
FromMatchesFilter
按包的来源过滤
设置IQProvider,IQProvider指定怎么解析你的自定义IQ类,不指定IQProvider,就会导致过滤包时发生错误,因为Smack不知道该如何解析你的IQ包。
首先编写一个类,该类继承自IQProvider,然后重写parse方法。这个方法返回一个IQ,组装好后直接返回即可。
@Override public NonChatMsgIQ parse(XmlPullParser parser, int initialDepth) throwsXmlPullParserException, IOException, SmackException { //TODO Auto-generated method stub NonChatMsgIQ msg=new NonChatMsgIQ("info"); msg.setMsgType(parser.getAttributeValue(0)); return msg; }类编写完毕,就往ProviderManager里添加我们的IQProvider。
ProviderManager.addIQProvider("info","match:info", new NonChatMsgIQProvider());作为即时聊天软件,短线重连太重要了。在Smack设置断线重连也很简单。
ReconnectionManager reconnectionManager=ReconnectionManager.getInstanceFor(connection); reconnectionManager.enableAutomaticReconnection();
在Smack中传输文件很简单,接收文件的一端调用addFileTransferListener方法添加文件文件接收事件,发送文件的一端调用sendFile或者sendStream方法发送文件。而且两端不需要提前成为好友。
发送文件:
FileTransferManager fileTransferManager= FileTransferManager.getInstanceFor(connection); OutgoingFileTransfer outgoingFileTransfer=fileTransferManager.createOutgoingFileTransfer(userId); outgoingFileTransfer.sendFile(fileName,"");
接收文件:
FileTransferManager fileTransferManager= FileTransferManager.getInstanceFor(connection); fileTransferManager.addFileTransferListener(new FileTransferListener() { @Override public void fileTransferRequest(FileTransferRequest fileTransferRequest) { IncomingFileTransfer incomingFileTransfer= fileTransferRequest.accept(); InputStream in=incomingFileTransfer.recieveFile();//开始接收文件 String fileName=incomingFileTransfer. getFileName(); final String dir="/sdcard/fileRec"; FileOutputStream fileOutputStream=new FileOutputStream(dir+File.separator+fileName); byte[] buf=new byte[1024]; int len=-1; int cur=0; while ((len=in.read(buf))!=-1) { fileOutputStream.write(buf,0,len); fileOutputStream.flush(); cur+=len; } fileOutputStream.close(); } });
Smack使用简单,适合中小型聊天软件或者社区软件使用。更多内容可以去查看Smack官方文档,官方API文档。