Smack 打印XMPP协议报文到日志文件(Android)

原创 2018年04月16日 17:30:33

Smack4.1.6+版本不确定是否可用(未实践,理论上应该没有问题),因Smack4.2.0版本改动较大
下载请前往https://download.csdn.net/download/w690333243/10352948
思路:参考Smack源码中SLF4JSmackDebugger
注:文章中所有 Log.debug的地方,均需要换成你自己的输出到文件的打印方式
在XMPPTCPConnectionConfiguration 配置configBuilder处(设置服务器地址,域名处)添加如下代码

configBuilder.setDebuggerEnabled(true);//开启Smack xmpp报文打印log
//SmackConfiguration.DEBUG = true;//暂时还不知道这是干嘛用的,之前看到有篇文章数,版本发布时要把SmackConfiguration.DEBUG 去掉,刚开始置位true是为了调试,小编没加这行代码,报文可以正常打印
SmackConfiguration.setDebuggerFactory(new XmppDebuggerFactory());//使用自己的log输出

一、XmppDebugger.java

import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ReconnectionManager;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.debugger.SmackDebugger;
import org.jivesoftware.smack.util.ObservableReader;
import org.jivesoftware.smack.util.ObservableWriter;
import org.jxmpp.util.XmppStringUtils;

import java.io.Reader;
import java.io.Writer;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Description:此类用于打印xmpp协议收发包信息
 */

public class XmppDebugger implements SmackDebugger
{
    public static final String LOGGER_NAME = "XMPP_SMACK";

    public static final AtomicBoolean printInterpreted = new AtomicBoolean(true);

    public static final String SENT_TAG = "SENT";
    public static final String RECEIVED_TAG = "RECV";

    private final XMPPConnection connection;

    private final StanzaListener receivedListener = new XmppLoggingPacketListener(RECEIVED_TAG);
    private final StanzaListener sentListener = new XmppLoggingPacketListener(SENT_TAG);
    private final XmppRawXmlListener XmppRawXmlListener = new XmppRawXmlListener();

    private ObservableWriter writer;
    private ObservableReader reader;

    /**
     * Makes Smack use this Debugger
     */
    public static void enable()
    {
        SmackConfiguration.setDebuggerFactory(new XmppDebuggerFactory());
    }

    /**
     * Create new Xmpp Smack Debugger instance
     *
     * @param connection
     *         Smack connection to debug
     * @param writer
     *         connection data writer to observe
     * @param reader
     *         connection data reader to observe
     */
    public XmppDebugger(XMPPConnection connection, Writer writer, Reader reader)
    {
        this.connection = connection;
        this.writer = new ObservableWriter(writer);
        this.writer.addWriterListener(XmppRawXmlListener);
        this.reader = new ObservableReader(Validate.notNull(reader));
        this.reader.addReaderListener(XmppRawXmlListener);
        this.connection.addConnectionListener(new XmppLoggingConnectionListener(connection));
    }

    @Override
    public Reader newConnectionReader(Reader newReader)
    {
        reader.removeReaderListener(XmppRawXmlListener);
        reader = new ObservableReader(newReader);
        reader.addReaderListener(XmppRawXmlListener);
        return reader;
    }

    @Override
    public Writer newConnectionWriter(Writer newWriter)
    {
        writer.removeWriterListener(XmppRawXmlListener);
        writer = new ObservableWriter(newWriter);
        writer.addWriterListener(XmppRawXmlListener);
        return writer;
    }

    @Override
    public void userHasLogged(String user)
    {
        String userTitle = getUserTitle(user);
        Log.debug(XmppDebugger.LOGGER_NAME, "userHasLogged User logged in connection.hashCode()=" + connection.hashCode() + " userTitle=" + userTitle);
    }

    private String getUserTitle(String user)
    {
        if (("@" + connection.getServiceName()).equals(XmppStringUtils.parseBareJid(user)))
        {
            return "<Anonymous>@" + connection.getServiceName();
        }
        else
        {
            return user;
        }
    }

