Отправка и получение IQ XMPP ASMACK Android

Предыстория:

Мне удалось реализовать чат один на один через XMPP в Android, используя библиотеку asmack. Я также могу отправить присутствие на сервер. Я использую сервер OpenFire для своего приложения на основе чата.

Проблема: я использую connection.addPacketListener(new PacketListener() для получения сообщений и пакетов IQ, для пакетов сообщений я классифицировал это следующим образом

PacketFilter Chatfilter = new MessageTypeFilter(Message.Type.chat);
connection.addPacketListener(new PacketListener() {
        public void processPacket(Packet packet) {
            Message message = (Message) packet;
            if (message.getBody() != null) {
                String fromName = StringUtils.parseBareAddress(message.getFrom());
                Log.i("XMPPClient", "Got text [" + message.getBody() + "] from [" + fromName + "]");
                messages.add(fromName + ":");
                m1=message.getBody();
                messages.add(message.getBody());
                // Add the incoming message to the list view
                /* mHandler.post(new Runnable() {
                public void run() {
                setListAdapter();
                recieve.setText(m1);
                }
                });*/
            }
        }
}, Chatfilter);

Все работает нормально, но проблема возникает, когда я использую что-то похожее для получения IQ-пакетов.

Вот код, который я использую для получения пакетов IQ

PacketFilter Iqfilter = new IQTypeFilter(IQ.Type.RESULT);
connection.addPacketListener(new PacketListener() {
    public void processPacket(Packet packet) {
        IQ iq = (IQ) packet;
        String fromName = StringUtils.parseBareAddress(iq.getFrom());
        Log.i("XMPPClient", "Got text [" + iq.toString() + "] from [" + fromName + "]");
        m1=iq.getFrom();
        mHandler.post(new Runnable() {
            public void run() {
                setListAdapter();
                recieve.setText(m1);
            }
        });
    }
}, Iqfilter);

Я отправляю простой запрос disco#items, а он не отвечает, даже в функцию не входит, я тоже пробовал его отлаживать, я также пытался отправить простую команду PING, но он тоже не отвечает. что я здесь упускаю?

Во-вторых, я сталкиваюсь с проблемами при отправке IQ-пакетов на сервер или другому клиенту. Я где-то читал, что надо делать так. Но это не работает.

final IQ iq = new IQ() {
            public String getChildElementXML() { 
            return "<query xmlns='http://jabber.org/protocol/disco#info'/>"; // here is your query
            //this returns "<iq type='get' from='User@YourServer/Resource' id='info1'> <query xmlns='http://jabber.org/protocol/disco#info'/></iq>";
             }};
            // set the type
            iq.setType(IQ.Type.GET);

            // send the request
            connection.sendPacket(iq);

Сбивает с толку то, что когда я читал документацию XMPP и asmack для Android, было написано, что для отправки IQ вам также необходимо иметь адрес получателя. но в этом коде мы не настраиваем никакого приемника.

В Интернете гораздо меньше информации о XMPP asmack и Android.


person Hassaan Rabbani    schedule 12.03.2014    source источник


Ответы (3)


Я думаю, проблема в том, что ваши провайдеры не зарегистрированы. Пожалуйста, взгляните на это. На Android вам необходимо зарегистрировать провайдеров вручную, прежде чем формировать XMPP-соединение. Скопируйте приведенный ниже класс в свой проект.

import org.jivesoftware.smack.provider.PrivacyProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smackx.GroupChatInvitation;
import org.jivesoftware.smackx.PrivateDataManager;
import org.jivesoftware.smackx.packet.ChatStateExtension;
import org.jivesoftware.smackx.packet.LastActivity;
import org.jivesoftware.smackx.packet.OfflineMessageInfo;
import org.jivesoftware.smackx.packet.OfflineMessageRequest;
import org.jivesoftware.smackx.packet.SharedGroupsInfo;
import org.jivesoftware.smackx.provider.AdHocCommandDataProvider;
import org.jivesoftware.smackx.provider.BytestreamsProvider;
import org.jivesoftware.smackx.provider.DataFormProvider;
import org.jivesoftware.smackx.provider.DelayInformationProvider;
import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
import org.jivesoftware.smackx.provider.MUCAdminProvider;
import org.jivesoftware.smackx.provider.MUCOwnerProvider;
import org.jivesoftware.smackx.provider.MUCUserProvider;
import org.jivesoftware.smackx.provider.MessageEventProvider;
import org.jivesoftware.smackx.provider.MultipleAddressesProvider;
import org.jivesoftware.smackx.provider.RosterExchangeProvider;
import org.jivesoftware.smackx.provider.StreamInitiationProvider;
import org.jivesoftware.smackx.provider.VCardProvider;
import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;
import org.jivesoftware.smackx.search.UserSearch;

import android.util.Log;

public class ServiceProviders {
    public static void Register_Providers(ProviderManager pm) {

        // Private Data Storage
        pm.addIQProvider("query", "jabber:iq:private",
                new PrivateDataManager.PrivateDataIQProvider());

        // Time
        try {
            pm.addIQProvider("query", "jabber:iq:time",
                    Class.forName("org.jivesoftware.smackx.packet.Time"));
        } catch (ClassNotFoundException e) {
            Log.w("TestClient",
                    "Can't load class for org.jivesoftware.smackx.packet.Time");
        }

        // Roster Exchange
        pm.addExtensionProvider("x", "jabber:x:roster",
                new RosterExchangeProvider());

        // Message Events
        pm.addExtensionProvider("x", "jabber:x:event",
                new MessageEventProvider());

        // Chat State
        pm.addExtensionProvider("active",
                "http://jabber.org/protocol/chatstates",
                new ChatStateExtension.Provider());

        pm.addExtensionProvider("composing",
                "http://jabber.org/protocol/chatstates",
                new ChatStateExtension.Provider());

        pm.addExtensionProvider("paused",
                "http://jabber.org/protocol/chatstates",
                new ChatStateExtension.Provider());

        pm.addExtensionProvider("inactive",
                "http://jabber.org/protocol/chatstates",
                new ChatStateExtension.Provider());

        pm.addExtensionProvider("gone",
                "http://jabber.org/protocol/chatstates",
                new ChatStateExtension.Provider());

        // XHTML
        pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im",
                new XHTMLExtensionProvider());

        // Group Chat Invitations
        pm.addExtensionProvider("x", "jabber:x:conference",
                new GroupChatInvitation.Provider());

        // Service Discovery # Items
        pm.addIQProvider("query", "http://jabber.org/protocol/disco#items",
                new DiscoverItemsProvider());

        // Service Discovery # Info
        pm.addIQProvider("query", "http://jabber.org/protocol/disco#info",
                new DiscoverInfoProvider());

        // Data Forms
        pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());

        // MUC User
        pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user",
                new MUCUserProvider());

        // MUC Admin
        pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin",
                new MUCAdminProvider());

        // MUC Owner
        pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner",
                new MUCOwnerProvider());

        // Delayed Delivery
        pm.addExtensionProvider("x", "jabber:x:delay",
                new DelayInformationProvider());

        // Version
        try {
            pm.addIQProvider("query", "jabber:iq:version",
                    Class.forName("org.jivesoftware.smackx.packet.Version"));
        } catch (ClassNotFoundException e) {
            // Not sure what's happening here.
        }

        // VCard
        pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());

        // Offline Message Requests
        pm.addIQProvider("offline", "http://jabber.org/protocol/offline",
                new OfflineMessageRequest.Provider());

        // Offline Message Indicator
        pm.addExtensionProvider("offline",
                "http://jabber.org/protocol/offline",
                new OfflineMessageInfo.Provider());

        // Last Activity
        pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider());

        // User Search
        pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider());

        // SharedGroupsInfo
        pm.addIQProvider("sharedgroup",
                "http://www.jivesoftware.org/protocol/sharedgroup",
                new SharedGroupsInfo.Provider());

        // JEP-33: Extended Stanza Addressing
        pm.addExtensionProvider("addresses",
                "http://jabber.org/protocol/address",
                new MultipleAddressesProvider());

        // FileTransfer
        pm.addIQProvider("si", "http://jabber.org/protocol/si",
                new StreamInitiationProvider());

        pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams",
                new BytestreamsProvider());

        // Privacy
        pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());

        pm.addIQProvider("command", "http://jabber.org/protocol/commands",
                new AdHocCommandDataProvider());
        pm.addExtensionProvider("malformed-action",
                "http://jabber.org/protocol/commands",
                new AdHocCommandDataProvider.MalformedActionError());
        pm.addExtensionProvider("bad-locale",
                "http://jabber.org/protocol/commands",
                new AdHocCommandDataProvider.BadLocaleError());
        pm.addExtensionProvider("bad-payload",
                "http://jabber.org/protocol/commands",
                new AdHocCommandDataProvider.BadPayloadError());
        pm.addExtensionProvider("bad-sessionid",
                "http://jabber.org/protocol/commands",
                new AdHocCommandDataProvider.BadSessionIDError());
        pm.addExtensionProvider("session-expired",
                "http://jabber.org/protocol/commands",
                new AdHocCommandDataProvider.SessionExpiredError());

        pm.addIQProvider("query", "http://jabber.org/protocol/disco#info",
                new DiscoverInfoProvider());
        pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());
        // pm.addExtensionProvider("status ","", new XMLPlayerList());

    }
}

