一、推送方式簡介:
當前隨着移動互聯網的不斷加速,消息推送的功能越來越普遍,不僅僅是應用在郵件推送上了,更多的體現在手機的APP上。當我們開發需要和服務器交互的應用程序時,基本上都需要獲取服務器端的數據,比如《地震應急通》就需要及時獲取服務器上最新的地震信息。
1、概念:
所謂的消息推送就是從服務器端向移動終端發送連接,傳輸一定的信息。比如一些新聞客戶端,每隔一段時間收到一條或者多條通知,這就是從服務器端傳來的推送消息;還比如常用的一些IM軟件如微信、GTalk等,都具有服務器推送功能。
推送技術通過自動傳送信息給用戶,來減少用於網絡上搜索的時間。它根據用戶的興趣來搜索、過濾信息,並將其定期推給用戶,幫助用戶高效率地發掘有價值的信息。
2、要獲取服務器上不定時更新的信息,一般來說有兩種方法:
第一種是客戶端使用Pull(拉)的方式,就是隔一段時間就去服務器上獲取一下信息,看是否有更新的信息出現。
第二種就是 服務器使用Push(推送)的方式,當服務器端有新信息了,則把最新的信息Push到客戶端上。這樣,客戶端就能自動的接收到消息。
雖然Pull和Push兩種方式都能實現獲取服務器端更新信息的功能,但是明顯來說Push方式比Pull方式更優越。因為Pull方式更費客戶端的網絡流量,更主要的是費電量,還需要我們的程序不停地去監測服務端的變化。
二、常見消息推送方案的原理:
1、輪詢(Pull)方式:
客戶端定時向服務器發送詢問消息,一旦服務器有變化則立即同步消息。應用程序應當階段性的與服務器進行連接並查詢是否有新的消息到達,你必須自己實現與服務器之間的通信,例如消息排隊等。而且你還要考慮輪詢的頻率,如果太慢可能導致某些消息的延遲,如果太快,則會大量消耗網絡帶寬和電池。
2、SMS(Push)方式:
通過攔截SMS消息並且解析消息內容來了解服務器的命令。這個方案的好處是,可以實現完全的實時操作;但是問題是這個方案的成本相對比較高,且依賴於運營商。
3、持久連接(Push)方式:
客戶端和服務器之間建立長久連接,這樣就可以實現消息的及時行和實時性。
這個方案可以解決由輪詢帶來的性能問題,但是還是會消耗手機的電池。我們需要開一個服務來保持和服務器端的持久連接(蘋果就和谷歌的C2DM是這種機制)。但是對於Android系統,當系統可用資源較低,系統會強制關閉我們的服務或者是應用,這種情況下連接會強制中斷。(Apple的推送服務之所以工作的很好,是因為每一台手機僅僅保持一個與服務器之間的連接,事實上C2DM也是這么工作的。即所有的推送服務都是經由一個代理服務器完成的,這種情況下只需要和一台服務器保持持久連接即可。C2DM=Cloud to Device Messaging)。
相比之下第三種還是最可行的。為軟件編寫系統服務或開機啟動功能;或者如果系統資源較低,服務被關閉后可以在onDestroy ()方法里面再重啟該服務,進而實現持久連接的方式。
三、消息推送解決方案概述
1、C2DM雲端推送方案
在Android手機平台上,Google提供了C2DM(Cloudto Device Messaging)服務。Android Cloud to Device Messaging (C2DM)是一個用來幫助開發者從服務器向Android應用程序發送數據的服務。該服務提供了一個簡單的、輕量級的機制,允許服務器可以通知移動應用程序直接與服務器進行通信,以便於從服務器獲取應用程序更新和用戶數據。C2DM服務負責處理諸如消息排隊等事務並向運行於目標設備上的應用程序分發這些消息。
C2DM操作過程示例圖:
這個服務存在很大的問題:
1)C2DM內置於Android的2.2系統上,無法兼容老的1.6到2.1系統。
2)C2DM需要依賴於Google官方提供的C2DM服務器,由於國內的網絡環境,這個服務經常不可用,如果想要很好的使用,我們的App Server必須也在國外,這個恐怕不是每個開發者都能夠實現的。
3) 不像在iPhone中,他們把硬件系統集成在一塊了。所以對於我們開發者來說,如果要在我們的應用程序中使用C2DM的推送功能,因為對於不同的這種硬件廠商平台,比如摩托羅拉、華為、中興做一個手機,他們可能會把Google的這種服務去掉,尤其像在國內就很多這種,把Google這種原生的服務去掉。買了一些像什么山寨機或者是華為這種國產機,可能Google的服務就沒有了。而像在國外出的那些可能會內置。
即然C2DM無法滿足我們的要求,那么我們就需要自己來實現Android手機客戶端與App Server之間的通信協議,保證在App Server想向指定的Android設備發送消息時,Android設備能夠及時的收到。
2、MQTT協議實現Android推送
采用MQTT協議實現Android推送功能也是一種解決方案。MQTT是一個輕量級的消息發布/訂閱協議,它是實現基於手機客戶端的消息推送服務器的理想解決方案。
wmqtt.jar 是IBM提供的MQTT協議的實現。我們可以從如下站點下載(http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg24006006)它。可以將該jar包加入自己的Android應用程序中。可以從這里(https://github.com/tokudu/AndroidPushNotificationsDemo)下載該項目的實例代碼,並且可以找到一個采用PHP書寫的服務器端實現(https://github.com/tokudu/PhpMQTTClient)。
架構如下圖所示:
3、RSMB實現推送功能
Really Small Message Broker (RSMB) ,是一個簡單的MQTT代理,同樣由IBM提供,其查看地址是:http://www.alphaworks.ibm.com/tech/rsmb。缺省打開1883端口,應用程序當中,它負責接收來自服務器的消息並將其轉發給指定的移動設備。SAM是一個針對MQTT寫的PHP庫。我們可以從這個http://pecl.php.net/package/sam/download/0.2.0地址下載它。send_mqtt.php是一個通過POST接收消息並且通過SAM將消息發送給RSMB的PHP腳本。
4、XMPP協議實現Android推送
1)XMPP:
XMPP全稱Extensible Messaging and Presence Protocol,前身是Jabber項目,是一種以XML為基礎的開放式即時通訊協議。XMPP因為被Google Talk和網易泡泡應用而被廣大網民所接觸。XMPP的關鍵特色是,分散式的即時通訊系統,以及使用XML串流。XMPP目前被IETF國際標准組織完成了標准化工作。
2)Android push notification(androidpn)
AndroidPN 是一個基於XMPP協議的java開源實現,它包含了完整的客戶端和服務器端。該服務器端基本是在另外一個開源工程openfire基礎上修改實現的。
androidpn實現意圖如下圖所示:
androidpn客戶端需要用到一個基於java的開源XMPP協議包asmack,這個包同樣也是基於openfire下的另外一個開源項目smack,不過我們不需要自己編譯,可以直接把androidpn客戶端里面的asmack.jar拿來使用。客戶端利用asmack中提供的XMPPConnection類與服務器建立持久連接,並通過該連接進行用戶注冊和登錄認證,同樣也是通過這條連接,接收服務器發送的通知。
3)androidpn服務器端:
androidpn服務器端也是java語言實現的,基於openfire開源工程,不過它的Web部分采用的是spring框架,這一點與openfire是不同的。Androidpn服務器包含兩個部分,一個是偵聽在5222端口上的XMPP服務,負責與客戶端的XMPPConnection類進行通信,作用是用戶注冊和身份認證,並發送推送通知消息。另外一部分是Web服務器,采用一個輕量級的HTTP服務器,負責接收用戶的Web請求。服務器的這兩方式,意義非凡:當相應的TCP端口被防火牆封閉,可以使用輪詢的方式進行訪問,因此又有助於通過防火牆。
服務器架構如下:
最上層包含四個組成部分,分別是SessionManager,Auth Manager,PresenceManager以及Notification Manager。SessionManager負責管理客戶端與服務器之間的會話,Auth Manager負責客戶端用戶認證管理,Presence Manager負責管理客戶端用戶的登錄狀態,NotificationManager負責實現服務器向客戶端推送消息功能。
這個解決方案的最大優勢就是簡單,我們不需要象C2DM那樣依賴操作系統版本,也不會擔心某一天Google服務器不可用。利用XMPP協議我們還可以進一步的對協議進行擴展,實現更為完善的功能。采用這個方案,我們目前只能發送文字消息,不過對於推送來說一般足夠了,因為我們不能指望通過推送得到所有的數據,一般情況下,利用推送只是告訴手機端服務器發生了某些改變,當客戶端收到通知以后,應該主動到服務器獲取最新的數據,這樣才是推送服務的完整實現。 XMPP協議書相對來說還是比較簡單的,值得我們進一步研究。
4)androidpn不足:
androidpn是一個基於XMPP協議的java開源Android push notification實現。它包含了完整的客戶端和服務器端。但也存在一些不足之處:
①、比如時間過長時,就再也收不到推送的信息了。
②、性能上也不夠穩定。
③、如果將消息從服務器上推送出去,就不再管理了,不管消息是否成功到達客戶端手機上。
如果我們要使用androidpn,則還需要做大量的工作,需要理解XMPP協議、理解Androidpn的實現機制,需要調試內部存在的BUG。
5、使用第三方平台
目前國內、國外有一些推送平台可供使用,但是涉及到收費問題、保密問題、服務質量問題、擴展問題等等,又不得不是我們望而卻步。
6、自己搭建一個推送平台。
這不是一件輕松的工作,當然可以根據各自的需要采取合適的方案。
========================================================================================================================
四、Android Push Notification實現信息推送使用
AndroidPn項目就是使用XMPP協議實現信息推送的一個開源項目。在這里介紹其使用過程。
1、Apndroid Push Notification的特點:
1)快速集成:提供一種比C2DM更加快捷的使用方式,避免各種限制.
2)無需架設服務器:通過使用"雲服務",減少額外服務器負擔.
3)可以同時推送消息到網站頁面,android 手機
4)耗電少,占用流量少.
2、具體配置過程:
1)下載並解壓androidpn的壓縮包
①、首先, 我們需要下載androidpn-client-0.5.0.zip和androidpn-server-0.5.0-bin.zip。
下載地址:http://sourceforge.net/projects/androidpn/
②、解壓兩個包,Eclipse導入client,配置好目標平台,打開raw/androidpn.properties文件,配置客戶端程序。
2)配置:
A、如果是模擬器來運行客戶端程序,把xmppHost配置成10.0.2.2[模擬器把10.0.2.2認為是所在主機的地址,127.0.0.1是模擬器本身的回環地址,10.0.2.1表示網關地址,10.0.2.3表示DNS地址,10.0.2.15表示目標設備的網絡地址],關於模擬器的詳細信息,大家可參閱相關資料。
xmppPort=5222 是服務器的xmpp服務監聽端口
運行androidpn-server-0.5.0\bin\run.bat啟動服務器,從瀏覽器訪問http://127.0.0.1:7070/index.do (androidPN Server有個輕量級的web服務器,在7070端口監聽請求,接受用戶輸入的文本消息)
運行客戶端,客戶端會向服務器發起連接請求,注冊成功后,服務器能識別客戶端,並維護和客戶端的IP長連接。
B、如果是在同一個局域網內的其他機器的模擬器測試(或者使用同一無線路由器wifi上網的真機) ,則需要把這個值設置為服務器機器的局域網ip
例如:你的電腦和android手機都通過同一個無線路由器wifi上網,電腦的ip地址為 192.168.1.2 而手機的ip地址為192.168.1.3,這個時候需要把這個值修改為xmppHost=192.168.1.1 或是電腦的IP地址,就可以在手機上使用了.
C、如果是不在同一個局域網的真機測試,我們需要將這個值設置為服務器的IP地址。