如何使用 Smack 确定 MUC 是不是存在?
Posted
技术标签:
【中文标题】如何使用 Smack 确定 MUC 是不是存在?【英文标题】: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?。
从技术上讲:
-
在 OpenFire 4.2.0 中,房间默认创建为公共和会员专用。
所有房间的名称都是由哈希字符串中的成员名称定义的 id,即
XXXXXX029d8c36b62259d0eXXXXXXXX
。这意味着用户 A 可以与 B、C 创建一个房间并像前一个一样获得groupId
,但随后用户 B(在另一台设备中)可以尝试创建同一个房间(与用户 A、B、C),这将给他同样的groupId
。
存在类似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;
其中manager
是MultiUserChatManager manager
而serviceDomain
只是String
。
所以,问题:这是正确的方法吗?可以改进吗?
【问题讨论】:
【参考方案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) 方法。以上是关于如何使用 Smack 确定 MUC 是不是存在?的主要内容,如果未能解决你的问题,请参考以下文章
smack 使用 4.1.0 rc1 在 muc 中接收消息
xmpp/smack : muc(MultiUserChat:多人聊天)房间配置表单