Вызовите этот метод следующим образом

ServiceProviders.Register_Providers(ProviderManager.getInstance());

Поэтому попробуйте вызвать этот метод в начале вашего приложения или перед формированием соединения.

Надеюсь это поможет

person Sheraz Ahmad Khilji    schedule 12.03.2014
comment
Отлично, теперь я получаю ответ с одной стороны, и это потрясающе, большое спасибо, но теперь, как я могу ответить на сервер. например, я использую анализатор xmpp и отправляю клиенту запрос disco#items, который был получен моим клиентом, но клиент не ответил серверу. мне нужно добавить обработчик ответа или что-то в этом роде? - person Hassaan Rabbani; 12.03.2014
comment
Во-вторых, как я могу отправить необработанный xml-запрос на сервер с клиента? я тоже что-то упустил в коде? - person Hassaan Rabbani; 12.03.2014
comment
@HassaanRabbani Ник, чтобы знать, что вышеуказанное решение сработало. Я не слишком много играл с asmack xmpp, и у меня не было опыта использования запроса disco#items. Поэтому я предлагаю вам задать еще один вопрос для этого, чтобы люди, у которых больше опыта, чем я, могли помочь вам. Если приведенный выше ответ решил вашу проблему, пожалуйста, примите его :) - person Sheraz Ahmad Khilji; 12.03.2014
comment
приведенное выше решение сработало для одной проблемы, то есть получения IQ, а как насчет отправки IQ? как я могу отправить IQ клиенту с другого клиента или с клиента на сервер? - person Hassaan Rabbani; 12.03.2014
comment
Взгляните на эту groups.google.com/forum/#!topic /prosody-users/8IW2t2i45Uk и community.igniterealtime.org/thread/40941 - person Sheraz Ahmad Khilji; 12.03.2014
comment
Доступны ли эти функции в библиотеке Smack? - person Kamalakannan J; 10.01.2017

