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

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

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

Java代码  
  1. if(!mXmppManager.isConnected()) {
  2. ConnectionConfiguration config = new ConnectionConfiguration(mHost, mPort);
  3. config.setSecurityMode(SecurityMode.required);
  4. config.setSASLAuthenticationEnabled(false);
  5. config.setCompressionEnabled(false);
  6. XMPPConnection connection = new XMPPConnection(config);
  7. mXmppManager.setConnection(connection);
  8. try {
  9. connection.connect();
  10. Log.i(LOGTAG, "XMPP connected successfully");
  11. /**
  12. * 这个就是对于通信的xml文本进行解析的解析器,再把信息转换成IQ,这个相当于QQ的聊天信息
  13. * 如果要用这个协议,其IQ的子类和IQProvider要进行重写
  14. */
  15. ProviderManager.getInstance().addIQProvider("notification",
  16. "androidpn:iq:notification",
  17. new NotificationIQProvider());
  18. } catch (XMPPException e) {
  19. Log.d(LOGTAG, "the connection is error ... ");
  20. }
  21. mXmppManager.runTask();
  22. } else {
  23. Log.i(LOGTAG, "XMPP connected already");
  24. mXmppManager.runTask();
  25. }

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

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

Java代码  
  1. if(!mXmppManager.isRegistered()){
  2. final String newUsername = newRandomUUID();
  3. final String newPassword = newRandomUUID();
  4. Registration registration = new Registration();
  5. PacketFilter packetFilter = new AndFilter(new PacketIDFilter(
  6. registration.getPacketID()), new PacketTypeFilter(
  7. IQ.class));
  8. PacketListener packetListener = new PacketListener() {
  9. @Override
  10. public void processPacket(Packet packet) {
  11. // 服务器回复客户端
  12. if(packet instanceof IQ) {
  13. IQ response = (IQ) packet;
  14. if(response.getType() == IQ.Type.ERROR) { // 注册失败
  15. if (!response.getError().toString().contains(
  16. "409")) {
  17. Log.e(LOGTAG,"Unknown error while registering XMPP account! " + response.getError().getCondition());
  18. }
  19. } else if(response.getType() == IQ.Type.RESULT) { // 注册成功
  20. mXmppManager.setUsername(newUsername);
  21. mXmppManager.setPassword(newPassword);
  22. // 把用户名和密码都保存到磁盘
  23. Editor editor = mSharedPrefs.edit();
  24. editor.putString(Contants.XMPP_USERNAME, newUsername);
  25. editor.putString(Contants.XMPP_PASSWORD, newPassword);
  26. editor.commit();
  27. mXmppManager.runTask();
  28. }
  29. }
  30. }
  31. };
  32. // 给注册的Packet设置Listener,因为只有等到正真注册成功后,我们才可以交流
  33. mConnection.addPacketListener(packetListener, packetFilter);
  34. registration.setType(IQ.Type.SET);
  35. registration.addAttribute("username", newUsername);
  36. registration.addAttribute("password", newPassword);
  37. // 向服务器端,发送注册Packet包,注意其中Registration是Packet的子类
  38. mConnection.sendPacket(registration);
  39. } else { // 已经注册过了
  40. mXmppManager.runTask();
  41. }

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

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

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

Java代码  
  1. // 判断是否已经登陆过了,是否是在登陆状态
  2. if(!mXmppManager.isAuthenticated()) {
  3. try {
  4. mConnection.login(mUsername, mPassword, "AndroidpnClient");
  5. // 设置XmppConnection的监听器
  6. if(mXmppManager.getConnectionListener() != null) {
  7. mConnection.addConnectionListener(mXmppManager.getConnectionListener());
  8. }
  9. // 设置服务器端推送的监听器
  10. PacketFilter packetFilter = new PacketTypeFilter(NotificationIQ.class);
  11. PacketListener packetListener = mXmppManager.getNotificationPacketListener();
  12. mConnection.addPacketListener(packetListener, packetFilter);
  13. mXmppManager.runTask();
  14. } catch (XMPPException e) {
  15. // 登陆失败,应该重试
  16. String INVALID_CREDENTIALS_ERROR_CODE = "401";
  17. String errorMessage = e.getMessage();
  18. // 如果只是因为没有注册,则进行重新注册
  19. if (errorMessage != null && errorMessage.contains(INVALID_CREDENTIALS_ERROR_CODE)) {
  20. mXmppManager.reregisterAccount();
  21. return;
  22. }
  23. mXmppManager.startReconnectionThread();
  24. } catch (Exception e) { // 有可能mConnection都为空
  25. Log.e(LOGTAG, "LoginTask.run()... other error");
  26. Log.e(LOGTAG, "Failed to login to xmpp server. Caused by: " + e.getMessage());
  27. mXmppManager.startReconnectionThread(); // 启动重连线程
  28. }
  29. } else {
  30. mXmppManager.runTask();
  31. }

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

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

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

