在初始广播消息后向特定 Smack 域发送消息

Posted

技术标签:

【中文标题】在初始广播消息后向特定 Smack 域发送消息【英文标题】:Sending messages to specific Smack domains after initial broadcast message 【发布时间】:2011-01-22 01:54:17 【问题描述】:

我正在使用 Smack 3.1.0 和 Java 创建一个即时消息客户端。我遇到的问题与向特定域上的用户发送消息有关。

例如,我有两个用户,1@gmail.com 和 2@gmail.com。 1@gmail.com 通过我的 IM 客户端登录到 XMPP。 2@gmail.com 通过 gmail.com 和第二次通过 pidgin 登录到 GChat。所以现在我有 1@gmail.com 的一个实例和 2@gmail.com 的 2 个实例。

gmail 的工作方式,如果 1@gmail.com 向 2@gmail.com 发送消息,gmail 和 pidgin 客户端都会收到初始消息。但是如果 gmail 实例响应消息,那么从那时起的每条消息都只会在 1@gmail.com 和 2@gmail.com 的 gmail 实例之间传递。

我想用我的 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 对象,它们可能会组合成一个新类。但它有效。

【问题讨论】:

【参考方案1】:

到目前为止,我了解 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。 然后像往常一样发送消息。

【讨论】:

【参考方案2】:

在您的 MessageListener 中为什么不总是响应发送者?我认为您可以通过调用 msg.getSender() 或 getFrom() 之类的方法来获取它(我现在在移动设备上,无法查看)

【讨论】:

msg.getFrom() 是一个字符串。回复发件人需要 Chat newChat = connection.getChatManager().createChat(msg.getFrom(), new MessageListener()); 你能把那个MessageListener设置为null吗?因为你已经有一个监听器来接收响应消息。 好吧,我可以将该侦听器设置为 null,但我会创建一个新的 Chat 实例,因此不会处理任何传入消息,因为旧侦听器已被破坏。 如果它被破坏了,有一个新的监听器有什么问题?那么如果 pidgin 客户端在 gtalk 已经开始新的会话之后响应呢? 我可以试试。我会告诉你的。

以上是关于在初始广播消息后向特定 Smack 域发送消息的主要内容,如果未能解决你的问题,请参考以下文章

高速公路从外部应用程序发送用户特定和广播消息

如何将receiptid映射到smack中发送的消息

使用 Smack Api for Android 发送和接收消息

使用 Smack 和 Openfire 发送/接收消息时遇到问题

使用 smack API 发送和接收消息

Android Smack MUC 400 错误请求发送群聊消息