Для отправки вам на самом деле просто нужно создать строку xml и вернуться в getChildElementXML(), никаких других настроек не требуется.

Для получения ответа IQ сначала необходимо создать IQProvider и добавить в ProviderManager, сопоставив xmlns в объекте запроса. IQProvider используется для преобразования пакета ответа в ваш настраиваемый объект IQ. Затем вам нужно расширить PacketListener, и когда вы создаете объект подключения, добавьте к нему прослушиватель с PacketTypeFilter, чтобы он соответствовал вашему классу IQ. При правильной настройке провайдера и слушателя вы сможете получить ответ IQ.

Вот ссылка: https://billynyh.github.io/blog/2014/09/28/android-xmpp-dev/

person Kevin Chen    schedule 27.06.2018

При отправке самоопределяемого сообщения, например,

<iq id='123' type='get' from='client@xmpp/B' to='client2@xmpp/s2'><req var='read'><attr var='temprature'/></req></iq>

Вам нужно определить свой собственный IQ и отправить этот IQ:

public class MyIQ extends IQ {
        @Override
        public String getChildElementXML() {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("&lt;req var='read'&gt;&lt; attr var='temprature'/&gt;&lt;/req&gt;");
            return stringBuilder.toString();
        }
    }

    MyIQ packet = new MyIQ();
    packet.setType(IQ.Type.GET);
    packet.setFrom("client@xmpp/B");
    packet.setTo("client2@xmpp/s2");
    xmppConnection.sendPacket(packet);
person Z. Mei    schedule 29.06.2018