    @Override
    public Reader getReader()
    {
        return reader;
    }

    @Override
    public Writer getWriter()
    {
        return writer;
    }

    @Override
    public StanzaListener getReaderListener()
    {
        return receivedListener;
    }

    @Override
    public StanzaListener getWriterListener()
    {
        return sentListener;
    }
}

二、Validate.java

/**
 * Description:此类用于
 */

/**
 * This is package-level helper class to validate dependencies while initialization is in progress
 */
final class Validate
{
    private Validate()
    { /* do not create instances */ }

    public static <T> T notNull(T instance)
    {
        return notNull(instance, null);
    }

    public static <T> T notNull(T instance, String message)
    {
        if (instance == null)
        {
            throw new NullPointerException(message);
        }
        else
        {
            return instance;
        }
    }
}

三、XmppDebuggerFactory.java

import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.debugger.SmackDebugger;
import org.jivesoftware.smack.debugger.SmackDebuggerFactory;

import java.io.Reader;
import java.io.Writer;

/**
 * Description:此类用于打印xmpp协议收发包信息
 */

public class XmppDebuggerFactory implements SmackDebuggerFactory
{
    @Override
    public SmackDebugger create(XMPPConnection connection, Writer writer, Reader reader) throws IllegalArgumentException {
        return new XmppDebugger(connection, writer, reader);
    }
}

四、XmppLoggingPacketListener.java

import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.packet.Stanza;

/**
 * Description:此类用于打印xmpp协议收发包信息
 */

public class XmppLoggingPacketListener implements StanzaListener
{
    private final String prefix;

    public XmppLoggingPacketListener(String prefix)
    {
        this.prefix = Validate.notNull(prefix);
    }

    public void processPacket(Stanza packet)
    {
        if (XmppDebugger.printInterpreted.get())
        {
            Log.debug(XmppDebugger.LOGGER_NAME, prefix + " " + packet.getClass().getName() + " " + packet.toXML());
        }
    }
}

五、XmppRawXmlListener.java

import org.jivesoftware.smack.util.ReaderListener;
import org.jivesoftware.smack.util.WriterListener;
import java.util.logging.Logger;

/**
 * Description:此类用于打印xmpp协议收发包信息
 */

public class XmppRawXmlListener implements ReaderListener, WriterListener
{

    XmppRawXmlListener()
    {
    }

    @Override
    public void read(String str)
    {
        Log.debug(XmppDebugger.LOGGER_NAME, XmppDebugger.RECEIVED_TAG + ": " + str);
    }

    @Override
    public void write(String str)
    {
        Log.debug(XmppDebugger.LOGGER_NAME, XmppDebugger.SENT_TAG + ": " + str);
    }
}

六、XmppLoggingConnectionListener.java

import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.XMPPConnection;

/**
 * Description:此类用于打印xmpp协议收发包信息
 */

public class XmppLoggingConnectionListener implements ConnectionListener
{
    private final XMPPConnection connection;

    public XmppLoggingConnectionListener(XMPPConnection connection)
    {
        this.connection = Validate.notNull(connection);
    }

    @Override
    public void connected(XMPPConnection connection)
    {
        Log.debug(XmppDebugger.LOGGER_NAME, "Connection connected: " + connection.hashCode());
    }

    @Override
    public void authenticated(XMPPConnection connection, boolean resumed)
    {
        Log.debug(XmppDebugger.LOGGER_NAME, "authenticated connection.getUser()=" + connection.getUser());
    }

    public void connectionClosed()
    {
        Log.debug(XmppDebugger.LOGGER_NAME, "connectionClosed");
    }

    public void connectionClosedOnError(Exception e)
    {
        Log.debug(XmppDebugger.LOGGER_NAME, "connectionClosedOnError e=" + e);
    }

    public void reconnectionFailed(Exception e)
    {
        Log.debug(XmppDebugger.LOGGER_NAME, "reconnectionFailed e=" + e);
    }

