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

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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值