Как с помощью Smack узнать, существует ли MUC?


Работа с Smack 4.3.0 в многопользовательском чате (XEP-0045-1.21) Пытаюсь узнать, создана ли уже комната или нет , но я не уверен, правильно ли я делаю. Я искал его, и наиболее относительный ответ на него был существует ли MUC?< /а>.

С технической точки зрения:

  1. По умолчанию в OpenFire 4.2.0 комнаты создаются как общедоступные и только для участников.
  2. Все имена комнат — это идентификаторы, определяемые именами участников в хеш-строке, т. е. 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;
}

где manager — это MultiUserChatManager manager, а serviceDomain — это просто String.

Итак, вопросы: это правильный способ сделать это? можно улучшить?


person MiguelHincapieC    schedule 12.09.2018    source источник


Ответы (2)


Я считаю, что проще всего получить некоторую информацию о комнате, например, ее форму конфигурации. Если ничего не будет возвращено, значит комнаты не существует:

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

person Rubycon    schedule 14.09.2018

По сути, это правильный путь.

В идеале вы просто используете MulitUserChatManager.getRoomInfo(EntityBareJid). Метод вернет RoomInfo, если комната существует, или выбросит, если ее нет.

Ваш первоначальный подход также можно улучшить, изменив тип 'groupId' на EntityBareJid, используя equals() вместо equalsIgnoreCase(). И укажите свой groupId как локальную часть адреса MUC. Итак, ваша функция становится:

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;
}
person Flow    schedule 12.09.2018
comment
Я считаю, что это не оптимально, потому что что произойдет, если на вашем сервере будет 100 тысяч комнат? Каждый раз у вас будет цикл из 100 000 итераций на стороне клиента, что потенциально может привести к ANR, что нехорошо. У меня есть альтернативное предложение (приведено в отдельном ответе) - person Rubycon; 14.09.2018
comment
Хорошая точка зрения. Я не рассматривал большие наборы результатов. Я бы, вероятно, использовал XEP-0045 § 6.4. Обновлю свой ответ позже. - person Flow; 14.09.2018
comment
В моем случае у нас не будет столько комнат и плюс я отметил этот метод @WorkerThread. В худшем случае я могу реализовать бинарный поиск, но я уверен, что он нам не понадобится (в нашем случае). В любом случае я реализую лучший :D - person MiguelHincapieC; 14.09.2018
comment
Верно. Если вы получаете ANR, вы все равно делаете это неправильно. Тем не менее, если XEP-0045 предоставляет механизм O(1) для поиска комнаты, то мы должны стремиться к нему, а не к подходу O(n). - person Flow; 14.09.2018