Java代码  
  1. public void processPacket(Packet packet) {
  2. if(packet instanceof NotificationIQ) {
  3. NotificationIQ notification = (NotificationIQ) packet;
  4. if(notification.getChildElementXML().contains("androidpn:iq:notification")) {
  5. String notificationId = notification.getId();
  6. String notificationApiKey = notification.getApiKey();
  7. String notificationTitle = notification.getTitle();
  8. String notificationMessage = notification.getMessage();
  9. String notificationUri = notification.getUri();
  10. Intent intent = new Intent(Contants.ACTION_SHOW_NOTIFICATION);
  11. intent.putExtra(Contants.NOTIFICATION_ID, notificationId);
  12. intent.putExtra(Contants.NOTIFICATION_API_KEY,notificationApiKey);
  13. intent.putExtra(Contants.NOTIFICATION_TITLE,notificationTitle);
  14. intent.putExtra(Contants.NOTIFICATION_MESSAGE, notificationMessage);
  15. intent.putExtra(Contants.NOTIFICATION_URI, notificationUri);
  16. mXmppManager.getContext().sendBroadcast(intent);
  17. }
  18. }
  19. }

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

转载于:https://www.cnblogs.com/zmissm/archive/2013/05/11/3072441.html

Androidpn里的XmppManager的理解相关推荐

  1. 转 Androidpn里的Xmpp的理解(消息推送)

    Androidpn里的Xmpp的理解(消息推送) XMPP(可扩展通讯和表示协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线探测.这个协议可能最终允许因特网用户向因特网上的其 ...

  2. python如何得出数组里最大_如何理解Python里的字典dict?

    字典dict由键值key-value构成,具有较强的查询检索能力. 基本格式为: dict={key1:value1,key2:value2,......,keyn,valuen } 1.key由数字 ...

  3. linux里netstat与ps,理解proc目录与linux进程、ps命令、netstat命令的关系

    零.proc目录简介 proc目录是虚拟文件系统(VFS)的一种实现,保存了进程信息(pid目录)和一些系统信息. 一.系统的信息 1.cpuinfo和meminfo两个文件 查看CPU和内存相关信息 ...

  4. 【react】---函数化编程的理解,柯里化函数及返柯里化函数的理解...

    虚拟DOM  与 js概念的理解 01.纯函数的理解: 02.柯里化函数 编写一个函数add(3)(4)(5)  得出结果  12    //通过柯里化  函数就可以实现 一个函数内,执行过程中,返回 ...

  5. 关于欧几里得定理和拓展欧几里得定理的理解 续

    前言 在我大一刚开始ACM的时候,写过一篇关于欧几里得定理理解的博客,这几天因为再次用到欧几里得定理,所以又转回去看了看,感觉自己以前写的不是很清楚,所以决定再写一篇关于欧几里得定理以及拓展欧几里得定 ...

  6. Linux里的21的理解

    转载自:https://blog.csdn.net/ggxiaobai/article/details/53507530 我们在Linux下经常会碰到nohup command>/dev/nul ...

  7. 机器学习和统计里面的auc怎么理解?

    转自: https://www.zhihu.com/question/39840928 作者:小小丘 (该作者对 auc的意义 讲得非常棒, 感谢付出) 链接:https://www.zhihu.co ...

  8. Matlab---傅里叶变换---通俗理解(一)

    一.概念 傅立叶变换是一种分析信号的方法,它可分析信号的成分,也可用这些成分合成信号.许多波形可作为信号的成分,比如正弦波.方波.锯齿波等,傅立叶变换用正弦波作为信号的成分.傅立叶变换,表示能将满足一 ...

  9. Matlab---傅里叶变换---通俗理解(二)

    1.用Matlab进行傅立叶变换 FFT是离散傅里叶变换的快速算法,可以将一个信号变换到频域.有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了.这就是很多信号分析采用F ...

  10. 打造属于自己的underscore系列(五)- 偏函数和函数柯里化

    这一节的内容,主要针对javascript函数式编程的两个重要概念,偏函数(partial application) 和函数柯里化(curry)进行介绍.着重讲解underscore中对于偏函数应用的 ...

最新文章

  1. linux中一些简便的命令之wc
  2. .NET Core开发实战(第22课:异常处理中间件:区分真异常与逻辑异常)--学习笔记(下)...
  3. 微软宣布新命令行工具 Windows Terminal 和 WSL2
  4. BZOJ1433 ZJOI2009 假期的宿舍 二分图匹配
  5. Linux实验二报告
  6. java jdom进行xml的增删改差_java使用DOM对XML文档进行增删改查操作实例代码
  7. 【英语学习】【WOTD】hoodwink 释义/词源/示例
  8. 数据结构—队列、循环队列、双端队列
  9. c4d阿诺德渲染器支持a卡吗_C4D常用的4大主流渲染器如何选择与比较 (OC/RS/VR/阿诺德)?...
  10. UVM:factory 机制
  11. Linux系统GPU压力测试
  12. android killer 反编译工具,安卓反编译工具-Android Killer下载1.3.0.0 正式版-腾牛下载...
  13. macbook usb口突然不能用 解决方法
  14. Apple LZF算法解析
  15. 【python爬虫专项(19)】blibli弹幕数据爬取(以全站搜索蔡徐坤的视频为例)
  16. Robust Pose Estimation in Crowded Scenes with Direct Pose-Level Inference 阅读笔记
  17. 内存取证工具——volatility 常用命令
  18. git rebase解决冲突
  19. SATA耦合电容浅析
  20. 搭建站群应该如何选择站群服务器空间

热门文章

  1. linux下安装php扩展curl
  2. anywhere随启随用的静态文件服务器
  3. 设计模式——状态模式
  4. 3ds max学习笔记(二)--查看视点
  5. credential for git
  6. Drcom账户管理Server端解说
  7. 开源项目使用问题集锦
  8. Win7 局域网内简单共享的设置
  9. 在Linux Redhat 9.0使用YUM
  10. java day09【继承、super、this、抽象类】