18

我正在使用 smack 3.1.0,当我添加花名册时,我无法订阅“两者”。谁能帮我?下面是我的代码:

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

代码执行后,我在 openfire 中观察到订阅是“to”

4

5 回答 5

42

重写@mschonaker 的答案更清楚一点。

两个用户都需要互相订阅接受他们收到的订阅请求。让我们称他们为爱丽丝和鲍勃。Alice 向 Bob 发送订阅请求:

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

当 Bob 收到请求时,他批准了它:

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

Bob 也可能对 Alice 的存在感兴趣,所以他订阅了她:

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

而 Alice 需要批准 Bob 的请求:

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

RFC6121 的第 3.1 节是当前关于其工作原理的最佳参考。

于 2011-05-25T22:41:32.217 回答
10

两个用户都需要相互订阅。通过发送出席信息订阅节。在 Smack 中:

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

RFC6121 的第 3.1 节将为您提供语义细节。

于 2011-05-24T23:44:27.047 回答
2

好的,我为此努力了几天,终于让事情正常了。谢谢@Joe Hildebrand,您的回答让我走上了解决这个问题的正确轨道。我已经用手动订阅模式实现了它(即用户需要手动接受另一个用户的请求)。

如果用户没有发回订阅或取消订阅,服务器会继续向用户推送订阅请求(在重新登录时)。因此,您可以将传入的订阅请求保存在本地列表中,并将其显示为“好友请求列表”以供手动接受/拒绝。如果您的应用程序重新启动(并因此重新连接到服务器),服务器将再次推送订阅请求。

这是它的工作原理:

  • User1 向 User2 发送订阅状态。
  • 名册条目在 User1 的名册中自动创建(但不在 User2 的名册中)。
  • User2 收到来自 User1 的订阅请求。
  • 用户 2 向用户 2 发回订阅状态(用户 2 > 用户 1 订阅完成)。
  • User2 检查 User1 是否在 User2 的花名册中。User1 不在 User2 的名单中。User2 向 User1 发回订阅状态。
  • 名册条目在 User2 的名册中自动创建。
  • User1 接收来自 User2 的订阅状态。
  • User1 检查 User2 是否在 User1 的名册中。User2 在 User1 的名单中。用户 1 向用户 2 发回订阅状态(用户 2 > 用户 1 订阅完成)。

            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
                }
            }
    
于 2014-01-29T10:07:45.037 回答
1

如果您使用的是开放式服务器,您还可以使用 用户服务插件,该插件将创建同时订阅的名册...

于 2014-03-12T13:13:27.220 回答
1

我遇到了同样的问题,但我得到了解决方案如何订阅设置“两者”

当您添加用户时,以下是向用户发送订阅

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

        RoosterConnection.getConnection().sendStanza(pres);

并且接收端放在连接类中的方法下面,presenceChanged 是 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();
    }
}
于 2017-09-18T09:48:14.803 回答