I fixed the issue, and I forgot to post the answer here for other people who might have the same problem. Anyway the fix is 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 to register the name of the child tag of the IQ response and not the request, hence "chat" instead of "retrieve".
Hope this helps, as I could not find any examples on the use of custom IQ in the android smack api.
Since the comment was too long I added it here.
Here you 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 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"));
}
}
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();
}
}
}
I just use this class, to call ServiceProviders.Register_Providers(ProviderManager.getInstance());
right after the Xmpp Connection is 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 for 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 you need to add the archive plugin to Openfire. Then after the Xmpp connection in the client you must register your providers including the one that helps retrieve the chat messages:
pm.addIQProvider("list", "urn:xmpp:archive", new ListIQProvider());
pm.addIQProvider("chat", "urn:xmpp:archive", new ChatIQProvider());
Then you need to send an IQ stanza like 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);