XMPP IQ result parsing issue - android

I am building a XMPP chat client app with eclipse, java and asmack. Using tutorials and many many google searches I managed to get the buddy list working, actual chatting also works fine.
My problem is with searching for more buddies to add to my contacts list. The XML to send is exemplified here : http://xmpp.org/extensions/xep-0055.html
My request is :
<iq
id="search123"
from="name3#webserv.xxx.com/name3"
to="search.xxx.zzz.com"
type="set" >
<query xmlns="jabber:iq:search" >
<nick>
android
</nick>
</query>
</iq>
the response I thought I was getting was/is this:
<iq
id="search123"
from="search.xxx.zzz.com"
to="name3#webserv.telebroad.com/Smack"
type="result" >
</iq>
But using
connConfig.setDebuggerEnabled(true);
(and an online Telnet Client) I managed to find out that the server IS actually working correctly and it's sending the requested results, but I'm just getting what you see above.
I have been at this for 4 days and my self esteem is quite low :P
Here is my code concerning the IQ request and response:
Packet asdf = new Packet() {
#Override
public String toXML() {
return "<iq type='set'"+
" from='name3#webserv.xxx.com/name3'"+
" to='search.xxx.zzz.com'"+
" id='search2'"+
" xml:lang='en'>"+
" <query xmlns='jabber:iq:search'>"+
" <nick>Android</nick>"+
" </query>"+
" </iq>";
}
};
ChatList.connection.sendPacket(asdf);
Log.e("packet", "request = "+ asdf.toXML());
PacketFilter filter = new IQTypeFilter(IQ.Type.RESULT);
ChatList.connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
IQ iq = (IQ)packet;
Log.e("response","incoming packet : "+ packet.toXML());
Log.e("response","incoming packet2 : "+ packet.toString());
}
}, filter);
I've tried lots of TypeFilters to no avail. I'm stumped!!
Bottom line:
1.request is being accepted correctly by server;
2.server response is correct(so says the debugger);
3.any response.toString or toXML prints out the type result XML from above(without the actual items after type='result'>.
4.I am about a week overdue on my final build for this app...help! :)

Try adding
ProviderManager pm = ProviderManager.getInstance();
pm.addIQProvider( "query","jabber:iq:search",new UserSearch.Provider());
pm.addExtensionProvider("x","jabber:x:data", new DataFormProvider());
before establishing connection.

This spec is already implemented via the UserSearchManager. Try using that instead.
As for your own case, I would guess that you haven't registered an appropriate provider for this specific element and namespace (like org.jivesoftware.smackx.search.UserSearch$Provider). In a normal Java environment, this would already be registered, but you will have to code it yourself in Android.

https://stackoverflow.com/a/14214622/1688731
This...just works!!!! I have no idea why. maybe Iterator iterator = row.getValues("jid"); does the trick. But everything else, I've tried a LOT of times!!

Related

how to publish and parse custom payload for pubsub xmpp smack library

