默认
打赏 发表评论 20
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
一个基于MQTT通信协议的完整Android推送Demo [附件下载]
微信扫一扫关注!

前言


目前市场上存在多种免费的云推送服务,比如:个推、JPush等,但从技术上讲这毕竟是别人的东西,主要面向通用场景,特定场景下还是得自已来实现推送服务。

本文主要介绍的是基于MQTT实现一个简单的Android消息推送系统。更多推送技术资料请见:http://www.52im.net/forum.php?mod=collection&action=view&ctid=11

通信协议比较


按照惯例,总是在跟类似的通信协议对比一下,以下内容搜集自网络,仅供参考。

方案1:使用GCM服务(Google Cloud Messaging)

简介:Google推出的云消息服务,即第二代的C2DM。
优点:Google提供的服务、原生、简单,无需实现和部署服务端。
缺点:Android版本限制(必须大于2.2版本),该服务在国内不够稳定、需要用户绑定Google帐号,受限于Google。


方案2:使用XMPP协议(Openfire + Spark + Smack)

简介:基于XML协议的通讯协议,前身是Jabber,目前已由IETF国际标准化组织完成了标准化工作。
优点:协议成熟、强大、可扩展性强、目前主要应用于许多聊天系统中,且已有开源的Java版的开发实例androidpn。
缺点:协议较复杂、冗余(基于XML)、费流量、费电,部署硬件成本高。


