Отправка сообщений в определенные домены Smack после первоначального широковещательного сообщения
Я создаю клиент обмена мгновенными сообщениями, используя Smack 3.1.0 и Java. Проблема, с которой я сталкиваюсь, связана с отправкой сообщений пользователю в определенном домене.
Например, у меня есть два пользователя: 1@gmail.com и 2@gmail.com. 1@gmail.com входит в XMPP через мой IM-клиент. 2@gmail.com входит в GChat через gmail.com И второй раз через pidgin. Так что теперь у меня есть один экземпляр 1@gmail.com и 2 экземпляра 2@gmail.com.
Как работает gmail, если 1@gmail.com отправляет сообщение на адрес 2@gmail.com, gmail и клиент pidgin оба получают исходное сообщение. Но затем, если экземпляр gmail отвечает на сообщение, каждое сообщение с этого момента идет только между 1@gmail.com и экземпляром gmail 2@gmail.com.
Я хотел бы подражать этому поведению с моим клиентом IM. Я думаю, что способ сделать это будет настроить чат, отправить начальный IM для всех экземпляров получателя. Тогда я бы настроил MessageListener для прослушивания ответа. Когда я получу ответ, мне нужно будет создать новый чат, указав 2@gmail.com/resource. Но тогда мне придется написать MessageListener дважды. Есть идеи? Вот пример кода, который я использую (метод AddText()
просто добавляет сообщение в мою панель разговора):
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);
}
});
ОБНОВЛЕНИЕ Я хотел дополнить ответ ниже фактическим кодом, который я использовал, чтобы сделать эту работу:
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);
}
}
});
Подводя итог, я отправляю первое сообщение всем ресурсам адреса получателя и жду ответа. Когда я получаю ответ, я заменяю текущий Chat
объект с новым, который указывает отдельный ресурс, который ответил на исходное сообщение. Код немного грязный с двумя разными MessageListener
объекты, которые могут быть объединены в новый класс. Но это работает.
2 ответа
В вашем MessageListener почему бы не всегда отвечать отправителю? Я думаю, что вы получите это, вызвав что-то вроде msg.getSender() или getFrom() (я сейчас на мобильном, не могу проверить)
До сих пор я понял, что Message Carbon (XEP - 0280) решит вашу проблему. Если вы включите углерод, он будет распространять сообщения на все зарегистрированные ресурсы пользователя. В вашем случае, если 1@gmail.com отправит сообщение на 2@gmail.com, оно будет распространено на все зарегистрированные ресурсы 2@gmail.com. Вот пример кода с использованием smack,
CarbonManager cm = CarbonManager.getInstanceFor(connection);
cm.enableCarbons();
cm.sendCarbonsEnabled();
Сначала убедитесь, что на вашем сервере поддерживается Message Carbon. Затем отправьте сообщение как обычно.