how to add roster with subscription mode "both"
Asked Answered
I

5

18

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("[email protected]","me",null)

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

Ichthyosis answered 27/4, 2011 at 10:27 Comment(0)
C
42

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('[email protected]');
connection.sendPacket(subscribe);

When Bob receives the request, he approves it:

Presence subscribed = new Presence(Presence.Type.subscribed);
subscribed.setTo('[email protected]');
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('[email protected]');
connection.sendPacket(subscribe);

And Alice needs to approve Bob's request:

Presence subscribed = new Presence(Presence.Type.subscribed);
subscribed.setTo('[email protected]');
connection.sendPacket(subscribed);

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

Cosper answered 25/5, 2011 at 22:41 Comment(11)
Hello. but where to write this two code for subscribe both sideGenitor
if i use Subscribed what i have to use JID here subscribed.setTo(jid); i am able to add entry to my account, but i am not getting presence of that entry.tell me what i to do for that.Perceive
@JoeHildebrand I am doning the things in same manner but not getting any subscription notification. Please have look #16816031Bairam
Why the bob again the send the request to alice after bob subscribed to alice.... can we implement in simple way like facebook request. if alice sends the request to bob. bob will accept it and then both are becoming friends @Joe HildebrandCandiscandle
@sravani: This is just the way XMPP works. You can hide this in your user interface; many clients do. The easiest way is if you get a 'subscribe' request from a contact where the roster subscription state is 'to', your client automatically responds with 'subscribed'.Cosper
Ya. i need to Handle in UI. But how can i detect the sybscription type is to or from or both...i have added this but it is throwing null pointer exception. connection.getRoster().getEntry(presence.getFrom()).getType());PLease suggest how can i handle that alice already sent the request to that bob and when bob got subscribe packet he is subscribed and he sent subscribe packet to alice again then this time alice should check whether alice already sent the request to bob or not if already sent then he should added bob as friend.Candiscandle
Instead of getType(), you probably have a getSubscription() method, or something similar.Cosper
excellent example @JoeHildebrand really appreciated answer. And i want to ask one question my scenario is that when user-A subscribe user-B then when user-B subscribed user-A then automatically user-B subscribe user a are u getting what i am trying to say.Roddy
@AliAshiq I think you're asking if subscriptions are always bi-directional. The answer is no, mostly. Some servers, clients, or libraries might mask that somewhat by automatically subscribing in response to subscription requests.Cosper
What would happen, if User2(Bob) does not exist on the server? So, now Alice sends a request to Bob, but bob, being unregistered, didnt receive the request. Now after 2 days, Bob registers himself. Now, how does pushes a subscription request to all those users who added them at first places?Civilization
Years later, API have changed but the flow itself is classic!Berri
N
10

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.

Neurilemma answered 24/5, 2011 at 23:44 Comment(6)
If user added from any other source, listen for packet listener and send Subscribe to jid, this is how it works, and you can see subscription as "both" in roster list. If type subscribed is used, then subscription will be from (roster sending request) and to(roster to whom request is sent)Figwort
Hello. but where to write this two code for subscribe both sideGenitor
RFC3921 is obsoleted by RFC6121. Also, your code doesn't make much sense, since you are subscribing, not unsubscribing, and "presence" isn't a variable currently in scope.Cosper
excellent example really appreciated answer. And i want to ask one question my scenario is that when user-A subscribe user-B then when user-B subscribed user-A then automatically user-B subscribe user a are u getting what i am trying to say.Roddy
I'm away from XMPP by the moment. You could ask another question in SO, I think.Australian
Each request and each response is a separate, non-automatic action, requiring an explicit choice by the user or by the software that they're running. Often, clients will auto-accept subscription requests from people you are subscribed to.Cosper
P
2

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
                }
            }
    
Pacien answered 29/1, 2014 at 10:7 Comment(0)
Q
1

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

Quent answered 12/3, 2014 at 13:13 Comment(0)
I
1

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();
    }
}
Inform answered 18/9, 2017 at 9:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.