gpt4 book ai didi

android - aSmack - 使用 Packet Listener 的 Packet to XML 输出可为空的元素

转载 作者:太空狗 更新时间:2023-10-29 16:41:25 27 4
gpt4 key购买 nike

我在我的 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 架构文件,并在 SimpleXML 库的帮助下映射了所有元素,这是我用来创建和发送包的代码:

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 上收到数据包并调用 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) 上放置了一个断点,并且包实际上被发送到我的提供者,但它仍然包含所有这些空元素。我现在有点迷茫,因为我需要它来继续工作,我会继续研究 Smack 源代码。

最佳答案

经过大量研究和查找 Smack 资源后,我找到了解决方案。步骤是,添加 IQProvider,为您的数据包添加一个 PacketListener,发送数据包。在您的 IQProvider 上等待数据包,解析它,并在您的监听器上获得响应。

所以 addIQProvideraddPacketListener 都是正确的,问题是,我需要对我的 ListIQProvider 上的 XML 进行完整的解析,这听起来很简单,但我花了很多时间花点时间弄清楚。

public class ListIQProvider implements IQProvider {

public ListIQProvider()
{
}

@Override
public IQ parseIQ(XmlPullParser parser) throws Exception
{
Logger.d(String.format("Received iq packet, namespace[%s], name[%s]", parser.getNamespace(), parser.getName()));
ListIQ iq = new ListIQ();
ListIQ.Set set = new Set();
boolean done = false;

String with = "", start = "";
while (!done)
{
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG)
{
if (parser.getName().equals("chat"))
{
with = parser.getAttributeValue("", "with");
start = parser.getAttributeValue("", "start");
iq.addChat(new Chat(with, start));
}
else if (parser.getName().equals("first"))
{
int index = parseInt(parser.getAttributeValue("", "index"));
set.setIndexAtt(index);
int first = parseInt(parser.nextText());
set.setFirst(first);
}
else if (parser.getName().equals("last"))
{
int last = parseInt(parser.nextText());
set.setLast(last);
}
else if (parser.getName().equals("count"))
{
int count = parseInt(parser.nextText());
set.setCount(count);
}
}
else if (eventType == XmlPullParser.END_TAG)
{
if (parser.getName().equals("list"))
{
iq.setSet(set);
done = true;
}
}
}

return iq;
}

private int parseInt(String integer)
{
return Integer.parseInt((integer != null ? integer : "0"));
}
}

之后,我在 ChatListListener 上要做的就是将 Packet 转换到我的 ListIQ 类。就是这样。这里的问题是,在我的 ChatListListener 上收到的 Packet 与在我的 上的 parseIQ 方法上返回的 Packet 相同ListIQProvider。所以在这个问题/答案中,我们几乎拥有 XEP-0136 所需的一切,或者至少开始使用它。由于我没有在网上找到任何好的和简单的资源来帮助我,我在这里分享我的。下面是 ListIQ 类:

public class ListIQ extends IQ {

private List<Chat> chats;

private Set set;

public ListIQ()
{
this.chats = new ArrayList<ListIQ.Chat>();
}

public Set getSet()
{
return set;
}

public void setSet(Set set)
{
this.set = set;
}

public void addChat(Chat chat)
{
chats.add(chat);
}

public List<Chat> getChats()
{
return chats;
}

@Override
public String getChildElementXML()
{
StringBuilder builder = new StringBuilder("<list xmlns=\"urn:xmpp:archive\">");
for (Chat chat : chats)
{
builder.append(chat.toXml());
}
builder.append(set.toXml());
builder.append("</list>");
return builder.toString();
}

public static class Chat {
private String with;
private String start;

public Chat()
{
}

public Chat(String with, String start)
{
this.with = with;
this.start = start;
}

public String getWith()
{
return with;
}

public void setWith(String with)
{
this.with = with;
}

public String getStart()
{
return start;
}

public void setStart(String start)
{
this.start = start;
}

public String toXml()
{
StringBuilder builder = new StringBuilder("<chat with=\"");
builder.append(with).append("\"");
builder.append(" start=\"");
builder.append(start);
builder.append("\"/>");
return builder.toString();
}

}

public static class Set {
private int last;
private int count;
private int indexAtt;
private int first;

public Set()
{
}

public int getLast()
{
return last;
}

public void setLast(int last)
{
this.last = last;
}

public int getCount()
{
return count;
}

public void setCount(int count)
{
this.count = count;
}

public int getIndexAtt()
{
return indexAtt;
}

public void setIndexAtt(int indexAtt)
{
this.indexAtt = indexAtt;
}

public int getFirst()
{
return first;
}

public void setFirst(int first)
{
this.first = first;
}

public String toXml()
{
StringBuilder builder = new StringBuilder("<set xmlns=\"http://jabber.org/protocol/rsm\">");
builder.append("<first index=\"").append(indexAtt).append("\">").append(first).append("</first>");
builder.append("<last>").append(last).append("</last>");
builder.append("<count>").append(count).append("</count>");
builder.append("</set>");
return builder.toString();
}
}

}

关于android - aSmack - 使用 Packet Listener 的 Packet to XML 输出可为空的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17088227/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com