Sending messages to specific Smack domains after initial broadcast message
I'm creating an instant messaging client using Smack 3.1.0 and Java. The problem I'm running in to has to do with sending messages to the user on a specific domain.
For example, I have two users, 1@gmail.com and 2@gmail.com. 1@gmail.com logs in to XMPP through my IM client. 2@gmail.com logs in to GChat through gmail.com AND a second time through pidgin. So now I have one instance of 1@gmail.com and 2 instances of 2@gmail.com.
The way gmail works, if 1@gmail.com sends a message to 2@gmail.com, the gmail and the pidgin client both get the initial message. But then if the gmail instance responds to the message, every message from then on only goes between 1@gmail.com and the gmail instance of 2@gmail.com.
I would like to mimic this behavior with my IM client. I would think the way to do it would be to set up a Chat, send the initial IM to all instances of the recipient. Then I'd set up a MessageListener to listen f开发者_运维百科or a response. When I get the response, I'd have to create a new chat, specifying the 2@gmail.com/resource. But then I'd have to write the MessageListener twice. Any ideas? Here's some sample code that I'm using (the method AddText()
simply appends the message to my conversation pane):
recipient = buddy;
setTitle("Instant Message - "+recipient);
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser(), new MessageListener() {
public void processMessage(Chat chat, Message msg) {
//if(chat.getParticipant().indexOf('/')!=-1)
addText(msg.getBody(), chat.getParticipant(), true);
}
});
UPDATE I wanted to supplement the answer below with actual code that I used to make this work:
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser(), new MessageListener() {
public void processMessage(Chat new_chat, Message msg) {
if(msg.getFrom().replaceFirst("/.*", "").equals(recipient.getUser()))
{
if(buddy_resource==null || !msg.getFrom().replaceFirst(".*?/", "").equals(buddy_resource.getResource()))
{
buddy_resource = recipient.getResource(msg.getFrom().replaceFirst(".*?/", ""));
chat = null;
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser()+"/"+buddy_resource.getResource(), new MessageListener(){
public void processMessage(Chat new_chat2, Message msg) {
addText(msg.getBody(), new_chat2.getParticipant(), true);
}
});
}
addText(msg.getBody(), chat.getParticipant(), true);
}
}
});
To summarize, I send the first message to all resources of the recipient's address and wait for a response. When I get the response, I replace the current Chat
object with a new one that specifies the individual resource that responded to the initial message. The code is a little messy with two different MessageListener
objects that could probably be combined into a new class. But it works.
So far I understood Message Carbon (XEP - 0280) will solve your problem. If you enable carbon it will distribute messages to all logged resources of a user. In your case if 1@gmail.com send message to 2@gmail.com it will be distributed to all logged resources of 2@gmail.com. Here's a code sample using smack,
CarbonManager cm = CarbonManager.getInstanceFor(connection);
cm.enableCarbons();
cm.sendCarbonsEnabled();
First make sure that your server is supported Message Carbon. Then send message as usual.
In your MessageListener why not always respond to the sender? I think you get it by calling something like msg.getSender() or getFrom() (I'm on mobile right now, cannot check)
精彩评论