how to add roster with subscription mode “both”

2019-01-31 09:23发布

问题:

i'm using smack 3.1.0, and when i add a roster,i can't get subscription "both". who can help me? below is my code:

Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.accept_all);
Roster roster = connection.getRoster();
roster.createEntry("buddy@test.com","me",null)

after the code execution, i observed in openfire the subscription is "to"

回答1:

Rewriting @mschonaker's answer to be a little more clear.

Both users need to subscribe to each other and accept the subscription request they received. Let's call them Alice and Bob. Alice sends a subscription request to Bob:

Presence subscribe = new Presence(Presence.Type.subscribe);
subscribe.setTo('bob@example.com');
connection.sendPacket(subscribe);

When Bob receives the request, he approves it:

Presence subscribed = new Presence(Presence.Type.subscribed);
subscribed.setTo('alice@example.com');
connection.sendPacket(subscribed);

Bob may also be interested in Alice's presence, so he subscribes to her:

Presence subscribe = new Presence(Presence.Type.subscribe);
subscribe.setTo('alice@example.com');
connection.sendPacket(subscribe);

And Alice needs to approve Bob's request:

Presence subscribed = new Presence(Presence.Type.subscribed);
subscribed.setTo('bob@example.com');
connection.sendPacket(subscribed);

Section 3.1 of RFC6121 is the current best reference for how this works.



回答2:

Both users need to subscribe to each other. By sending a presence subscription stanza. In Smack:

    Presence presence = new Presence(Presence.Type.subscribe);
    presence.setTo(jid);
    connection.sendPacket(presence);

Section 3.1 of the RFC6121 will give you the semantic details.



回答3:

Okay, I toiled hard at this for a couple of days and finally got things working. Thank you @Joe Hildebrand, your answer put me on the right track to solve this. I have implemented it with a manual subscription mode (ie. user needs to accept another user's request manually).

The server keeps pushing subscribe request to the user (upon re-login) if the user hasn't sent a subscribed or unsubscribed back. So what you can do is save the incoming subscribe requests locally in a list and display that as a "friend request list" for manual accept/reject. If your application gets restarted (and hence re-connects to server), the server will push subscribe requests again.

This is how it works:

  • User1 sends subscribe presence to User2.
  • Roster entry gets automatically created in User1's roster (but not in User2's roster).
  • User2 receives subscribe request from User1.
  • User2 sends back a subscribed presence to User2 (User2 > User1 subscription complete).
  • User2 checks if User1 is in User2's roster. User1 is not in User2's roster. User2 sends back a subscribe presence to User1.
  • Roster entry gets automatically created in User2's roster.
  • User1 receives subscribe presence from User2.
  • User1 checks if User2 is in User1's roster. User2 is in User1's roster. User1 sends back a subscribed presence to User2 (User2 > User1 subscription complete).

            final Presence newPresence = (Presence) packet;
            final Presence.Type presenceType = newPresence.getType();
            final String fromId = newPresence.getFrom();
            final RosterEntry newEntry = getRoster().getEntry(fromId);
    
            if (presenceType == Presence.Type.subscribe)
            {
                //from new user
                if (newEntry == null)
                {
                    //save request locally for later accept/reject
                    //later accept will send back a subscribe & subscribed presence to user with fromId
                    //or accept immediately by sending back subscribe and unsubscribed right now
                }
                //from a user that previously accepted your request
                else
                {
                    //send back subscribed presence to user with fromId
                }
            }
    


回答4:

If you are using open fire server you can also use User Service plugin which will create roster with subscription both...



回答5:

Same problem I was face but I got the solution how subscribe set 'both'

Below is sending subscription to user, when you added the user

 Presence pres = new Presence(Presence.Type.subscribed);
        pres.setPriority(24);
        pres.setMode(Presence.Mode.available);
        pres.setTo(friendJid);

        RoosterConnection.getConnection().sendStanza(pres);

and Receiving end put below method in connection class and presenceChanged is default method of RosterListener.

 @Override
public void presenceChanged(Presence presence) {
    mBus.post(presence);
    try {
        Presence pres = new Presence(Presence.Type.subscribed);
        pres.setTo(presence.getFrom());
        RoosterConnection.getConnection().sendStanza(pres);
    } catch (SmackException.NotConnectedException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}


标签: java xmpp smack