    public void reconnectionSuccessful()
    {
        Log.debug(XmppDebugger.LOGGER_NAME, "reconnectionSuccessful ");
    }

    public void reconnectingIn(int seconds)
    {
        Log.debug(XmppDebugger.LOGGER_NAME, "reconnectingIn " + seconds);
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/w690333243/article/details/79963639

Android studio使用smack连接xmpp服务器收发消息

我使用的是ejabberd16.09的linux版本,安装教程网上有很多,我在这里只介绍一下android端连接、登录和收发消息的方法。 ejabberd官网地址:点击打开链接     进入正题,我使...
  • l631768226
  • l631768226
  • 2016-10-25 15:58:03
  • 3810

Android 使用Smack+openfire开发基于XMPP协议的聊天

本文:openfire:4.0.1,Smack:4.1.6 OpenFire与Smack下载:http://www.igniterealtime.org/index.jsp SmackAPI:http...
  • muzhengjun
  • muzhengjun
  • 2016-04-13 15:35:26
  • 4157

Android的XMPP协议的smack开源框架

说到aSmack,自然要先提提Smack。Smack API是一个完整的实现了XMPP协议的开源API库,而aSmack则是Smack在Android上的构建版本,于2013年2月初迁移到 Git...
  • zhview
  • zhview
  • 2016-09-09 17:22:11
  • 930

XMPP的android获取所有联系人,创建会话,发送消息实现

下面就开始获取用户的联系人:当然返回的是一个List,然后显示到ListView上去,这个就不说了,配置一个adapter适配器就好了。 /** * 获得所有的联系人列表 * * @r...
  • jsjysxw
  • jsjysxw
  • 2015-08-22 21:20:26
  • 689

Android之基于XMPP协议即时通讯软件(三)

CSDN博客之星投票请移驾:http://vote.blog.csdn.net/blogstaritem/blogstar2013/weidi1989 本文主要介绍本应用的控制层具体实现...
  • weidi1989
  • weidi1989
  • 2013-12-22 23:55:18
  • 22052

XMPP之登录报文

刚把登录报文抓了分析,有很多报文,所以写了一小点报文 三次握手 C: S: C:TCP S:   PLAIN   ANONYMOUS   SCRAM-SHA-1   CRAM-MD5  ...
  • cainiaobegin
  • cainiaobegin
  • 2017-04-04 22:00:40
  • 397

Android基于XMPP Smack及Openfire学习笔记(1)

之前开发的项目中有用到IM聊天功能,但是这块功能公司有专门的IM团队来开发,由他们开发好后, 直接接入到我们APP中,我真正参与到IM开发的内容很少。现在抽项目相对比较闲的时间,自己来 一步步学习IM...
  • true100
  • true100
  • 2016-02-20 11:33:46
  • 2136

android客户端xmpp & smack & openfire简单开发实例

最近闲的蛋疼,研究了下xmpp即时通讯,有些许收获,拿出来跟大家分享一下吧,欢迎指点和讨论!废话不多说,开始搞事情。 步骤一:测试环境配置。 1.下载openfire服务器相关配置 下载链接:http...
  • u013086747
  • u013086747
  • 2017-07-17 10:00:25
  • 1182

利用smack实现基于XMPP协议的简单通信demo

XMPP+OPENFIRE+SMACK     首先需要安装即时通信服务器,这里使用开源的openfire 下载地址: http://www.igniterealtime.org/downl...
  • czjuttsw
  • czjuttsw
  • 2012-11-08 20:53:38
  • 7450

openfire,XMPP,smack,android下离线消息的接收

登录之后呢,先设置离线,不然是收不到离线消息的,处理完离线消息后(比如说保存到数据库),就可以设置为在线了 这里呢,创建一个离线消息工具类 /** * 离线信息管理类. */ public c...
  • jsjysxw
  • jsjysxw
  • 2015-08-22 22:05:24
  • 1790
收藏助手
不良信息举报
您举报文章:Smack 打印XMPP协议报文到日志文件(Android)
举报原因:
原因补充:

(最多只允许输入30个字)