Search code examples
androidsmack

How to know online or offline of user in smack in one to one chat?


I have tried this code and all the snippet available still cannot able to receive the online or offline presence of the user. Please help me. Thanks in advance.

fun checkStatus() {
    val jid = JidCreate.entityBareFrom("QTX69RGLVQ3VVU8QUB@localhost")

    var roster = Roster.getInstanceFor(connection)
    var availability = roster.getPresence(jid);
    var  userMode = availability.getMode();
    retrieveState_mode(userMode, availability.isAvailable)
}

fun retrieveState_mode(userMode: Presence.Mode, isOnline:Boolean):Int {
    var userState = 0;
    if(userMode == Presence.Mode.dnd) {
        userState = 3;
    } else if (userMode == Presence.Mode.away || userMode == Presence.Mode.xa) {
        userState = 2;
    } else if (isOnline) {
        userState = 1;
    }
    return userState
}

Always I'm getting as 0


Solution

  • First thing first. If you read this:

    https://xmpp.org/extensions/xep-0162.html

    you will find this: subscription='both': You and the contact are interested in each other's presence information.

    So if your roster is set to subscription='both', you both must be in each other roster (lets say buddy request and approval in both directions) to listen to each others presence information.

    So knowing previous, the way I have done it using Smack is:

    //Created presence packet listener
    private StanzaListener presencePacketListener;
    
    //In my connection creating
    private XMPPTCPConnection createConnection() throws XmppStringprepException {
            XMPPTCPConnectionConfiguration.Builder config =  XMPPTCPConnectionConfiguration.builder();
            .......
            config.setSendPresence(true);
            .......
            return new XMPPTCPConnection(config.build());
    }
    
    //Then in login method
    public void login() throws SmackInvocationException, XmppStringprepException {
            connect();
            try {
                //Add presencePacketListener to listen for subscribed users (Roster) presence
                con.addSyncStanzaListener(presencePacketListener, new StanzaTypeFilter(Presence.class));
                //Actual login
                .....
                onConnectionEstablished();
            } catch(Exception e) {          
                throw exception;
            }
    }
    
    // onConnectionEstablished method
    private void onConnectionEstablished() {
            if (state != State.CONNECTED) {         
                sendPacket(new Presence(Presence.Type.available));
            }
    }
    

    When doing

    sendPacket(new Presence(Presence.Type.available));

    all users in your roster subscription will receive this presence packet. That will be processed in

    presencePacketListener

    that we have registered earlier on login.

    //PresencePacketListener
    public class PresencePacketListener implements StanzaListener {
        private Context context;
    
        PresencePacketListener(Context context) {
            this.context = context;
        }
    
        @Override
        public void processStanza(Stanza packet) {
            Presence presence = (Presence)packet;
            Presence.Type presenceType = presence.getType();
            //Do sth with presence
        }
    }