this question is asked before here and here but i dont get answer from there.
I'm developing application in which i'm using pubsub and xmpp, for android i'm using smack library. i want to send custom payload to the node and on receiving custom payload how to parse and display it in to list? now i am able to send and receive message but it is just a small example from documentaion. here is my example,
String msg = "room pubsub test";
SimplePayload payload = new SimplePayload("message", "pubsub:test:message", "<message xmlns='pubsub:test:message'><body>" + msg + "</body></message>");
PayloadItem<SimplePayload> item = new PayloadItem<>(null, payload);
node.publish(item);
and when i receive item
node.addItemEventListener(new ItemEventListener() {
#Override
public void handlePublishedItems(ItemPublishEvent items) {
System.out.println("======================handlePublishedItems==============================");
System.out.println(items.getItems());
}
}
and the output i'm getting is
[org.jivesoftware.smackx.pubsub.PayloadItem |
Content [<item id='5E277A9C33A58'>
<message xmlns='pubsub:test:message'>
<body xmlns='pubsub:test:message'>room pubsub test</body><
/message>
</item>]]
i want to send custom payload like the time at which message is sent, who have sent this message etc.
so, how can i send custom payload? and how to parse it and show it to user?
Send custom payload for time and sender using below code:
SimplePayload payload = new SimplePayload("message", "pubsub:test:message", "<message xmlns='pubsub:test:message'><body>" + textMessage + "</body><from>"+Sender+"</from><time>"+time+"</time></message>");
For parsing you can use XmlPullParser and parse response using Tag name

Accessing JSON object inside Message Stanza using Smack Library

my addAsyncStanzaListner is being called when an ack message is received from Firebase Cloud Messaging services. I need to ack this messages according to the docs. The problem that I am having is I can't reach the "message_type" "key"/"value" pair inside the JSON object that arrives inside the message stanza that's received. Could you please help me in accessing this important value/pair. I am using Smack Library 4.1. I've been following this post answer for this setup, but somehow It doesn't work:
GCM XMPP Server using Smack 4.1.0
Here's how the code is looking like:
other_connection.addAsyncStanzaListener(new StanzaListener() {
#Override
public void processPacket(Stanza packet) throws SmackException.NotConnectedException {
//how should i convert this stanza into a message stanza
//I have tried Message message = (Message)packet; IT DOESNT WORK
//I have tried getting the extension with the GCM Namespace. It doesnt
//return a json string
In your code you just recive a Stanza as Java Object.
Stanza has a method to output an XML.
You can use this method to obtain a JSON if you need, just add some custom functionality.
Following this example
your code can looks like this:
#Override
public void processPacket(Stanza packet) throws SmackException.NotConnectedException {
JSONObject jsonObj = XML.toJSONObject(packet.toXML());
String json = jsonObj.toString();
//foo
Note: This answer is for the general problem of extracting JSON from a message. In the case of FCM, it's possible that there's another method that's more appropriate.
Suppose your have a Stanza object that corresponds to the following XML:
<message from='a#example.com' to='b#example.com' type='normal'>
<json xmlns='urn:xmpp:json:0'>{ "key1" : "value1", "key2": "value2" }</json>
<body/>
</message>
To extract the JSON string, you need to do:
import org.jivesoftware.smackx.json.packet.JsonPacketExtension;
...
JsonPacketExtension jsonPacketExtension = JsonPacketExtension.from(stanza);
String contentJson = jsonPacketExtension.getJson();

How to send a XMPP IQ Package to a PHP JAXL-Script?

ive a problem. Im using asmack for connecting and sending Data between Android and OpenFire.
Now i'ld like to get this data with PHP and Jaxl (which is working fine).
The problem is that i modify the sent message (to JSON and XML) and add a HEADER to the XML/JSON. This seems to work well but its not a proper solution.
Now i'm thinking about sending IQ Packages which hold the Header information already.
This is the Part in Android/Java.
CommandIQPacket iq1 = new CustomIQPacket();
iq1.setTo(to);
iq1.setType(IQ.Type.GET);
iq1.setCommand("test");
iq1.setPriority(1);
iq1.setJid(message.getMessage());
iq1.setDate(new Date(System.currentTimeMillis()));
mConnection.sendPacket(iq1);
The CustomIQPacket class extends IQ and add the required data by overriding getChildElementXML().
Sample:
public class CommandIQPacket extends IQ {
private int priority;
private String jid, command;
//some getter and setter
#Override
public CharSequence getChildElementXML() {
StringBuilder builder = new StringBuilder("<query xmlns=\"urn:xmpp:ts\">");
builder.append("<jid command=\"");
builder.append(command).append("\"");
builder.append(" date=\"");
builder.append(date).append("\"");
builder.append(" priority=\"");
builder.append(priority).append("\"");
builder.append(">");
builder.append(jid);
builder.append("</jid>");
builder.append("</query>");
return builder.toString();
}
}
Now i've my PHP CLI Script with JAXL. This looks like that.
<?php
// configs, stuff, etc.
$client = new JAXL(array(
'jid' => "myopenfireuser",
'pass' => "myopenfirepass",
'bosh_url' => "http://url-to-bosh.com:7070/http-bind/",
'log_level' => JAXL_INFO,
'strict' => TRUE
));
$client->require_xep(array(
'0115', // Entity Capabilities
'0203', // Delayed Delivery
'0114', // jabber component protocol
'1337'
));
ive added 1337 here, which should be the XEP for parsing the IQ package.
$client->add_cb('on_chat_message', function($stanza) {
global $client;
$iq = $client->xeps['1337']->get_raw_iq_pkt();
// some more stuff
}
Now it seems to be that $iq does not hold any rawdata. I cant access the XML which means that i cant parse the IQ Package.
The 1337 XEP looks like that.
class XEP_1337 extends XMPPXep {
public function init() {
return array(
'on_get_iq' => 'on_xmpp_iq'
);
}
public function get_raw_iq_pkt() {
$attrs = array(
'type' => 'get',
'from' => $this->jaxl->full_jid->to_string(),
'to' => $this->jaxl->full_jid->domain
);
return $this->jaxl->get_iq_pkt(
$attrs, new JAXLXml('query', "ts")
);
}
}
I couldnt find any good tutorial about JAXL and IQ Packages. This is the only readme ive found about it (https://media.readthedocs.org/pdf/jaxl/latest/jaxl.pdf)
The sent data is for example
<iq id='qEfml-14' to='openfirebot#openfirebot.com/Ressource' type='get'><query xmlns="ts"><jid command="test" date="Mon Jul 28 12:36:15 MESZ 2014" priority="1">...</query></iq>
the return value from openfire (jaxl) is
<iq type="error" id="NP3HP-12" from="bot..#myopenfire.com" to="maclient#ts.com/Ressource"><query xmlns="ts" action="create"><jid command="test" date="Mon Jul 28 23:04:22 MESZ 2014" priority="1">...</jid></query><error code="503" type="cancel"><service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>
OpenFire error=
at org.apache.mina.filter.executor.ExecutorFilter$ProcessEventsRunnable.run(ExecutorFilter.java:283)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
at java.lang.Thread.run(Thread.java:701)
2014.07.29 15:56:33 org.jivesoftware.openfire.nio.ConnectionHandler - Closing connection due to error while processing message: <iq id="769-83772" to="ts.com" from="ts.com/4140f14a" type="result"></iq>
java.lang.NullPointerException
at org.jivesoftware.openfire.IQRouter.route(IQRouter.java:115)
at org.jivesoftware.openfire.spi.PacketRouterImpl.route(PacketRouterImpl.java:76)
at org.jivesoftware.openfire.net.StanzaHandler.processIQ(StanzaHandler.java:330)
at org.jivesoftware.openfire.net.ClientStanzaHandler.processIQ(ClientStanzaHandler.java:93)
at org.jivesoftware.openfire.net.StanzaHandler.process(StanzaHandler.java:295)
at org.jivesoftware.openfire.net.StanzaHandler.process(StanzaHandler.java:187)
at org.jivesoftware.openfire.nio.ConnectionHandler.messageReceived(ConnectionHandler.java:181)
at org.apache.mina.common.support.AbstractIoFilterChain$TailFilter.messageReceived(AbstractIoFilterChain.java:570)
at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(AbstractIoFilterChain.java:299)
at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilterChain.java:53)
at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceived(AbstractIoFilterChain.java:648)
at org.apache.mina.common.IoFilterAdapter.messageReceived(IoFilterAdapter.java:80)
at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(AbstractIoFilterChain.java:299)
at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilterChain.java:53)
at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceived(AbstractIoFilterChain.java:648)
at org.apache.mina.filter.codec.support.SimpleProtocolDecoderOutput.flush(SimpleProtocolDecoderOutput.java:58)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:185)
at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(AbstractIoFilterChain.java:299)
at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilterChain.java:53)
at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceived(AbstractIoFilterChain.java:648)
at org.apache.mina.filter.executor.ExecutorFilter.processEvent(ExecutorFilter.java:239)
at org.apache.mina.filter.executor.ExecutorFilter$ProcessEventsRunnable.run(ExecutorFilter.java:283)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
at java.lang.Thread.run(Thread.java:701)
This is what ive found out now:
Its important that to has the fullname with ressource. user#domain/Ressource
And.. the Receiving client must be online. Offline messages dont get accepted for IQ PAckets from OpenFire (by default)
And.. regarding this article it must be registered somehow. How can this be done in jaxl? i thought adding the XEP and using init() is enough.
Sending and Receiving custom XMPP IQs with aSmack on Android
And.. ive modified the PAcketListener but still same result.
PacketFilter filter = new PacketFilter() {
#Override
public boolean accept(Packet packet) {
return true;
}
};
mConnection.addPacketListener(mPacketListener, filter);
ProviderManager.addIQProvider("query", "ts", new CommandIQProvider());
while mPacketListener is a class which extends from PacketListener.
public class ChatPacketListener implements PacketListener {
public void processPacket(Packet packet) {
if (packet instanceof Message) {
Message message = (Message) packet;
String from = message.getFrom();
if (message.getBody() != null) {
Log.d("ChatPacketLsitener", "XMPP packet received - sending Intent: " + XmppService.ACTION_XMPP_MESSAGE_RECEIVED);
XmppService.maybeAcquireWakeLock();
XmppTools.startSvcXMPPMsg(mCtx, message.getBody(), from);
}
} else {
Log.e("Packet", "Packet is not from type Message. Its from type " + packet.getClass());
}
}

JavaMail Message getHeader() bug

I am writing an Android GMail client application.
When it creates a message, I add a header to it like this:
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(username));
msg.setSubject(subject);
msg.setText(message);
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
long time = someTime;
msg.addHeader("My_Header", Long.toString(time));
//IMAPFolder f declaration & initialization
f.open(Folder.READ_WRITE);
f.addMessages(new Message[]{msg});
f.close(true);
It all works fine and I am able to see the header correctly added to the message when viewing my GMail account on my PC. However, when I later try to retrieve the header information, it gets very weird.
When I call
String[] str = msg.getHeader("My_Header");
getHeader() returns null if I am running the app. However, when I debug the app and set a breakpoint before the getHeader() call, it returns the header value corrently.
My source code:
MimeMessage msg = getNextMessage();
String subject = msg.getSubject();
InternetAddresses to[] = msg.getAllRecipients()
String when[] = msg.getHeader(GMailClient.TIME_TO_SEND);
if (when == null) {
Log.i(TAG, "Null Header");
} else {
long time = Long.parseLong(when[0]);
Log.i(TAG, "Value retrieved: " + when[0]);
}
Possibly Gmail isn't returning the header information correctly via IMAP? You might want to look at the protocol trace to see exactly what the server is returning for your request.
Also, try writing out the entire message using (e.g.)
msg.writeTo(new FileOutputStream("msg.txt"));
and see if the header is there. If it is, and the protocol trace shows that it's not being returned for the getHeader call, it's a bug in the server. In that case, see the JavaMail FAQ entry for how to work around such server bugs.

Smack getPrivacyList method throws classCastException

I am using Smack in an Android app for XMPP based communication. I am trying to create a privacy list using PrivacyManager. I have created a PrivacyList successfully, but when I try to access that list it returns ClassCastException. Here is the code:
PrivacyListManager privacyManager;
privacyManager = PrivacyListManager.getInstanceFor(connection);
PrivacyList privacyList = privacyManager.getPrivacyList("msg_block_list");
Investigating a bit more, I have found that the exception occurs in getRequest method in PrivacyListManager.java class on following line:
Privacy privacyAnswer =
(Privacy) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
Here is the getRequest method:
private Privacy getRequest(Privacy requestPrivacy) throws XMPPException {
// The request is a get iq type
requestPrivacy.setType(Privacy.Type.GET);
requestPrivacy.setFrom(this.getUser());
// Filter packets looking for an answer from the server.
PacketFilter responseFilter = new PacketIDFilter(requestPrivacy.getPacketID());
PacketCollector response = connection.createPacketCollector(responseFilter);
// Send create & join packet.
connection.sendPacket(requestPrivacy);
// Wait up to a certain number of seconds for a reply.
Privacy privacyAnswer =
(Privacy) response.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Stop queuing results
response.cancel();
// Interprete the result and answer the privacy only if it is valid
if (privacyAnswer == null) {
throw new XMPPException("No response from server.");
}
else if (privacyAnswer.getError() != null) {
throw new XMPPException(privacyAnswer.getError());
}
return privacyAnswer;
}
I have followed this tutorial for implementing PrivacyList. Anyone can help?
PacketCollector's method getResult() returns Packet object, but it could be any inherited from Packet class object, either Message or Presence or IQ (in IQ case you can use (privacy) cast, because Privacy is IQ's child class). In your case it seems like you get object which is present in another hierarchy, than Privacy class.
I have found the problem. The XML file smack.providers was missing. I created the file with following contents and it worked.
<?xml version="1.0"?>
<!-- Providers file for default Smack extensions -->
<smackProviders>
<!-- Privacy -->
<iqProvider>
<elementName>query</elementName>
<namespace>jabber:iq:privacy</namespace>
<className>org.jivesoftware.smack.provider.PrivacyProvider</className>
</iqProvider>
</smackProviders>

Categories

Resources