方案3:使用MQTT协议(更多信息见:http://mqtt.org/

简介:轻量级的、基于代理的“发布/订阅”模式的消息传输协议。
优点:协议简洁、小巧、可扩展性强、省流量、省电,目前已经应用到企业领域(参考:mqtt.org/software),且已有C++版的服务端组件rsmb。
缺点:不够成熟、实现较复杂、服务端组件rsmb不开源,部署硬件成本较高。


方案4:使用HTTP轮循方式

简介:定时向HTTP服务端接口(Web Service API)获取最新消息。
优点:实现简单、可控性强,部署硬件成本低。
缺点:实时性差。


对各个方案的优缺点的研究和对比,推荐使用MQTT协议的方案进行实现,主要原因是:MQTT最快速,也最省流量(固定头长度仅为2字节),且极易扩展,适合二次开发。接下来,我们就来分析使用MQTT方案进行Android消息的原理和方法,并架设自己的推送服务。

(即时通讯网注:作为通信协议,实际上Google的Protobuf也是个非常不错的选择,请见强列建议将Protobuf作为你的即时通讯应用数据传输格式,更多通信协议的选择和对比文章请见:http://www.52im.net/forum.php?mod=collection&action=view&ctid=18

基于MQTT推送系统的技术原理


a.png

实际上,其他推送系统(包括GCM、XMPP方案)的原理都与此类似。

推送服务端准备


  • 下载&解压rsmb安装包(下载地址:请见文末附件
  • 进入对应的目录,比如32位的Linux系统则应该进入linux_ia32目录。
  • 编辑配置文件broker_1883.cfg。

broker_1883.cfg的配置如下:
port 1883  
max_inflight_messages 10  
max_queued_messages 1000  

运行./broker broker_1883.cfg,显示如下:
20120823 110454.039 CWNAN9999I Really Small Message Broker
20120823 110454.039 CWNAN9997I Licensed Materials - Property of IBM
20120823 110454.039 CWNAN9996I Copyright IBM Corp. 2007, 2010 All Rights Reserved
20120823 110454.039 CWNAN9995I US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
20120823 110454.039 CWNAN0049I Configuration file name is broker_1883.cfg
20120823 110454.040 CWNAN0053I Version 1.2.0, Aug 18 2010 17:03:35
20120823 110454.040 CWNAN0054I Features included: bridge
20120823 110454.040 CWNAN9993I Author: Ian Craggs ([url=mailto:icraggs@uk.ibm.com]icraggs@uk.ibm.com[/url])
20120823 110454.040 CWNAN0014I MQTT protocol starting, listening on port 1883
... ...

这样,推送服务的服务端就已经准备好了,监听1883端口。

推送客户端准备


  • 下载&解压AndroidPushNotificationsDemo项目(下载地址:请见文末附件
  • 将该项目导入Eclipse中(File -> Export -> Existing Projects into Workspace)
  • 修改PushService.java中的MQTT_HOST常量为推送服务端的IP地址。
  • 启动Android模拟器,并安装该项目。

注意:在新版本的Android SDK中可能会遇到以下错误:
.. ...
08-23 02:28:44.184: W/dalvikvm(282): VFY: unable to find class referenced in signature (Lcom/ibm/mqtt/MqttPersistence;)
08-23 02:28:44.194: I/dalvikvm(282): Failed resolving Lcom/tokudu/demo/PushService$MQTTConnection; interface 35 'Lcom/ibm/mqtt/MqttSimpleCallback;'
08-23 02:28:44.194: W/dalvikvm(282): Link of class 'Lcom/tokudu/demo/PushService$MQTTConnection;' failed
08-23 02:28:44.194: E/dalvikvm(282): Could not find class 'com.tokudu.demo.PushService$MQTTConnection', referenced from method com.tokudu.demo.PushService.connect
08-23 02:28:44.194: W/dalvikvm(282): VFY: unable to resolve new-instance 42 (Lcom/tokudu/demo/PushService$MQTTConnection;) in Lcom/tokudu/demo/PushService;
... ...
08-23 02:28:44.404: E/AndroidRuntime(282): java.lang.VerifyError: com.tokudu.demo.PushService
08-23 02:28:44.404: E/AndroidRuntime(282):     at com.tokudu.demo.PushActivity$1.onClick(PushActivity.java:32)
08-23 02:28:44.404: E/AndroidRuntime(282):     at android.view.View.performClick(View.java:2408)
08-23 02:28:44.404: E/AndroidRuntime(282):     at android.view.View$PerformClick.run(View.java:8816)
08-23 02:28:44.404: E/AndroidRuntime(282):     at android.os.Handler.handleCallback(Handler.java:587)
08-23 02:28:44.404: E/AndroidRuntime(282):     at android.os.Handler.dispatchMessage(Handler.java:92)
08-23 02:28:44.404: E/AndroidRuntime(282):     at android.os.Looper.loop(Looper.java:123)
08-23 02:28:44.404: E/AndroidRuntime(282):     at android.app.ActivityThread.main(ActivityThread.java:4627)
08-23 02:28:44.404: E/AndroidRuntime(282):     at java.lang.reflect.Method.invokeNative(Native Method)
08-23 02:28:44.404: E/AndroidRuntime(282):     at java.lang.reflect.Method.invoke(Method.java:521)
08-23 02:28:44.404: E/AndroidRuntime(282):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
08-23 02:28:44.404: E/AndroidRuntime(282):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
08-23 02:28:44.404: E/AndroidRuntime(282):     at dalvik.system.NativeStart.main(Native Method)
... ...

原因是发布的时候没有加入wmqtt.jar包,解决办法如下:

  • 在项目根目录下创建libs目录,并把wmqtt.jar包移入该目录。
  • 重新配置项目的Java Build Path(右键菜单中的Properties选项中)。
  • 重新打包发布即可。

运行效果如下:

b.png

点击“Start Push Service”按钮即可开启推送服务,这时我们可以看到rsmb的服务日志中打出以下提示:
20120823 113742.297 CWNAN0033I Connection attempt to listener 1883 received from client tokudu/9774d56d682e549c on address 192.168.28.39:3345

其中的“9774d56d682e549c”就是对应的客户端ID号。

发送服务准备


  • 下载&解压PHP版的发送服务端代码send_mqtt.zip(下载地址:请见文末附件
  • 修改etc/config.php中推送服务端的IP地址和端口号,即MQTT_SERVER_HOST和MQTT_SERVER_POST常量。
  • 打开对应的URL地址,就可以看到发送服务的界面,实际上就是向对应的推送客户端推送消息。

c.png

接着,我们在该界面中填入客户端ID(9774d56d682e549c)和推送消息(test)并点击“Send Push Message”按钮,服务端就可以向客户端推送消息了。我们看到,客户端上立马就可以收到刚刚推送的消息,如下图:

d.png

结语


当然,以上方案还存在许多的不足,比如,如果客户端没有保持连接,发送的消息就会被丢弃。不过,我们可以利用MQTT协议开发出更强大的服务端来替代rsmb,更可以加入队列、缓存等功能进行优化,有兴趣的朋友不妨试试。可参考开源项目Mosquitto(http://mosquitto.org/)。

源码下载


MQTT服务-rsmb_1.2.0(52im.net).zip (1.02 MB , 下载次数: 102 , 售价: 2 金币)

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:滴滴打车架构演变及应用实践(PPT讲稿) [附件下载]下一篇:轻量级即时通讯框架MobileIMSDK的iOS源码(开源版)[附件下载]

本帖已收录至以下技术专辑

推荐方案
评论 20
学习了!谢谢!
收藏了
收藏了 很需要这种资料。
签名: 啦啦啦啦啦啦
这个demo为什么点了start push service会闪退呢
引用:yy695575613 发表于 2018-04-16 15:09
这个demo为什么点了start push service会闪退呢

这个android demo比较老了,你可以把android下的logcat抓到日志贴出来看看是什么问题。估计你的手机是新版android
引用:JackJiang 发表于 2018-04-16 15:14
这个android demo比较老了,你可以把android下的logcat抓到日志贴出来看看是什么问题。估计你的手机是新 ...

04-16 03:26:29.623: E/AndroidRuntime(1190): FATAL EXCEPTION: main
04-16 03:26:29.623: E/AndroidRuntime(1190): Process: com.tokudu.demo, PID: 1190
04-16 03:26:29.623: E/AndroidRuntime(1190): java.lang.VerifyError: com/tokudu/demo/PushService
04-16 03:26:29.623: E/AndroidRuntime(1190):         at com.tokudu.demo.PushActivity$1.onClick(PushActivity.java:32)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at android.view.View.performClick(View.java:4438)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at android.view.View$PerformClick.run(View.java:18422)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at android.os.Handler.handleCallback(Handler.java:733)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at android.os.Handler.dispatchMessage(Handler.java:95)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at android.os.Looper.loop(Looper.java:136)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at android.app.ActivityThread.main(ActivityThread.java:5017)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at java.lang.reflect.Method.invokeNative(Native Method)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at java.lang.reflect.Method.invoke(Method.java:515)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
04-16 03:26:29.623: E/AndroidRuntime(1190):         at dalvik.system.NativeStart.main(Native Method)
引用:yy695575613 发表于 2018-04-16 16:45
04-16 03:26:29.623: E/AndroidRuntime(1190): FATAL EXCEPTION: main
04-16 03:26:29.623: E/AndroidRu ...

你百度一下“java.lang.VerifyError”
楼主,这个可以实现定时用PHP获取Oracle数据库数据,然后进行推送吗
引用:Singer 发表于 2018-04-18 08:03
楼主,这个可以实现定时用PHP获取Oracle数据库数据,然后进行推送吗

理论上可以,你试试看
引用:JackJiang 发表于 2018-04-18 09:24
理论上可以,你试试看

楼主,PHPService端文件需要放在哪个文件夹下
学习学习
学习一下
学习了
签名: 心情好
赞,简要的入门总结
签名: Linux Driver
很好的资源学习了
签名: 好好好
学习一下
签名: https://mustang2247.github.io/
很好的实践例子
签名: 春节快乐
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部