【发布时间】:2014-05-18 17:16:05
【问题描述】:
我正在使用 aSmack 和 Openfire。
经过大量研究,我发现 Openfire 不支持消息归档并安装了插件 OpenArchive。
现在存档工作正常,所有消息都可以正常存储。
现在在客户端,我尝试发送 IQ 节 来检索存档的聊天记录。
首先我添加了一个如下所示的 IQ Provider:
pm.addIQProvider("list", "urn:xmpp:archive", new ListIQProvider());
然后我用了:
final IQ iq = new IQ()
{
@Override public String getChildElementXML()
{
return "<list xmlns='urn:xmpp:archive' with='test@customOpenfire.com'><set xmlns='http://jabber.org/protocol/rsm'><max xmlns='http://jabber.org/protocol/rsm'>30</max></set> </list>";
}
};
iq.setType(IQ.Type.GET);
iq.setPacketID("987654321");
xmppConnection.sendPacket(iq);
效果很好,我收到了回复。
<iq id="987654321" to="admin@customOpenfire.com/Smack" type="result">
<list xmlns="urn:xmpp:archive">
<chat with="test@customOpenfire.com" start="2014-04-06T12:11:28.674Z"/>
<chat with="test@customOpenfire.com" start="2014-04-03T16:55:59.523Z"/>
<chat with="test@customOpenfire.com" start="2014-04-05T16:33:03.377Z"/>
<chat with="test@customOpenfire.com" start="2014-04-02T14:32:10.499Z"/>
<chat with="test@customOpenfire.com" start="2014-04-06T12:47:52.961Z"/>
<chat with="test@customOpenfire.com" start="2014-04-03T14:46:24.877Z"/>
<chat with="test@customOpenfire.com" start="2014-04-06T12:37:14.608Z"/>
<chat with="test@customOpenfire.com" start="2014-04-03T15:48:46.642Z"/>
<chat with="test@customOpenfire.com" start="2014-04-02T13:46:07.750Z"/>
<chat with="test@customOpenfire.com" start="2014-04-04T18:25:57.968Z"/>
<chat with="test@customOpenfire.com" start="2014-04-03T19:08:45.238Z"/>
<chat with="test@customOpenfire.com" start="2014-04-04T18:47:19.067Z"/>
<chat with="test@customOpenfire.com" start="2014-04-04T19:34:27.819Z"/>
<chat with="test@customOpenfire.com" start="2014-04-02T15:09:13.140Z"/>
<chat with="test@customOpenfire.com" start="2014-04-03T18:30:36.804Z"/>
<chat with="test@customOpenfire.com" start="2014-04-05T14:09:34.973Z"/>
<chat with="test@customOpenfire.com" start="2014-04-04T22:47:54.363Z"/>
<chat with="test@customOpenfire.com" start="2014-04-02T15:32:44.540Z"/>
<chat with="test@customOpenfire.com" start="2014-04-03T17:18:37.940Z"/>
<chat with="test@customOpenfire.com" start="2014-04-03T13:37:15.630Z"/>
<chat with="test@customOpenfire.com" start="2014-04-04T17:10:39.116Z"/>
<set xmlns="http://jabber.org/protocol/rsm">
<first index="0">66</first>
<last>139</last>
<count>21</count>
</set>
</list>
</iq>
然后我想检索实际的消息,所以我发送了这个 IQ 节:
final IQ iq = new IQ()
{
@Override public String getChildElementXML()
{
return "<retrieve xmlns='urn:xmpp:archive' with='test@customOpenfire.com'><set xmlns='http://jabber.org/protocol/rsm'><max xmlns='http://jabber.org/protocol/rsm'>30</max></set> </retrieve>";
}
};
iq.setType(IQ.Type.GET);
iq.setPacketID("987654321");
xmppConnection.sendPacket(iq);
当然,在我创建自定义提供程序并将其添加如下之后:
pm.addIQProvider("retrieve", "urn:xmpp:archive", new ChatIQProvider());
我应该收到类似的东西:
<iq xmlns="jabber:client" type="result" id="hgfg" to="admin@customOpenfire.com/7dd0f2fc">
<chat xmlns="urn:xmpp:archive" with="test@customOpenfire.com" start="2014-04-02T13:46:07.750Z">
<from secs="0" jid="test@customOpenfire.com">
<body>hello</body>
</from>
<to secs="2">
<body>hey</body>
</to>
<from secs="5" jid="test@customOpenfire.com">
<body>test</body>
</from>
<set xmlns="http://jabber.org/protocol/rsm">
<first index="0">0</first>
<last>2</last>
<count>3</count>
</set>
</chat>
但在我的数据包侦听器中,结果不会被解析,并且会像我删除 ListIQProvider() 后的 list 节 一样被处理。
这是我的自定义类:
ChatIQ:
public class ChatIQ extends IQ {
private String xmlns;
private String with;
private String start;
private List<From> froms;
private Set set;
public ChatIQ()
{
this.froms = new ArrayList<ChatIQ.From>();
}
public String getXmlns()
{
return xmlns;
}
public void setXmlns(String xmlns)
{
this.xmlns = xmlns;
}
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 void addFrom(From from)
{
froms.add(from);
}
public List<From> getFroms()
{
return froms;
}
public Set getSet()
{
return set;
}
public void setSet(Set set)
{
this.set = set;
}
@Override
public String getChildElementXML()
{
StringBuilder builder = new StringBuilder("<chat xmlns=\"urn:xmpp:archive\"");
builder.append("with=\"").append(with).append("\"");
builder.append(" start=\"");
builder.append(start);
builder.append("\">");
for(From from : froms)
{
builder.append(from.toXml());
}
builder.append(set.toXml());
builder.append("</chat>");
return builder.toString();
}
public static class From
{
private String secs;
private String jid;
private Body body;
public String getSecs()
{
return secs;
}
public void setSecs(String secs)
{
this.secs = secs;
}
public String getJid()
{
return jid;
}
public void setJid(String jid)
{
this.jid = jid;
}
public Body getBody()
{
return body;
}
public void setBody(Body body)
{
this.body = body;
}
public String toXml()
{
StringBuilder builder = new StringBuilder("<from ");
builder.append("secs=\"").append(secs).append("\" ");
builder.append("jid=\"").append(jid).append("\" >");
builder.append(body.toXml());
builder.append("</from>");
return builder.toString();
}
}
public static class Body
{
private String message;
public Body(String message)
{
this.message = message;
}
public String getMessage()
{
return message;
}
public void setMessage(String message)
{
this.message = message;
}
public Object toXml()
{
StringBuilder builder = new StringBuilder("<body>");
builder.append(message);
builder.append("</body>");
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();
}
}
}
ChatIQProvider:
public class ChatIQProvider implements IQProvider {
public ChatIQProvider()
{
}
@Override
public IQ parseIQ(XmlPullParser parser) throws Exception
{
Log.d("CHAT IQ PROVIDER", String.format("Received iq packet, namespace[%s], name[%s]", parser.getNamespace(), parser.getName()));
ChatIQ iq = new ChatIQ();
ChatIQ.Set set = new Set();
boolean done = false;
From from = new From();
String secs = "", jid = "";
while (!done)
{
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG)
{
if (parser.getName().equals("from"))
{
secs = parser.getAttributeValue("", "secs");
jid = parser.getAttributeValue("", "jid");
from = new From();
iq.addFrom(from);
}
else if(parser.getName().equals("body") && from.getBody()==null)
{
ChatIQ.Body body = new Body(parser.nextText());
from.setBody(body);
}
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("chat"))
{
iq.setSet(set);
done = true;
}
}
}
return iq;
}
private int parseInt(String integer)
{
return Integer.parseInt((integer != null ? integer : "0"));
}
}
我的问题如下:
- 为什么我的自定义 IQProvider 无法识别?
- 我能否在不通过 IQproviders 的情况下获取接收到的 XML 并对其进行解析?
- 有没有更简单的方法可以从服务器检索归档消息?知道消息存在并且我确实在客户端收到它们,我只是找不到获取内容并解析它的方法。
谢谢。
【问题讨论】:
标签: android xmpp chat archive provider