在做添加好友之间,必须要对xmpp的好友订阅有一定的了解,以前我不了解其中原理,盲目的做,以为添加到了各自的列表能够发消息就没事了,后来发现这样会导致很多问题,比如好友上下线无提醒,好友更新了vcard没有提示等一系列和好友相关的问题都出来了。
后来终于重视这个问题,查找相关资料,自行百度,发现很多资料都是只说了单边实现没有设计原理,事实上,那也不算真的实现了,现在我来说下原理和流程,希望对同是做即时通讯的同学们有所帮助;
我们知道,一个好友就对应一个RosterEntry,那我们看怎么来构造一个RosterEntry对象:
/** * Creates a new roster entry. * * @param user the user. 用户的jid * @param name the nickname for the entry. 指定给这个用户的昵称(其实我更愿意叫做备注) * @param type the subscription type. 这个用户和我的好友关系类型 * @param status the subscription status (related to subscriptions pending to be approbed).这个用户和我的好友状态 * @param connection a connection to the XMPP server.连接,不解释 */ RosterEntry(String user, String name, RosterPacket.ItemType type, RosterPacket.ItemStatus status, Roster roster, Connection connection) { this.user = user; this.name = name; this.type = type; this.status = status; this.roster = roster; this.connection = connection; }
上面的user和nickname还有Connection相信大家都知道了,Roster是花名册,相信大家也不陌生,通过XmppConnection.getRoster()可以获取到当前连接的花名册,我们重点来说下type和 status是干嘛用的;
凭我们用过qq的经验来看,添加好友是需要有几种状态的,比如我加了你,你同意了,但是你不想把动态让我看到,所以你不一定加我,这就是单方订阅,我加你,但是你拒绝了我 ,那我们就没啥关系,我加了你,你也加了我,那我们就是朋友了,我们是双方订阅,现在我们来捋一捋xmpp中有哪几种状态;
我们先看itemType是个什么鬼,点进去源码看一下;
public static enum ItemType { /** * The user and subscriber have no interest in each other's presence. */ none, /** * The user is interested in receiving presence updates from the subscriber. */ to, /** * The subscriber is interested in receiving presence updates from the user. */ from, /** * The user and subscriber have a mutual interest in each other's presence. */ both, /** * The user wishes to stop receiving presence updates from the subscriber. */ remove }
我们看到,这是一个枚举类型,上面都有注释,为了大家更清楚一些我就给大家翻译一下;none表示我和对方没有任何关系;to表示我发了我请求订阅了对方,对方同意了,但是他没有订阅我;from就是to反过来,他订阅了我,但是我没有订阅他;both表示我们双方互相订阅了;remove表示我想取消以前的订阅;
这种订阅状态是通过发送Presence来实现的。我们结合具体的应用场景来讲一下,怎么来订阅:
一、添加者 1、加入到 用户 roster列表 <iq type="set"><query xmlns="jabber:iq:roster"><item jid="13548583222@iz28sr0uiyaz" name="13548583222"></item></query></iq> 2、发送订阅presence <presence type="subscribe" to="13548583222@iz28sr0uiyaz"></presence> 3、对方同意,互相订阅 <presence type="subscribed" to="13548583222@iz28sr0uiyaz"></presence> 二、被添加者 接受好友添加 1 、发送接受请求订阅 <presence type="subscribed" to="13548583222@iz28sr0uiyaz"></presence> 2、添加到roster列表 <iq type="set"><query xmlns="jabber:iq:roster"><item jid="13548583222@iz28sr0uiyaz"></item></query></iq> 3、发送订阅 <presence type="subscribe" to="13548583222@iz28sr0uiyaz"></presence> 这时添加者发现已经在花名册中了,只需要发送subscribed就OK了,同时更新自己显示的列表; 添加者:<presence type="subscribed" to="13548583222@iz28sr0uiyaz"></presence>
上面这个流程通过发包的方式呈现,可能大家不是很明白,那么我画一个UML图加深理解;
到此,两个人就成为了双方的好友了,这时候只要有一方有更新,另一方就会受到与之相关的消息,比如vcard更新,状态更新等;
那么既然加了好友,我们来看下好友列表这块,如果我们只想显示双方都添加对方好友的列表,那我们需要做一个刷选,回归到前面的RosterEntry来,做一个判断:
if ( entry.getType()==ItemType.both) { User user = transEntryToUser(entry); tempUsers.add(user); UserManager.getInstance(mContext).saveUserDetail2Local(user); }
这样的话,好友列表就只有互相都订阅的好友了;
本文属原创,如需转载请注明出处,尊重劳动成果,谢谢!
有问题欢迎下面留言问题;
下面补充一点,关于删除好友出现了删除好友后无需处理就是好友的问题,于是我跟踪了下发送的包,正确的顺序应该是这样的:
如同增加一个名册条目, 如果服务器能成功地处理roster set那么它必须在该用户的名册中更新该条目, 发送一个roster push到该用户的所有感兴趣的资源(其中的'subscription'属性值设为"remove"), 并发送一个IQ result给初始的资源; 详见章节2.3. 另外, 该用户的服务器可能需要生成一个或更多subscription相关的presence节, 如下: 如果该用户对该联系人有一个出席信息订阅, 那么该用户的服务器必须发送一个type为"unsubscribe"的presence节给该联系人(为了对该联系人的出席信息取消订阅). 如果该联系人对该用户有一个出席信息订阅, 那么该用户的服务器必须发送一个type为"unsubscribed"的presence节给该联系人(为了取消该联系人对该用户的订阅). 如果出席信息订阅是相互的, 那么该用户的服务器必须同时发送type为"unsubscribe"presence节和type为"unsubscribed"的的presence节给该联系人.
也就是说,我们需要对于互相订阅的用户,我们需要发送两个presence:
Presence.Type.unsubscribe,和Presence.Type.unsubscribed,同时,我们需要从花名册中移除这个用户:
roster.removeEntry(entry);
相关推荐
Asmack是一个Android平台上的XMPP(Extensible Messaging and Presence Protocol)库,它允许开发者创建支持聊天、好友搜索等基本IM功能的应用。本项目提供了一套基于Asmack的在线聊天源代码,经过配置和调试后,...
其中用户管理模块包含登录、注册、信息资料维护三个子模块 匹配好友模块包含搜索好友、匹配好友两个子模块 即时通讯模块包含文字聊天、图片发送、语音发送以及群聊四个子模块。文字聊天主界面选择MessageFragment,...
7. **联系人管理**:实现Roster功能,获取和管理好友列表,支持添加、删除、搜索好友。同时,处理好友的在线状态更新。 8. **推送通知**:当应用在后台运行或者完全关闭时,通过Google的Firebase Cloud Messaging ...
win7修复本地系统工具
《自动化专业英语》04-Automatic-Detection-Block(自动检测模块).ppt
《计算机专业英语》chapter12-Intelligent-Transportation.ppt
内容概要:本文详细介绍了基于西门子S7-1200博图平台的3轴伺服螺丝机程序。该程序使用SCL语言编写,结合KTP700组态和TIA V14及以上版本,实现了对X、Y、Z三个轴的精密控制。文章首先概述了程序的整体架构,强调了其在自动化控制领域的高参考价值。接着深入探讨了关键代码片段,如轴初始化、运动控制以及主程序的设计思路。此外,还展示了如何通过KTP700组态实现人机交互,并分享了一些实用的操作技巧和技术细节,如状态机设计、HMI交互、异常处理等。 适用人群:从事自动化控制系统开发的技术人员,尤其是对西门子PLC编程感兴趣的工程师。 使用场景及目标:适用于希望深入了解西门子S7-1200博图平台及其SCL语言编程特点的学习者;旨在帮助读者掌握3轴伺服系统的具体实现方法,提高实际项目中的编程能力。 其他说明:文中提供的代码示例和设计理念不仅有助于理解和学习,还能直接应用于类似的实际工程项目中。
内容概要:本文详细探讨了五种非线性滤波器(卡尔曼滤波(KF)、扩展卡尔曼滤波(EKF)、无迹卡尔曼滤波(UKF)、粒子滤波(PF)和变维卡尔曼滤波(VDKF))在水下长基线定位(LBL)系统中的应用。通过对每种滤波器的具体实现进行MATLAB代码展示,分析了它们在不同条件下的优缺点。例如,KF适用于线性系统但在非线性环境中失效;EKF通过雅可比矩阵线性化处理非线性问题,但在剧烈机动时表现不佳;UKF利用sigma点处理非线性,精度较高但计算量大;PF采用蒙特卡罗方法,鲁棒性强但计算耗时;VDKF能够动态调整状态维度,适合信标数量变化的场景。 适合人群:从事水下机器人(AUV)导航研究的技术人员、研究生以及对非线性滤波感兴趣的科研工作者。 使用场景及目标:①理解各种非线性滤波器的工作原理及其在水下定位中的具体应用;②评估不同滤波器在特定条件下的性能,以便为实际项目选择合适的滤波器;③掌握MATLAB实现非线性滤波器的方法和技术。 其他说明:文中提供了详细的MATLAB代码片段,帮助读者更好地理解和实现这些滤波器。此外,还讨论了数值稳定性问题和一些实用技巧,如Cholesky分解失败的处理方法。
VMware-workstation-full-14.1.3-9474260
DeepSeek系列-提示词工程和落地场景.pdf
javaSE阶段面试题
《综合布线施工技术》第5章-综合布线工程测试.ppt
安川机器人NX100使用说明书.pdf
内容概要:本文详细介绍了将M7120型平面磨床的传统继电器控制系统升级为基于西门子S7-1200 PLC的自动化控制系统的过程。主要内容涵盖IO分配、梯形图设计和组态画面实现。通过合理的IO分配,确保了系统的可靠性和可维护性;梯形图设计实现了主控制逻辑、砂轮升降控制和报警逻辑等功能;组态画面则提供了友好的人机交互界面,便于操作和监控。此次改造显著提高了设备的自动化水平、运行效率和可靠性,降低了维护成本。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是熟悉PLC编程和控制系统设计的专业人士。 使用场景及目标:适用于需要进行老旧设备升级改造的企业,旨在提高生产设备的自动化水平和可靠性,降低故障率和维护成本。具体应用场景包括但不限于金属加工行业中的平面磨床等设备的控制系统改造。 其他说明:文中还分享了一些实际调试中的经验和技巧,如急停逻辑的设计、信号抖动的处理方法等,有助于读者在类似项目中借鉴和应用。
chromedriver-linux64-136.0.7103.48.zip
IMG_20250421_180507.jpg
《网络营销策划实务》项目一-网络营销策划认知.ppt
Lianantech_Security-Vulnerabil_1744433229
MybatisCodeHelperNew2019.1-2023.1-3.4.1
【深度学习部署】基于Docker的BERT模型训练与API服务部署:实现代码复用与模型共享