I am connected to server(Xmpp)
but unable to send and receive packets at my psi client
Here is snippet of my code
POSClientIQ posclientiq = new POSClientIQ();
posclientiq.connectXMPPServer();
posclientiq.processMessage();
}
public void processMessage()
{ try{
final IQ iq1 = new IQ() {
public String getChildElementXML() {
return "<iq type='get' from ='sam'><query xmlns='jabber:iq:roster'></query></iq>";
}
};
iq1.setType(IQ.Type.GET);
// PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(iq1.getPacketID()));
connection.sendPacket(iq1);
System.out.println("Message send");
The getChildElementXML() returns the tag. If you are using Smack then you don't need to write your own IQ implementation unless it is a custom query. For your case, to query the roster use RosterPacket.
If you have a custom query and you would like to use your IQ implementation then:
final IQ iq = new IQ() {
public String getChildElementXML() {
return "<query xmlns='http://jabber.org/protocol/disco#info'/>"; // here is your query
//this returns "<iq type='get' from='User#YourServer/Resource' id='info1'> <query xmlns='http://jabber.org/protocol/disco#info'/></iq>";
}};
// set the type
iq.setType(IQ.Type.GET);
// send the request
connection.sendPacket(iq);
As you can see you have here your custom query and you use Smack to set the rest of your IQ e.g. setting the type. Please note that Smack fills the "from" for you based on the JID your are logged into.
//To retrieve archive msges from server..
MyCustomIQ iq = new MyCustomIQ();
iq.setType(IQ.Type.set);
mConnection.sendIqWithResponseCallback(iq, new PacketListener() {
#Override
public void processPacket(Packet packet) throws SmackException.NotConnectedException {
Log.i("Send IQ with Response", "****** message " + packet);
}
}, new ExceptionCallback() {
#Override
public void processException(Exception exception) {
exception.printStackTrace();
Log.i("IO archjieve Exception",""+ exception.getMessage());
}
}, 5000);
mConnection.sendPacket(new Presence(Presence.Type.available));
PacketTypeFilter filter=new PacketTypeFilter(org.jivesoftware.smack.packet.Message.class);
PacketListener myListener=new PacketListener(){
public void processPacket(Packet packet){
if(((Message) packet).getType().equals(Message.Type.chat))
{
((Message) packet).getBody();
}
else if(((Message) packet).getType().equals(Message.Type.normal))
{
DefaultPacketExtension pacExten=PacketUtil.packetExtensionfromCollection(packet.getExtensions(), "result", "urn:xmpp:mam:0");
String strMsg=pacExten.getValue("body");
}
}
}
;
mConnection.addPacketListener(myListener, filter);
//My Custom IQ
class MyCustomIQ extends IQ {
String token;
protected MyCustomIQ() {
super("query","urn:xmpp:mam:0");
}
#Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
// String queryId = prefix + Long.toString(new AtomicLong().incrementAndGet());
xml.attribute("queryid",queryId);
xml.rightAngleBracket();
return xml;
}
}
//You may get the response in PacketListerener sometimes so put debug in that also
Related
I am develloping call signals using Smack 4. I want to send an IQ-result which have the format below using Smack 4 and Java:
<iq from="sister#realworld.lit/home"
id="v73hwcx9"
to="alice#wonderland.lit/rabbithole"
type="result"/>
This is what I did and did not work
public class AcknowledgeIQ extends IQ {
public AcknowledgeIQ() {
super("");
setType(Type.result);
}
#Override
public IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
return null;
}
public String toXml(){
return super.toXML(null).toString();
}
}
I have tested below code on the SMACK 4.3.4.
public class AcknowledgeIQ extends org.jivesoftware.smack.packet.IQ {
public AcknowledgeIQ() {
super(null, null);
}
#Override
public IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
xml.rightAngleBracket();
return xml;
}
}
Usage example :
AcknowledgeIQ ackIQ = new AcknowledgeIQ();
ackIQ.setType(org.jivesoftware.smack.packet.IQ.Type.result);
Log.d(TAG, "AcknowledgeIQ = "+ackIQ.toXML(null).toString());
Logcat output :
AcknowledgeIQ = <iq xmlns='jabber:client' to='alice#wonderland.lit/rabbithole' id='MGr5o-5' type='result'></iq>
I am doing a project MAS project on jade.
I have 2 agents one to send and one to receive.
How do i make agent 1 send a message to agent 2, for example "1000", and only when agent 2 receives the "1000", agent 2 will reply with for example, "turn off"?
My sugestion is to create agent1 with a RequestPerformer behaviour and agent2 with a CyclicBehaviour to listen messages.
agent1 behaviour content can be like this:
ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
cfp.addReceiver(/*agent2AID*/);
cfp.setContent("1000");
cfp.setConversationId(1000);
cfp.setReplyWith("cfp" + System.currentTimeMillis()); // Unique value
myAgent.send(cfp);
mt = MessageTemplate.and(MessageTemplate.MatchConversationId(targetProduct),
MessageTemplate.MatchInReplyTo(cfp.getReplyWith()));
agent2 behaviour can be like this:
private class CFPServer extends CyclicBehaviour {
private static final long serialVersionUID = 1L;
public void action() {
MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.CFP);
ACLMessage msg = myAgent.receive(mt);
if (msg != null) {
// CFP Message received. Process it
String title = msg.getContent();
ACLMessage reply = msg.createReply();
// The requested fruit is NOT available for sale.
reply.setPerformative(ACLMessage.INFORM);
reply.setContent("turn off");
myAgent.send(reply);
} else {
block();
}
}
}
The related problem is very well discussed and solved in many ways, you can check out the following implementation of a simple Contract Net Protocol where you can find send and reply functions:
https://github.com/clebercbr/tp_cnp/blob/master/src/java/
See that the agent initiator is like agent1 and participant and rejector are like your agent2
I do not recommend to write a cyclic behaviour for messageReception, it will burn the proc for nothing. A simpleBehaviour with done() at false and a block() in the action() is much more efficient.
Regarding your pb, something like that should work :
public class ReceiveMessageBehaviour extends SimpleBehaviour{
private boolean finished=false;
/**
*
* This behaviour is a one Shot.
* It receives a message tagged with an inform performative, print the content in the console and destroy itself if its equal to 1000
* #param myagent
*/
public ReceiveMessageBehaviour(final Agent myagent) {
super(myagent);
}
public void action() {
//1) receive the message
final MessageTemplate msg Template = MessageTemplate.MatchPerformative(ACLMessage.INFORM);
final ACLMessage msg = this.myAgent.receive(msgTemplate);
//2) check its caracts
if (msg != null && msg.getContent().equals("1000")) {
System.out.println(this.myAgent.getLocalName()+"<----Result received from "+msg.getSender().getLocalName()+" ,content= "+msg.getContent());
this.finished=true;
//3) answer
final ACLMessage msg2 = new ACLMessage(ACLMessage.INFORM);
msg2.setSender(this.myAgent.getAID());
msg2.addReceiver(new AID(msg.getSender().getLocalName(), AID.ISLOCALNAME));
msg2.setContent("turn off");
this.myAgent.send(msg2);
}else{
block();// the behaviour goes to sleep until the arrival of a new message in the agent's Inbox.
}
}
public boolean done() { return finished;}
}
I'm new to these JADE related components. But I would like to add the simplest code that we can use to solve this problem using oneShotBehaviour and Cyclicehaviour.
The following code enables simple communication among two clients.
Agent A-Class:-
public class Agent_A extends Agent{
protected void setup(){
System.out.println(getAID().getName()+" is ready.");
addBehaviour(new AgentA_SendMessage());
addBehaviour(new AgentA_ReceiveMessage());
}
public class AgentA_SendMessage extends OneShotBehaviour{
#Override
public void action(){
ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
msg.addReceiver(new AID("AgentB",AID.ISLOCALNAME));
msg.setContent("1000");
send(msg);
}
}
public class AgentA_ReceiveMessage extends CyclicBehaviour{
Scanner scn2 = new Scanner(System.in);
#Override
public void action(){
ACLMessage remsg = myAgent.receive();
if(remsg!=null){
String reply = remsg.getContent();
System.out.println("Reply From "+remsg.getSender()+" :- "+reply);
}
else{
block();
}
}
}
}
Agent B Class:-
public class Agent_B extends Agent{
protected void setup(){
System.out.println("Hello Seller Agent : "+getAID().getName()+" is ready.");
addBehaviour(new AgentB_ReceiveMessage());
}
public class AgentB_ReceiveMessage extends CyclicBehaviour{
#Override
public void action(){
ACLMessage remsg = myAgent.receive();
if(remsg!=null){
System.out.println(""+remsg);
ACLMessage reply = remsg.createReply();
reply.setPerformative(ACLMessage.INFORM);
String price = remsg.getContent();
reply.setContent("off");
send(reply);
}else{
block();
}
}
}
}
How to create HTTP post connection to multiple URLs and post the JSON data to get the response from all the URLs using parallel.io in JAVA. I have tried with the below code set. But getting 404/java.net.ConnectException: http error
public class ParallecService {
private ParallelClient parallelClient;
private List<String> postHostsList = Arrays.asList("http://www.url1.com", "http://www.url2.com", "http://www.url3.com");
public void processRequest() {
parallelClient = new ParallelClient();
}
public void processPostRequests() {
parallelClient = new ParallelClient();
String requestBody = "JSON DATA";
parallelClient.prepareHttpPost("").setConcurrency(20).setTargetHostsFromList(postHostsList).setHttpHeaders(new ParallecHeader().addPair("Content-Type", "application/json")).setHttpEntityBody(requestBody).execute(
new ParallecResponseHandler() {
public void onCompleted(ResponseOnSingleTask responseOnSingleTask, Map<String, Object> map) {
responseOnSingleTask.getStatusCode().replaceAll("", "_");
System.out.println("Status Code : " + responseOnSingleTask.getStatusCode());
System.out.println("Last Updated" + PcDateUtils.getNowDateTimeStrStandard());
System.out.println(responseOnSingleTask.getErrorMessage());
System.out.println(responseOnSingleTask.getStackTrace());
System.out.println(responseOnSingleTask.getError());
System.out.println(responseOnSingleTask.getRequest().getRequestContent());
}
}
);
parallelClient.releaseExternalResources();
}
}
I already read these topics:
how to use SignalR in Android
Android Client doesn't get data but .net client getting data from SignalR server
I write a simple chat system with Android that works with SignalR.
It is supposed to the clients send messages (by calling SendMessage method on the server) and the server should call the NewMessage method on the clients.
Here is my ChatHub class (simplified) written in C#.
public class ChatHub : Hub
{
// Store the clients connections Id
static readonly List<string> _connectedClients;
public override Task OnConnected()
{
// Keep connections id
// This section works fine and when the android device connects to the server,
// Its connection id will stored.
_connectedClients.Add(Context.ConnectionId)
//... other codes
}
public void SendMessage(string message)
{
foreach (var connectionId in _connectedClients)
{
// according to the logs
// android device connection id exists here
// and it works fine.
Clients.Client(connectionId).NewMessage(message);
}
}
}
When the android client connects to the server, On the OnConnected method, the connection id will be stored in the _connectedClients and it works fine.
In the SendMessage method of the ChatHub class, We have the android device connection id, and I'm sure that the android device is within the list
And here is my Andoird codes:
public class ChatActivity extends AppCompatActivity
{
// private fields
HubConnection connection;
HubProxy hub;
ClientTransport transport;
protected void onCreate(Bundle savedInstanceState) {
Logger logger = new Logger() {
#Override
public void log(String message, LogLevel logLevel) {
Log.e("SignalR", message);
}
};
Platform.loadPlatformComponent(new AndroidPlatformComponent());
connection = new HubConnection("192.168.1.100");
hub = connection.createHubProxy("chatHub"); // case insensitivity
transport = new LongPollingTransport(connection.getLogger());
// no difference when using this:
//transport = new ServerSentEventsTransport(connection.getLogger());
// this event never fired!
hub.subscribe(new Object() {
public void NewMessage(String message)
{
Log.d("<Debug", "new message received in subscribe"); // won't work!
}
}
// this event never fired!
hub.on("NewMessage", new SubscriptionHandler() {
#Override
public void run() {
Log.d("<Debug", "new message received in `on`"); // won't work!
}
});
// connect to the server that works fine.
SignalRFuture<Void> awaitConnection = connection.start(transport);
try {
awaitConnection.get(); // seems useless when using this or not!
}
catch (Exception ex) {
}
// this method works fine.
hub.invoke("sendMessage", "this is a test message to the server")
.done(new Action<Void>() {
#Override
public void run(Void aVoid) throws Exception {
Log.d("<Debug", "message sent."); // Works fine
}
});
}
}
In the above java code, invoking the sendMessage on the server works fine and the server get the messages.
But the only problem is that the hub.on(...) or hub.subscribe(...) events are never be called by the server.
In a simple description, My app can send message, but can not receive message from the others.
Any suggestion will be appreciated.
For the futures this is the way I finally achieved the answer (please first read the question android codes):
public class ChatActivity extends AppCompatActivity
{
// private fields
HubConnection connection;
HubProxy hub;
ClientTransport transport;
protected void onCreate(Bundle savedInstanceState) {
Logger logger = new Logger() {
#Override
public void log(String message, LogLevel logLevel) {
Log.e("SignalR", message);
}
};
Platform.loadPlatformComponent(new AndroidPlatformComponent());
connection = new HubConnection("192.168.1.100");
hub = connection.createHubProxy("chatHub"); // case insensitivity
/* ****new codes here**** */
hub.subscribe(this);
transport = new LongPollingTransport(connection.getLogger());
/* ****new codes here**** */
connection.start(transport);
/* ****new codes here**** */
/* ****seems useless but should be here!**** */
hub.subscribe(new Object() {
#SuppressWarnings("unused")
public void newMessage(final String message, final String messageId, final String chatId,
final String senderUserId, final String fileUrl, final String replyToMessageId) {
}
});
/* ********************** */
/* ****new codes here**** */
/* **** the main method that I fetch data from server**** */
connection.received(new MessageReceivedHandler() {
#Override
public void onMessageReceived(final JsonElement json) {
runOnUiThread(new Runnable() {
public void run() {
JsonObject jsonObject = json.getAsJsonObject();
Log.e("<Debug>", "response = " + jsonObject.toString());
}
});
}
});
/* ********************** */
}
}
!important note:
The priority of the codes is important. this is how I fix my problem in this topic.
You does not provider parameters in your client-side which should be same as your side-site. The code should be below:
hub.on("NewMessage", new SubscriptionHandler1<String>() {
#Override
public void run(String message) {
Log.d("<Debug", "new message received in `on`");
}
},String.class); //do not forget say the String class in the end
smack presence listener in multi user chat not getting called. Used Smack Api to login and then added roster.addRosterListener(mRoasterListener); but could not get any success to listen when presence of other user of the chat room changes. I tried following code to get the presence listener to work :
connection.login(loginUser, passwordUser);
MultiUserChatManager manager =
MultiUserChatManager.getInstanceFor(connection);
muc = manager.getMultiUserChat(roomID + "#" +context.getString(R.string.group_chat_id));
Log.d("Join User: ", "Already Created");
muc.join(Utilities.getUserPhoneNo(context));
muc.addMessageListener(mGroupMessageListener);
Roster roster = Roster.getInstanceFor(connection);//luna
roster.addRosterListener(mRoasterListener);//roasterListener
Log.d("Joined User Phone: ", " " + Utilities.getUserPhoneNo(context));
and this class to listen for presence change...
public class RoasterListener implements RosterListener{
public RoasterListener(Context context){
}
#Override
public void entriesAdded(Collection<String> collection) {
}
#Override
public void entriesUpdated(Collection<String> collection) {
}
#Override
public void entriesDeleted(Collection<String> collection) {
}
#Override
public void presenceChanged(Presence presence) {
System.out.println("Presence changed: " + presence.getFrom() + " " + presence);
}
}
I tried many links available by stackoverflow but could not get any success.
Please Help!
For Multi User Chat you don't have to use Roster, because it's normal to meet people you don't have in Roster.
To know who is in a muc, first ask for occupants:
muc.join(user,password);
List<String> occupantsAtJoinTime = muc.getOccupants();
for (String occupant : occupantsAtJoinTime)
{
System.out.println("occupant: "+occupant);
//actions
}
then, to keep Occupants list updated, register a DefaultParticipantStatusListener to your muc and define that Listner:
muc.addParticipantStatusListener(new CustomParticipantStatusListner());
definied as (there are many methods to implement if you need):
public class CustomParticipantStatusListner extends DefaultParticipantStatusListener
{
public void joined(String participant)
{
System.out.println(participant + "just joined MUC");
//actions (add occupantsRightNow)
}
public void left(String participant)
{
System.out.println(participant + " just left MUC");
//actions (remove occupantsRightNow)
}
}
All this with smack 4.1.7
It's about the Manage role modifications in Multi User Chat.
This example shows how to grant voice to a visitor and listen for the notification events:
// User1 creates a room
muc = new MultiUserChat(conn1, "myroom#conference.jabber.org");
muc.create("testbot");
// User1 (which is the room owner) configures the room as a moderated room
Form form = muc.getConfigurationForm();
Form answerForm = form.createAnswerForm();
answerForm.setAnswer("muc#roomconfig_moderatedroom", "1");
muc.sendConfigurationForm(answerForm);
// User2 joins the new room (as a visitor)
MultiUserChat muc2 = new MultiUserChat(conn2, "myroom#conference.jabber.org");
muc2.join("testbot2");
// User2 will listen for his own "voice" notification events
muc2.addUserStatusListener(new DefaultUserStatusListener() {
public void voiceGranted() {
super.voiceGranted();
...
}
public void voiceRevoked() {
super.voiceRevoked();
...
}
});
// User3 joins the new room (as a visitor)
MultiUserChat muc3 = new MultiUserChat(conn3, "myroom#conference.jabber.org");
muc3.join("testbot3");
// User3 will lister for other occupants "voice" notification events
muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() {
public void voiceGranted(String participant) {
super.voiceGranted(participant);
...
}
public void voiceRevoked(String participant) {
super.voiceRevoked(participant);
...
}
});
// The room's owner grants voice to user2
muc.grantVoice("testbot2");
Details can be refered in http://web.mit.edu/svalente/lib/smack_3_0_4/documentation/extensions/muc.html .
Firstly, join a chat room:
public MultiUserChat joinMultiUserChat(String user, String roomsName,
String password) {
if (getConnection() == null)
return null;
try {
MultiUserChat muc = new MultiUserChat(getConnection(), roomsName
+ "#conference." + getConnection().getServiceName());
DiscussionHistory history = new DiscussionHistory();
history.setMaxChars(0);
// history.setSince(new Date());
muc.join(user, password, history,
SmackConfiguration.getPacketReplyTimeout());
Log.i("MultiUserChat", "Chat room【"+roomsName+"】joined........");
return muc;
} catch (XMPPException e) {
e.printStackTrace();
Log.i("MultiUserChat", "Chat room【"+roomsName+"】failed........");
return null;
}
}
Then, use MultiChatUser to send Message:
try {
multiUserChat.sendMessage(message);
} catch (XMPPException e) {
e.printStackTrace();
}
Add a Listener:
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
public class TaxiMultiListener implements PacketListener {
#Override
public void processPacket(Packet packet) {
Message message = (Message) packet;
String body = message.getBody();
}
}
Finally, call the Listener using MultiUserChat:
multiUserChat.addMessageListener(new TaxiMultiListener());