0
votes

I have this Android application which I've been trying to set a XMPP MultiUserChat.

As far as connecting to XMPP, loging-in and creating a MUC ( as well as joining an already created one ) everything is going alright.

I just seem to be failing at properly listening to the sent messages, and I'm not sure why.

I have worked a few times before with XMPP using Javascript ( StropheJS with Bosh ), so I'm somewhat acquainted with its protocols.

As I have already tried what's being suggested at the following post ( the only post I found about the matter ) :

How to properly listen for MultiUserChat in Smack?

So, I've decided to ask you some directions, as I think it's probably a mere setup that I've been missing all along.

So, for simplicity's sake, I'm going to provide my entire sequence.

I created a Service so my XMPP connection can be pervasive throughout the entire application. As I need to connect to XMPP as soon as my app logs in as well and the MUC rooms are going to be used only further down in other activities. Well, you get the picture. So, here's the code:

(sorry if it's a bit too long, I don't mean to be annoying, all I want is to provide everything is needed in order to solve it )

//everything is alright here.
//it's connecting correctly to XMPP
public void connect()
{

    Thread t = new Thread(new Runnable() {

        @Override
        public void run()
        {
            boolean flConnected = false;
            System.setProperty("smack.debugEnabled", "true");
            SmackConfiguration.setDefaultPacketReplyTimeout(10000);


            ConnectionConfiguration ConnectionConfiguration = new ConnectionConfiguration(Host, Port);
            ConnectionConfiguration.setSecurityMode(org.jivesoftware.smack.ConnectionConfiguration.SecurityMode.disabled);

            ConnectionConfiguration.setDebuggerEnabled(true);
            ConnectionConfiguration.setSendPresence(true);

            connection = new XMPPTCPConnection(ConnectionConfiguration);

            try
            {
                connection.connect();
                login();
            }
            //there are many exceptions being treated, I 
            //suppressed them here for simplicity's sake
            catch (Exception e)
            {
                Log.e(TAG, "connection exception: " + e.getMessage());
            }


        }
    });
    t.start();
}

public void login()
{
    try
    {
        connection.login(this.User, Pwd);

        Presence presence = new Presence(Presence.Type.available);
        connection.sendPacket(presence);
        this.setLoginAttempts();           

    }
    catch (Exception e)
    {
        Log.e(TAG, "connection exception: "+e.getMessage());
    }
}

So, when the user should be the admin of a certain chatgroup, I create the group passing the GroupName (id)

public void createGroup(String strRoom)
{
    try
    {
        muc = new MultiUserChat(connection, strRoom+"@"+this.GroupChat);
        muc.create(this.User);

        Form form = muc.getConfigurationForm();
        Form submitForm = form.createAnswerForm();



        for (Iterator fields = form.getFields().iterator(); fields.hasNext();) {
            FormField field = (FormField) fields.next();
            if (!FormField.TYPE_HIDDEN.equals(field.getType())
                    && field.getVariable() != null) {
                    submitForm.setDefaultAnswer(field.getVariable());
            }
        }

        List<String> owners = new ArrayList<>();
        owners.add(this.User + "@"+this.Host);

        muc.sendConfigurationForm(submitForm);                        

        //here, it's another FAILED attempt of putting the 
        //listener to an async class. Didn't work at all!!
        //just kept it here so you can see my attempts!
        //new MessageRunner().execute(connection);           

    }
    catch (Exception ex)
    {
        Log.e(TAG, " exception :"+ex.getMessage());
    }
}

And when it's merely an participant, it joins the group:

public void joinGroup(String strRoom)
{
    try
    {
        DiscussionHistory history = new DiscussionHistory();
        history.setMaxStanzas(50);
        muc = new MultiUserChat(connection, strRoom+"@"+this.GroupChat);
        muc.join(strRoom, this.Pwd, history, connection.getPacketReplyTimeout());

        this.addMessageListener(muc);

        this.listen2Group();
    }
    catch (Exception ex)
    {
        Log.e(TAG, "Exception :"+ex.getMessage());
    }
}

So, I have 3 methods which I used as attempts to make the user properly listen to the incomming messages.

One of them is being set right after the Login: setListener(connection);

The other two are being called after the user joins the GroupChat:

addMessageListener(muc); and listen2Group();

I'm leaving them all here so you can see how far I have gone:

private void addMessageListener(MultiUserChat muc)
{
    //it's never coming here! never ever!!!
    if(null != muc){
        muc.addMessageListener(new PacketListener() {
            @Override
            public void processPacket(Packet packet) {
                Log.i("processPacket", "receiving message");
            }
        });
    }
}

private void listen2Group()
{

    //also, NEVER EVER getting here at any time!!
    PacketFilter filter = new MessageTypeFilter(Message.Type.groupchat);


    connection.addPacketListener(new PacketListener() {
        @Override
        public void processPacket(Packet packet) throws NotConnectedException
        {
            Message message = (Message) packet;
            if (message.getBody() != null)
            {

                //message should be treated here, 
                //but I suppressed it as well.
            }
        }
    }, filter);
}

public void setListener(XMPPConnection cnx)
{
    this.connection = cnx;
    if (connection != null) {

        PacketFilter filter = new MessageTypeFilter(Message.Type.groupchat);
        connection.addPacketListener(new PacketListener() {
            @Override
            public void processPacket(Packet packet) {
                Message message = (Message) packet;
                if (message.getBody() != null) 
                {                        
                   //message will be treated here.
                }
            }
        }, filter);
    }

}

And here's how I'm sending the messages:

public void sendMessage(String msgText)
{
    try
    {

        Message msg = new Message();
        msg.setBody(msgText);
        msg.setType(Message.Type.groupchat);


        muc.sendMessage(msg);

        //I tried sending with this one as well, nope!
        //connection.sendPacket(msg);
    }
    catch(Exception ex)
    {
        Log.e(TAG, " exception :"+ex.getMessage());
    }
}

So, probably you already saw where I'm doing it wrong. But I've been working on it for days. Nothing comes through!

When I check at my server ( openfire ), all the users are being set to online, the are being properly logged into the MUC as well, when the messages are sent, nothing happens!

I place the breakpoints at all the listeners I showed you, but they never fire, no matter what I do. The message is sent, but it never arrives anywhere.

Any ideas?

1

1 Answers

0
votes

For future references ( as smack in its current version is not all the way documented )

I found what was wrong with the listeners!

It turn out that I was not setting the destination to the chatgroup.

As it's by nature a GroupChat, I had assumed it didn't need to set the receiver to the messages.

Everything was needed to fix that, was at my sendMessage method, an extra line:

msg.setTo(this.room+"@"+my_service_address);

http://xmpp.org/extensions/xep-0045.html

At XEP-0045 it states that for groupchat it must have a destination address in order to work properly.

"Messages sent within multi-user chat rooms are of a special type "groupchat" and are addressed to the room itself (room@service), then reflected to all occupants."