- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在我的 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 上等待数据包,解析它,并在您的监听器上获得响应。
所以 addIQProvider 和 addPacketListener 都是正确的,问题是,我需要对我的 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/
我正在使用 Asmack API 在 android 上创建一个多用户聊天室,我想通过使用获取所有托管的房间 MultiUserChat.getHostedRooms(connection, serv
我正在基于 asmack 库在 Android 上开发聊天应用程序。我创建了 1 个用户并在好友列表中添加了 3 个 friend 。当我使用名册显示好友列表时。我无法在好友列表中获取所有用户,只有
我正在尝试为我的聊天应用程序实现离线文件扩展。我正在使用 PacketExtension 和 EmbeddedExtensionProvider 添加和解析自定义扩展。我可以看到在发送消息时添加了值和
基本上我有一个运行整个项目的主类。该代码运行良好,但一旦应用程序失去焦点,它就会变得不活动。我想知道我将如何让它成为一项服务。一个会在启动时启动的。 该应用程序将是一种用于通知的单向消息系统。即 De
我有一个 aSmack 实现的应用程序,(8-4.0.5),据我们所知,它有一个内部重新连接管理,但它并不令人满意,因为有时我们应该等待 5 分钟才能重新连接,而我们现在知道这是一个这样做的好时机,所
我正在我正在开发的 Android 应用程序中使用 asmack xmpp 客户端,并希望使用压缩。我找到了 setCompressionEnabled,但当我尝试它时,它告诉我我需要 smackx。
我正在使用 asmack 库,并面临多用户聊天请求的问题。 发送 session 请求时,它不会进入邀请监听器,尽管相同的代码在 java 中使用 smack 库。 调试时它显示我正在接收消息,但没有
我完全按照答案建议的操作( Asmack not loading VCard ),但它仍然不起作用。 DEBUG 输出显示 Smack 收到带有 VCard 信息的数据包,但随后在 https://g
我正在努力让 aSmack 在我的项目中发挥作用。在 eclipse 中创建一个标准项目,添加 jar 以构建路径/库。开始使用 XMPP 类,但我不确定我是否应该做其他事情来正确设置项目(稍后再说)
我正在开发 Android 平台上的聊天应用程序。我想通过 xmpp 库中的 PubSub 共享我的当前位置。谁能给我代码,说明如何使用 pubsub API。 提前致谢。 最佳答案 Smack do
我建立了一个基于 aSmack 的应用程序,显然所有关于连接的东西都在一个服务中运行,所以保持它的连接是非常重要的,因为我们知道在后台运行的服务可能会在手机资源不足时被杀死(通常是 Ram),因此在服
我在我的 android 应用程序中使用 aSmack 库进行群聊,我的问题是有时当连接丢失时,ReconnectionManager 无法重新连接并出现此错误: java.lang.IllegalT
我在通过 XMPP 发送图像时遇到了一个问题。下面是我完成的代码 fragment 。我不知道代码有什么问题。 Message msg = new Message(emailId, Message.T
我不熟悉 smack 库的使用和制作一个聊天应用程序。当我添加 friend 时,从这段代码..,它有效。 public void Addcontact() { Roster.setDefaul
我正在使用 Asmack 的二进制版本(我会尽快构建它,因为我第一次尝试时遇到了问题)。我还设置了自己的 ejabberd 服务器。 当我尝试加载一些联系人 VCard 时,服务器返回信息但 Asma
我尝试用 asmack 编写一个 android 演示。存在名为 “host-unknown” 的错误。我该如何解决? 这是我在 LogCat 中看到的: 03-16 08:31:10.671: I/
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
我遇到了 XML 节中缺少属性的问题。根据服务器端的日志文件,我可以确认属性是从客户端发送到服务器的。此外,当服务器将 XML 节传递给接收者时,该属性也存在(仍然基于服务器端的日志文件)。问题是,当
我无法使用 asmack 接收文件,但我能够发送文件。下面是接收文件的代码,请告诉我我做错了什么 ServiceDiscoveryManager serv= new Ser
我正在使用 openfire 和 asmack 库。我正在 android 聊天应用程序中实现在线 和离线 按钮。如何将我的在线状态设置为“不可用”。 注意:我不想使用connection.disco
我是一名优秀的程序员,十分优秀!