方案1、使用gcm服務(google cloud messaging)
簡介:google推出的雲消息服務,即第二代的c2dm。
優點:google提供的服務、原生、簡單,無需實作和部署服務端。
缺點:android版本限制(必須大于2.2版本),該服務在國内不夠穩定、需要使用者綁定google帳号,受限于google。
方案2、使用xmpp協定(openfire + spark + smack)
簡介:基于xml協定的通訊協定,前身是jabber,目前已由ietf國際标準化組織完成了标準化工作。
優點:協定成熟、強大、可擴充性強、目前主要應用于許多聊天系統中,且已有開源的java版的開發執行個體androidpn。
缺點:協定較複雜、備援(基于xml)、費流量、費電,部署硬體成本高。
簡介:輕量級的、基于代理的“釋出/訂閱”模式的消息傳輸協定。
缺點:不夠成熟、實作較複雜、服務端元件rsmb不開源,部署硬體成本較高。
方案4、使用http輪循方式
簡介:定時向http服務端接口(web service api)擷取最新消息。
優點:實作簡單、可控性強,部署硬體成本低。
缺點:實時性差。
對各個方案的優缺點的研究和對比,推薦使用mqtt協定的方案進行實作,主要原因是:mqtt最快速,也最省流量(固定頭長度僅為2位元組),且極易擴充,适合二次開發。接下來,我們就來分析使用mqtt方案進行android消息的原理和方法,并架設自己的推送服務。
1、推送原理分析

實際上,其他推送系統(包括gcm、xmpp方案)的原理都與此類似。
2、推送服務端準備
b> 進入對應的目錄,比如32位的linux系統則應該進入linux_ia32目錄。
c> 編輯配置檔案broker_1883.cfg,配置如下:
port 1883
max_inflight_messages 10
max_queued_messages 1000
d> 運作./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 ([email protected])
20120823 110454.040 cwnan0014i mqtt protocol starting, listening on port 1883
... ...
這樣,推送服務的服務端就已經準備好了,監聽1883端口。
3、推送用戶端準備
b> 将該項目導入eclipse中(file -> export -> existing projects into workspace)
c> 修改pushservice.java中的mqtt_host常量為推送服務端的ip位址。
d> 啟動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包,解決辦法如下:
1> 在項目根目錄下建立libs目錄,并把wmqtt.jar包移入該目錄。
2> 重新配置項目的java build path(右鍵菜單中的properties選項中)。
3> 重新打包釋出即可。
運作效果如下:
點選“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号。
4、發送服務準備
b> 修改etc/config.php中推送服務端的ip位址和端口号,即mqtt_server_host和mqtt_server_post常量。
c> 打開對應的url位址,就可以看到發送服務的界面,實際上就是向對應的推送用戶端推送消息。
接着,我們在該界面中填入用戶端id(9774d56d682e549c)和推送消息(test)并點選“send push message”按鈕,服務端就可以向用戶端推送消息了。我們看到,用戶端上立馬就可以收到剛剛推送的消息,如下圖。