`
handsomeliuyang
  • 浏览: 314908 次
  • 性别: Icon_minigender_1
  • 来自: 益阳
社区版块
存档分类
最新评论

Androidpn里的Xmpp的理解

阅读更多

  XMPP(可扩展通讯和表示协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线探测。这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息。用xmpp来实现android的push功能,感觉有点大材小用了,xmpp本身是一种即时通信协议。

  xmpp是一种用于即时通信的协议,使用过程有点类似于我们使用QQ的过程,其使用过程分为三步:

  1. 连接服务器,就好像打开QQ软件,看代码:

if(!mXmppManager.isConnected()) {
	ConnectionConfiguration config = new ConnectionConfiguration(mHost, mPort);
	config.setSecurityMode(SecurityMode.required);
	config.setSASLAuthenticationEnabled(false);
	config.setCompressionEnabled(false);
	
	XMPPConnection connection = new XMPPConnection(config);
	mXmppManager.setConnection(connection);
	try {
		connection.connect();
		Log.i(LOGTAG, "XMPP connected successfully");
		/**
		 * 这个就是对于通信的xml文本进行解析的解析器,再把信息转换成IQ,这个相当于QQ的聊天信息
		 * 如果要用这个协议,其IQ的子类和IQProvider要进行重写
		 */
		ProviderManager.getInstance().addIQProvider("notification",
				"androidpn:iq:notification",
				new NotificationIQProvider());
		
	} catch (XMPPException e) {
		Log.d(LOGTAG, "the connection is error ... ");
	}
	mXmppManager.runTask();
} else {
	Log.i(LOGTAG, "XMPP connected already");
	mXmppManager.runTask();
}

 

这一步主要是连接服务器,还有设置一些连接的参数,还有设置连接的解析器。

  2. 如果没有用户,注册新的帐号和密码

if(!mXmppManager.isRegistered()){
	final String newUsername = newRandomUUID();
	final String newPassword = newRandomUUID();
	Registration registration = new Registration();
	
	PacketFilter packetFilter = new AndFilter(new PacketIDFilter(
			registration.getPacketID()), new PacketTypeFilter(
			IQ.class));
	PacketListener packetListener = new PacketListener() {
		@Override
		public void processPacket(Packet packet) {
			// 服务器回复客户端
            if(packet instanceof IQ) {
            	IQ response = (IQ) packet;
            	if(response.getType() == IQ.Type.ERROR) { // 注册失败
            		if (!response.getError().toString().contains(
                            "409")) {
                        Log.e(LOGTAG,"Unknown error while registering XMPP account! " + response.getError().getCondition());
                    }
            	} else if(response.getType() == IQ.Type.RESULT) { // 注册成功
            		mXmppManager.setUsername(newUsername);
            		mXmppManager.setPassword(newPassword);
            		// 把用户名和密码都保存到磁盘
            		Editor editor = mSharedPrefs.edit();
            		editor.putString(Contants.XMPP_USERNAME, newUsername);
            		editor.putString(Contants.XMPP_PASSWORD, newPassword);
            		editor.commit();
            		
            		mXmppManager.runTask();
            	}
            }
		}
	};
	// 给注册的Packet设置Listener,因为只有等到正真注册成功后,我们才可以交流
	mConnection.addPacketListener(packetListener, packetFilter);
	
	registration.setType(IQ.Type.SET);
	registration.addAttribute("username", newUsername);
    registration.addAttribute("password", newPassword);
	
	// 向服务器端,发送注册Packet包,注意其中Registration是Packet的子类
	mConnection.sendPacket(registration);
	
} else { // 已经注册过了
	mXmppManager.runTask();
}

 

 只要连接了服务器了,客户端就可以向服务器端发送消息,发送是以Packet(数据包)来进行发送的,这个类有很多的子类,注册的子类为Registration。

 

 

 

 

 还有要注意的是,上面的addPacketListener方法不是给所有发送的数据包设置listener,而只是针对这次的注册Packet。

  3. 用注册的帐号和密码进行登陆(像用QQ号帐进行登陆一样)

// 判断是否已经登陆过了,是否是在登陆状态
if(!mXmppManager.isAuthenticated()) {
	try {
		mConnection.login(mUsername, mPassword, "AndroidpnClient");
		// 设置XmppConnection的监听器
		if(mXmppManager.getConnectionListener() != null) {
			mConnection.addConnectionListener(mXmppManager.getConnectionListener());
		}
		// 设置服务器端推送的监听器
		PacketFilter packetFilter = new PacketTypeFilter(NotificationIQ.class);
		PacketListener packetListener = mXmppManager.getNotificationPacketListener();
		mConnection.addPacketListener(packetListener, packetFilter);
		
		mXmppManager.runTask();
	} catch (XMPPException e) {
		// 登陆失败,应该重试 
        String INVALID_CREDENTIALS_ERROR_CODE = "401";
        String errorMessage = e.getMessage();
        // 如果只是因为没有注册,则进行重新注册
        if (errorMessage != null && errorMessage.contains(INVALID_CREDENTIALS_ERROR_CODE)) {
        	mXmppManager.reregisterAccount(); 
            return;
        }
        mXmppManager.startReconnectionThread();
	} catch (Exception e) { // 有可能mConnection都为空
		Log.e(LOGTAG, "LoginTask.run()... other error");
		Log.e(LOGTAG, "Failed to login to xmpp server. Caused by: " + e.getMessage());
		mXmppManager.startReconnectionThread(); // 启动重连线程
	}
} else {
	mXmppManager.runTask();
}

  

  这里设置了连接的监听器mConnection.addConnectionListener(),连接过程中有可以连接突然中断,连接出错等等问题,要进行监听。

  设置服务器推送信息的Listener,接收到信息后,显示给用户。
  如果出错的原因是401(无效的用户名和密码,则应该进行重新注册,再连接)

 

对于服务器push过来的信息进行处理,是在PacketListener类里面,这个接口里,只要实现一个方法processPacket(Packet packet),从传过来的Packet(数据包)里获取自己需要的数据:

public void processPacket(Packet packet) {
    if(packet instanceof NotificationIQ) {
    	NotificationIQ notification = (NotificationIQ) packet;
    	if(notification.getChildElementXML().contains("androidpn:iq:notification")) {
    		String notificationId = notification.getId();
            String notificationApiKey = notification.getApiKey();
            String notificationTitle = notification.getTitle();
            String notificationMessage = notification.getMessage();
            String notificationUri = notification.getUri();

            Intent intent = new Intent(Contants.ACTION_SHOW_NOTIFICATION);
            intent.putExtra(Contants.NOTIFICATION_ID, notificationId);
            intent.putExtra(Contants.NOTIFICATION_API_KEY,notificationApiKey);
            intent.putExtra(Contants.NOTIFICATION_TITLE,notificationTitle);
            intent.putExtra(Contants.NOTIFICATION_MESSAGE, notificationMessage);
            intent.putExtra(Contants.NOTIFICATION_URI, notificationUri);

            mXmppManager.getContext().sendBroadcast(intent);
    	}
    }
}

 

 

对于Androidpn项目的整体代码分析,看下一遍文章。

 

 

 

 

5
0
分享到:
评论
6 楼 天涯海角262253 2015-05-28  
5 楼 u012398365 2014-10-14  
眼拙呀,直接new一个XmppManager对象,connect就可以了。
4 楼 u012398365 2014-10-14  
服务端启动了,客户端安装成功后,在哪注册设备呢?
3 楼 wenjiefeng 2012-10-14  
请问一下,在andrioidpn-client客户端源码里,NotificationDetailsActivity这个类里,下面的参数都是什么意思呢
Intent intent = getIntent();
        String notificationId = intent
                .getStringExtra(Constants.NOTIFICATION_ID);
        String notificationApiKey = intent
                .getStringExtra(Constants.NOTIFICATION_API_KEY);
        String notificationTitle = intent
                .getStringExtra(Constants.NOTIFICATION_TITLE);
        String notificationMessage = intent
                .getStringExtra(Constants.NOTIFICATION_MESSAGE);
        String notificationUri = intent
                .getStringExtra(Constants.NOTIFICATION_URI);
      Log.i("test", "notificationId===============" + notificationId);
       Log.i("test", "notificationApiKey============" + notificationApiKey);
       Log.i("test", "notificationTitle============" + notificationTitle);
       Log.i("test", "notificationMessage=================" + notificationMessage);
       Log.i("test", "notificationDistance========distance=====111====" + notificationDistance);
       Log.i("test", "notificationUri===============" + notificationUri);
    疑惑1、   这几个参数代表什么意思呢,  notificationId;  notificationApiKey; notificationTitle;     notificationMessage;   notificationUri;
我看源码里好几处都用到这几个参数 ,
  疑惑2、  现在服务端已经能将消息推送到服务端了并增加了一些参数,推送的消息里增加了距离distance等参数,应该在客户端的哪个类里获取这些值呢?
如何处理呢?
谢谢了
2 楼 .荭蓦紡 2012-05-20  
NotificationIQ   这里IQ是啥意思?
1 楼 flytosea 2012-03-14  
哥们写的不错 ,能聊聊吗

相关推荐

    工业接线检测系统中的视觉匹配技术与图像处理算法设计及其应用场景

    内容概要:本文档介绍了基于视觉匹配的工业装配智能识别系统的具体设计方案,旨在实现自动化、高精度接线检测。文中详细描述了系统的硬件构成、关键技术和处理流程,强调了从图像平滑到OCR文字提取等多个步骤的具体实施方式及其重要性,并阐述了系统对于提高工业生产质量评估效率的作用。此外,文档还探讨了所使用各类图像处理与深度学习方法的有效性和实际应用潜力,提供了较为完整的系统可行性分析。 适用人群:涉及图像处理技术研究的科研人员、从事工业自动化生产的管理人员和技术工作者。 使用场景及目标:适用于需要高精度识别接线正确性的各种工业生产线。其主要目标是在保证高效的同时尽可能减少人工介入,以确保检测的一致性和精确度,从而降低生产成本并提高产品合格率。 其他说明:系统涵盖了多项前沿科技,如机器视觉领域的图像平滑技术、边缘检测算法、图像匹配算法以及AI驱动的文字识别技术(OCR)。这些共同构成了完整的接线状态分析链路,可用于实时监控生产环节中接线情况。

    基于阶梯碳交易成本的含电转气-碳捕集(P2G-CCS)耦合的综合能源系统低碳经济优化调度,采用(Matlab+Yalmip+Cplex) 考虑P2G设备、碳捕集电厂、风电机组、光伏机组、CHP机组、燃

    基于阶梯碳交易成本的含电转气-碳捕集(P2G-CCS)耦合的综合能源系统低碳经济优化调度,采用(Matlab+Yalmip+Cplex) 考虑P2G设备、碳捕集电厂、风电机组、光伏机组、CHP机组、燃气锅炉、电储能、热储能、烟气存储罐。

    灵活而强大的Python数据分析操作库,提供类似于R数据框架对象的标记数据结构,统计函数等等.zip

    python

    二开白色UI汇汇通运营级 K线都正常的版本,运营级,接单、运营

    从朋友那换来的,白色UI,二开的版本,不喜欢之前那个黑色UI的,可以看这个了,白色的看起来,精神了不少。 K线都正常的版本,运营级,接单、运营都没问题。

    springboot187社区养老服务平台的设计与实现.zip

    1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。

    非官方的抖音API包装在Python.zip

    python

    Python中的贝叶斯建模和概率编程.zip

    python

    springboot172基于springboot的二手车交易系统的设计与实现.zip

    1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。

    matlab实现扩展卡尔曼滤波器(EKF)三维同步定位与建图(SLAM)及LQR轨迹控制研究-卡尔曼滤波-轨迹控制

    内容概要:该文章聚焦于无人机在复杂环境中实现自主导航与精确定位的技术难点,特别提出了一种基于扩展卡尔曼滤波器(EKF)进行三维同步定位与建图(SLAM)的方法,并结合线性二次型调节器(LQR)优化轨迹控制策略。具体内容涵盖系统的运动和观测模型建立、EKF的工作原理及其更新步骤、LQR的设计思路以及详细的MATLAB代码实现。文中不仅提供了完整的仿真环境设置,还在实验部分展示了定位精度提升、轨迹跟踪效果显著和地图构建的实际结果。 适用人群:研究人员、工程师以及对无人机动态系统感兴趣的学者和技术爱好者。 使用场景及目标:①解决无人机在复杂环境下精确导航和地图构建问题;②优化无人机沿预定路径飞行的能力,增强控制稳定性;③适用于学术研究和技术开发等领域。 其他说明:本文通过详尽的数学推导和代码实例,帮助读者理解EKF和LQR的应用背景、实施细节及其优势。此外,作者针对现有技术和未来研究趋势进行了讨论,指出了可能的发展方向。阅读时应注意实验条件对结论的影响,同时参考提供的完整MATLAB代码,有助于加深理解和实操能力。

    Python原生操作系统原生GUI工具包.zip

    python

    高质量的QR码生成器库在Java TypeScriptJavaScript Python Rust C.zip

    python

    Matlab simulink电力电子单项全波整流电路仿真

    《Matlab Simulink电力电子单项半波整流电路仿真》是基于Matlab/Simulink平台的电力电子单相半波整流电路仿真项目,旨在帮助用户通过仿真模型深入理解单相半波整流电路的工作原理、性能特点以及参数调节对电路行为的影响。该仿真模型用于模拟单相交流电源输入,通过半波整流方式将交流电转换为直流电,广泛应用于低功率的直流电源供电系统、低功率电池充电器等领域。 一、单项半波整流电路基本原理 单相半波整流电路是一种最简单的整流电路,它仅利用交流电源的半个周期来进行能量转换,通常采用二极管作为整流元件。半波整流器可以将交流信号的正半周期转换为直流电,但输出电压存在明显的波动,因此通常需要额外的滤波电路来平滑输出。 工作原理: 交流输入电源:输入的交流电压周期性变化,从零值增至最大值,然后反向变化,最终回到零值,完成一个周期。 整流元件(二极管):在正半周期,二极管导通,将交流电转化为直流电;在负半周期,二极管不导通,因此没有电流流通,输出电压为零。 输出直流电压:由于单相半波整流只利用了交流信号的正半周期,因此输出的直流电压在每个周期内会出现波动,表现为脉动直流。 电路组成:

    基于matlab的二维小波相干分析,以空气质量数据为例 进行二维小波相干分析

    基于matlab的二维小波相干分析,以空气质量数据为例。 进行二维小波相干分析。

    MMC冷热冗余故障控制simulink仿真 0.295s SM1断路 0.3s SM1旁路开关闭合 0.5s SM2短路 0.505s SM2旁路开关闭合 0.7s 冷备用模块投入 0.995s SM

    MMC冷热冗余故障控制simulink仿真 0.295s SM1断路 0.3s SM1旁路开关闭合 0.5s SM2短路 0.505s SM2旁路开关闭合 0.7s 冷备用模块投入 0.995s SM3断路 1s SM3旁路开关闭合 1.2s SM4断路 1.205s SM4旁路开关闭合

    springboot127基于Springboot技术的实验室管理系统.zip

    1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。

    Python文件的格式化器.zip

    python

    基于51单片机的电梯控制系统 操作说明: 1.图中绿灯为电梯上行指示灯、黄灯为下行指示灯、红灯为报警指示灯 2.电梯初始状态位于一楼,在一楼的用户可直接按下电梯内部按钮,按后动电梯开始运行 3.在

    基于51单片机的电梯控制系统 操作说明: 1.图中绿灯为电梯上行指示灯、黄灯为下行指示灯、红灯为报警指示灯。 2.电梯初始状态位于一楼,在一楼的用户可直接按下电梯内部按钮,按后动电梯开始运行。 3.在任一层楼的用户,可以通过电梯外部的按钮请求电梯,电梯到达后通过内部按钮确定目标层。 注意:启动按钮相当于关门,电梯内部的请求都要按启动后电梯才会运行。

    Muc知识图谱-第二次实验报告实验代码

    Muc知识图谱_第二次实验报告实验代码

    Python书籍可以在线免费阅读或下载.zip

    python

    分布式Server:Server

    这段代码是一个使用DDS(Data Distribution Service,数据分发服务)API的订阅者应用示例。DDS是一种中间件协议,用于在分布式系统中发布和订阅数据。该代码示例展示了如何创建一个订阅者,接收Grade类型的数据,计算三个成绩的平均值,并将结果以AverageGrade类型的数据发布出去。以下是对代码主要部分的解析和一些潜在问题的指出: 主要部分解析 创建参与者(Participant): 使用DomainParticipantFactory创建一个参与者,该参与者在指定的域ID中运行。 创建订阅者(Subscriber)和发布者(Publisher): 在参与者下分别创建订阅者和发布者。 注册数据类型: 注册Grade和AverageGrade数据类型,这是DDS通信的基础。 创建主题(Topic): 为Grade和AverageGrade数据类型分别创建主题。 创建数据读取器(DataReader)和数据写入器(DataWriter): 在订阅者下创建Grade数据读取器,在发布者下创建AverageGrade数据写入器。 数据接收与处理: 在UserDat

Global site tag (gtag.js) - Google Analytics