我在我的 Android 应用程序中使用 aSmack 与我的 XMPP 服务器通信,并且我打开了 Smack 的调试,这样我就可以看到所有 XML 的来/去。我的问题是我正在使用 PacketListener 来获取服务器对我发送的包的响应,但是当我调用 Packet 的 toXML() 方法时,我得到了一个奇怪的输出。
下面的课程和更多详细信息。
我的服务器有 XEP-0136 实现,由于 aSmack 还没有它的代码,所以我正在制作 IQ 数据包并发送它,这是按预期工作的,正如您在我的 XML 数据包下面看到的那样,如XEP-0136,检索集合列表(http://xmpp.org/extensions/xep-0136.html#manage-list)
xml包发送到服务器
06-13 14:11:21.769: D/SMACK(3018): 02:11:21 PM SENT (1079273464):
<iq id="john@company.com/Smack/Conversations" type="get">
<list with="john@company.com" xmlns="urn:xmpp:archive">
<set xmlns="http://jabber.org/protocol/rsm">
<max>30</max>
</set>
</list>
</iq>
为了创建这个 XML,我得到了 XEP-0136 中设计的 XML Schema 文件,并在 SimpleXML lib 的帮助下映射了所有元素,这是我用来创建和发送包的代码:
XMPPService.java
private static final int MAX_LIST = 30;
public void getConversations(String email, BaseActivity activity)
{
if (isAuthenticated())
{
String packetId = connection.getUser() + "/Conversations";
Set set = new Set();
set.setMax(MAX_LIST);
List list = new List();
list.setWith(email);
list.setSet(set);
final IQ iq = new IQ();
iq.setList(list);
iq.setType(IQType.get);
iq.setId(packetId);
PacketIDFilter filter = new PacketIDFilter(packetId);
connection.addPacketListener(new ChatListListener(activity), filter);
sendPacket(iq);
}
}
public void sendPacket(IQ iq)
{
if (isAuthenticated())
{
connection.sendPacket(new IQPacket(iq));
}
}
IQPacket.java
public class IQPacket extends Packet {
private IQ iq;
public IQPacket(IQ iq)
{
this.iq = iq;
}
public IQPacket(Packet packet, IQ iq)
{
super(packet);
this.iq = iq;
}
@Override
public String toXML()
{
StringWriter writer = new StringWriter();
Serializer serializer = new Persister();
try
{
serializer.write(iq, writer);
return writer.getBuffer().toString();
} catch (Exception e)
{
Log.e("COMPANY", "Error serializing xml", e);
}
return null;
}
}
正如我所说,这部分有效,我的问题是监听器,当我为收到的包调用 toXML() 方法时,我无法获得有关聊天的重要信息,但是 Smack 调试输出向我打印所有我期待的信息如下所示:
接收到的 XML 的 Smack 调试
06-13 14:11:21.989: D/SMACK(3018): 02:11:21 PM RCV (1079273464):
<iq type="result" id="john@company.com/Smack/Conversations" to="john@company.com/Smack">
<list xmlns="urn:xmpp:archive">
<chat with="anotheruser@company.com" start="2013-06-10T13:19:25.000Z"/>
<chat with="yetanotheruser@company.com" start="2013-06-10T13:36:50.876Z"/>
<set xmlns="http://jabber.org/protocol/rsm">
<first index="0">2</first>
<last>3</last>
<count>9</count>
</set>
</list>
</iq>
这个 XML 也是预期的答案,因为我将所有这些元素都映射为 JavaBeans,但这是我在 ChatListener 上收到 Packet 并调用 toXML() 方法时得到的结果:
06-13 14:11:22.009: I/System.out(3018):
<iq id="john@company.com/Smack/Conversations" to="john@company.com/Smack" type="result">nullnullnullnullnullnull2nullnull3nullnull9nullnull</iq>
ChatListListener.java
public class ChatListListener implements PacketListener {
private BaseActivity activity;
public ChatListListener(BaseActivity activity)
{
this.activity = activity;
}
@Override
public void processPacket(Packet packet)
{
activity.notifyPacketReceived();
System.out.println(packet.toXML());
}
}
Packet来自 org.jivesoftware.smack.packet.Packet,所以它是来自 aSmack 库的默认 Packet 。
所以我的问题是,我与 Smack 调试器有何不同?我查看了它的代码,我看到它还从数据包中调用 toXML() 方法并添加一个 ReceiveListener。我的想法是在调用 toXML() 之后,我可以使用 SimpleXML 将其转换为我映射的 IQ.java 并开始使用它的信息。
编辑
添加更多信息。因此,在查找 Smack 代码以及它如何处理收到的包之后,我发现也许我应该使用 IQProvider。所以我注册了我的 IQProvider
ProviderManager.getInstance().addIQProvider("list", "urn:xmpp:archive", new ListIQProvider());
之后,我在我的 IQProvider 的方法parseIQ(XmlPullParser arg0)上设置了一个断点,并且包实际上正在发送到我的提供者,但它仍然包含所有这些 null 元素。我现在有点迷茫,因为我需要它来继续工作,我将继续研究 Smack 源代码。