【问题标题】:How can I find out if a MUC exists using Smack?如何使用 Smack 确定 MUC 是否存在?
【发布时间】:2018-09-12 15:19:54
【问题描述】:


在多用户聊天 (XEP-0045-1.21) 中使用 Smack 4.3.0 我正在尝试确定是否已经创建了一个房间,但我不确定我正在做的是否是正确的方法。 我已经搜索过了,最相关的答案是 does MUC exist?

从技术上讲:

  1. 在 OpenFire 4.2.0 中,房间默认创建为公共和会员专用。
  2. 所有房间的名称都是由哈希字符串中的成员名称定义的 id,即XXXXXX029d8c36b62259d0eXXXXXXXX。这意味着用户 A 可以与 B、C 创建一个房间并像前一个一样获得groupId,但随后用户 B(在另一台设备中)可以尝试创建同一个房间(与用户 A、B、C),这将给他同样的groupId
  3. 存在类似whatsapp 的架构层,因此用户可以留下Group Chat 并随时重新加入。

此刻我在做什么:

@WorkerThread
public boolean isGroupChatAlreadyCreated(@NonNull final String groupId)
        throws
        XmppStringprepException,
        XMPPException.XMPPErrorException,
        MultiUserChatException.NotAMucServiceException,
        SmackException.NotConnectedException,
        InterruptedException,
        SmackException.NoResponseException {
    List<HostedRoom> hostedRooms = manager.getHostedRooms(JidCreate.domainBareFrom(serviceDomain));
    for (HostedRoom hostedRoom : hostedRooms) {
        if (hostedRoom.getName().equalsIgnoreCase(groupId)) {
            return true;
        }
    }

    return false;
}

其中managerMultiUserChatManager managerserviceDomain 只是String

所以,问题:这是正确的方法吗?可以改进吗?

【问题讨论】:

    标签: xmpp smack multiuserchat


    【解决方案1】:

    我相信更简单的方法是获取有关房间的一些信息,例如它的配置表格。如果不返回任何内容,则表示房间不存在:

    public boolean isGroupChatAlreadyCreated(@NonNull final EntityBareJid groupId)
            throws
            XMPPErrorException,
            NotConnectedException,
            InterruptedException,
            NoResponseException {
    
        MultiUserChat multiUserChat = MultiUserChatManager.getInstanceFor(connection).getMultiUserChat(groupId);
    
        return multiUserChat.getConfigurationForm() != null;
    }
    

    更多信息在这里https://github.com/igniterealtime/Smack/blob/4.3/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java#L809

    【讨论】:

      【解决方案2】:

      这基本上是正确的方法。

      理想情况下,您只需使用MulitUserChatManager.getRoomInfo(EntityBareJid)。如果房间存在,该方法将返回RoomInfo,如果不存在则抛出。

      您的原始方法也可以通过使用equals() 而不是equalsIgnoreCase() 将“groupId”的类型更改为EntityBareJid 来改进。并将您的 groupId 作为 MUC 地址的 Localpart。所以你的功能变成:

      public boolean isGroupChatAlreadyCreated(@NonNull final EntityBareJid groupId)
              throws
              XmppStringprepException,
              XMPPErrorException,
              NotAMucServiceException,
              NotConnectedException,
              InterruptedException,
              NoResponseException {
          List<HostedRoom> hostedRooms = manager.getHostedRooms(JidCreate.domainBareFrom(serviceDomain));
          for (HostedRoom hostedRoom : hostedRooms) {
              if (hostedRoom.getJid().equals(groupId)) {
                  return true;
              }
          }
      
          return false;
      }
      

      【讨论】:

      • 我认为这不是一个最佳方案,因为如果您的服务器有 10 万个房间会发生什么?每次在客户端都会有一个 100K 的迭代循环,这可能会导致 ANR 不好。我有一个替代建议(在单独的答案中提供)
      • 好点。我没有考虑过大型结果集。我可能会使用 XEP-0045 § 6.4。稍后会更新我的答案。
      • 在我的情况下,我们不会有这么多房间,而且我用@WorkerThread 标记了那个方法。在最坏的情况下,我可以实现二进制搜索,但我很确定我们不需要它(在我们的例子中)。无论如何,我会实施最好的:D
      • 对。如果您收到 ANR,那么无论如何您都做错了。尽管如此,如果 XEP-0045 提供了 O(1) 机制来查找房间,那么我们应该瞄准它,而不是 O(n) 方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 2016-02-28
      • 2020-12-10
      • 2016-10-25
      相关资源
      最近更新 更多