android - IQ Custom provider not recognized -
i using asmack openfire.
after lot of research found openfire doesn't support message archiving , installed plugin openarchive.
now archiving works fine , messages stored fine.
now in client side tried sending iq stanza retrieve archived chats.
first added iq provider below:
pm.addiqprovider("list", "urn:xmpp:archive", new listiqprovider());
then used:
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);
it worked fine , received response.
<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>
then wanted retrieve actual messages sent iq stanza:
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);
of course after created custom provider , added below:
pm.addiqprovider("retrieve", "urn:xmpp:archive", new chatiqprovider());
and should have received like:
<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>
but in packet listener result isn't parsed , treated list stanza treated if remove listiqprovider().
here custom classes:
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 : froms) { builder.append(from.toxml()); } builder.append(set.toxml()); builder.append("</chat>"); return builder.tostring(); } public static class { 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 = 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"); = 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")); } }
my questions follow:
- why isn't custom iqprovider recognized?
- can received xml , parse without going through iqproviders?
- is there simpler way retrieve archived messages server? knowing messages exist , receive them in client side can't find way content , parse it.
thank you.
i fixed issue, , forgot post answer here other people might have same problem. anyway fix pretty simple. instead of:
pm.addiqprovider("retrieve", "urn:xmpp:archive", new chatiqprovider());
i should've used:
pm.addiqprovider("chat", "urn:xmpp:archive", new chatiqprovider());
i have register name of child tag of iq response , not request, hence "chat" instead of "retrieve".
hope helps, not find examples on use of custom iq in android smack api.
since comment long added here.
here go:
listiqprovider:
public class listiqprovider implements iqprovider { public listiqprovider() { } @override public iq parseiq(xmlpullparser parser) throws exception { listiq iq = new listiq(); listiq.set set = new set(); boolean done = false; string = "", start = ""; while (!done) { int eventtype = parser.next(); if (eventtype == xmlpullparser.start_tag) { if (parser.getname().equals("chat")) { = 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")); }
}
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\">"); (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(); } } }
i use class, call serviceproviders.register_providers(providermanager.getinstance());
right after xmpp connection connected.
serviceproviders:
public class serviceproviders { public static void register_providers(providermanager pm) { log.e("provider", "start"); // private data storage pm.addiqprovider("query", "jabber:iq:private", new privatedatamanager.privatedataiqprovider()); // time try { pm.addiqprovider("query", "jabber:iq:time", class.forname("org.jivesoftware.smackx.packet.time")); } catch (classnotfoundexception e) { log.w("testclient", "can't load class org.jivesoftware.smackx.packet.time"); } // roster exchange pm.addextensionprovider("x", "jabber:x:roster", new rosterexchangeprovider()); // message events pm.addextensionprovider("x", "jabber:x:event", new messageeventprovider()); // chat state pm.addextensionprovider("active", "http://jabber.org/protocol/chatstates", new chatstateextension.provider()); pm.addextensionprovider("composing", "http://jabber.org/protocol/chatstates", new chatstateextension.provider()); pm.addextensionprovider("paused", "http://jabber.org/protocol/chatstates", new chatstateextension.provider()); pm.addextensionprovider("inactive", "http://jabber.org/protocol/chatstates", new chatstateextension.provider()); pm.addextensionprovider("gone", "http://jabber.org/protocol/chatstates", new chatstateextension.provider()); // xhtml pm.addextensionprovider("html", "http://jabber.org/protocol/xhtml-im", new xhtmlextensionprovider()); // group chat invitations pm.addextensionprovider("x", "jabber:x:conference", new groupchatinvitation.provider()); // service discovery # items pm.addiqprovider("query", "http://jabber.org/protocol/disco#items", new discoveritemsprovider()); // service discovery # info pm.addiqprovider("query", "http://jabber.org/protocol/disco#info", new discoverinfoprovider()); // data forms pm.addextensionprovider("x", "jabber:x:data", new dataformprovider()); // muc user pm.addextensionprovider("x", "http://jabber.org/protocol/muc#user", new mucuserprovider()); // muc admin pm.addiqprovider("query", "http://jabber.org/protocol/muc#admin", new mucadminprovider()); // muc owner pm.addiqprovider("query", "http://jabber.org/protocol/muc#owner", new mucownerprovider()); // delayed delivery pm.addextensionprovider("x", "jabber:x:delay", new delayinformationprovider()); // version try { pm.addiqprovider("query", "jabber:iq:version", class.forname("org.jivesoftware.smackx.packet.version")); } catch (classnotfoundexception e) { // not sure what's happening here. } // vcard pm.addiqprovider("vcard", "vcard-temp", new vcardprovider()); // offline message requests pm.addiqprovider("offline", "http://jabber.org/protocol/offline", new offlinemessagerequest.provider()); // offline message indicator pm.addextensionprovider("offline", "http://jabber.org/protocol/offline", new offlinemessageinfo.provider()); // last activity pm.addiqprovider("query", "jabber:iq:last", new lastactivity.provider()); // user search pm.addiqprovider("query", "jabber:iq:search", new usersearch.provider()); // sharedgroupsinfo pm.addiqprovider("sharedgroup", "http://www.jivesoftware.org/protocol/sharedgroup", new sharedgroupsinfo.provider()); // jep-33: extended stanza addressing pm.addextensionprovider("addresses", "http://jabber.org/protocol/address", new multipleaddressesprovider()); // filetransfer pm.addiqprovider("si", "http://jabber.org/protocol/si", new streaminitiationprovider()); pm.addiqprovider("query", "http://jabber.org/protocol/bytestreams", new bytestreamsprovider()); // privacy pm.addiqprovider("query", "jabber:iq:privacy", new privacyprovider()); pm.addiqprovider("command", "http://jabber.org/protocol/commands", new adhoccommanddataprovider()); pm.addextensionprovider("malformed-action", "http://jabber.org/protocol/commands", new adhoccommanddataprovider.malformedactionerror()); pm.addextensionprovider("bad-locale", "http://jabber.org/protocol/commands", new adhoccommanddataprovider.badlocaleerror()); pm.addextensionprovider("bad-payload", "http://jabber.org/protocol/commands", new adhoccommanddataprovider.badpayloaderror()); pm.addextensionprovider("bad-sessionid", "http://jabber.org/protocol/commands", new adhoccommanddataprovider.badsessioniderror()); pm.addextensionprovider("session-expired", "http://jabber.org/protocol/commands", new adhoccommanddataprovider.sessionexpirederror()); pm.addiqprovider("query", "http://jabber.org/protocol/disco#info", new discoverinfoprovider()); pm.addextensionprovider("x", "jabber:x:data", new dataformprovider()); // archive pm.addiqprovider("list", "urn:xmpp:archive", new listiqprovider()); pm.addiqprovider("chat", "urn:xmpp:archive", new chatiqprovider()); } }
@hirenpatel
first need add archive plugin openfire. after xmpp connection in client must register providers including 1 helps retrieve chat messages:
pm.addiqprovider("list", "urn:xmpp:archive", new listiqprovider()); pm.addiqprovider("chat", "urn:xmpp:archive", new chatiqprovider());
then need send iq stanza follow:
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);
Comments
Post a Comment