Android--消息推送機制

1.推送方式基礎知識:
當我們開發需要和服務器交互的應用程序時,基本上都需要獲取服務器端的數據,比如《地震應急通》就需要及時獲取服務器上最新的地震信息。要獲取服務器上不定時更新的信息一般來說有兩種方法,第一種是客戶端使用Pull(拉)的方式,隔一段時間就去服務器上獲取信息,看是否有更新的信息出現。第二種就是服務器使用Push(推送)的方式,當服務器端有新信息了,則把最新的信息Push到客戶端上。 
雖然Pull和Push兩種方式都能實現獲取服務器端更新信息的功能,但是明顯來說Push is better than pull。因爲Pull方式更費客戶端的網絡流量,更主要的是費電量。  
在開發Android和iPhone應用程序時,我們往往需要從服務器不定的向手機客戶端即時推送各種通知消息,iPhone上已經有了比較簡單的和完美的推送通知解決方案,我會在以後詳細介紹IPhone中的解決方案,可是Android平臺上實現起來卻相對比較麻煩,最近利用幾天的時間對Android的推送通知服務進行初步的研究。在Android手機平臺上,Google提供了C2DM(Cloudto Device Messaging)服務,起初我就是準備採用這個服務來實現自己手機上的推送功能。  
Android Cloud to Device Messaging (C2DM)是一個用來幫助開發者從服務器向Android應用程序發送數據的服務。該服務提供了一個簡單的、輕量級的機制,允許服務器可以通知移動應用程序直接與服務器進行通信,以便於從服務器獲取應用程序更新和用戶數據。C2DM服務負責處理諸如消息排隊等事務並向運行於目標設備上的應用程序分發這些消息。關於C2DM具體使用過程,我會以後的博文中再詳細介紹,這裏大家先了解下大致方案情況。
C2DM操作過程圖:

但是經過一番研究發現,這個服務存在很大的問題:
1)C2DM內置於Android的2.2系統上,無法兼容老的1.6到2.1系統;
2)C2DM需要依賴於Google官方提供的C2DM服務器,由於國內的網絡環境,這個服務經常不可用,如果想要很好的使用,我們的App Server必須也在國外,這個恐怕不是每個開發者都能夠實現的; 有了上述兩個使用上的制約,導致我最終放棄了這個方案,不過我想利用另外一篇文章來詳細的介紹C2DM的框架以及客戶端和App Server的相應設置方法,可以作爲學習與參考之用。即然C2DM無法滿足我們的要求,那麼我們就需要自己來實現Android手機客戶端與App Server之間的通信協議,保證在App Server想向指定的Android設備發送消息時,Android設備能夠及時的收到。
2. 幾種常見的解決方案
1)輪詢(Pull):應用程序應當階段性的與服務器進行連接並查詢是否有新的消息到達,你必須自己實現與服務器之間的通信,例如消息排隊等。而且你還要考慮輪詢的頻率,如果太慢可能導致某些消息的延遲,如果太快,則會大量消耗網絡帶寬和電池。
2)SMS(Push):在Android平臺上,你可以通過攔截SMS消息並且解析消息內容來了解服務器的意圖。這是一個不錯的想法,我就見過採用這個方案的應用程序。這個方案的好處是,可以實現完全的實時操作。但是問題是這個方案的成本相對比較高,你很難找到免費的短消息發送網關,關於這個方案的實現。
3)持久連接(Push):這個方案可以解決由輪詢帶來的性能問題,但是還是會消耗手機的電池。Apple的推送服務之所以工作的很好,是因爲每一臺手機僅僅保持一個與服務器之間的連接,事實上C2DM也是這麼工作的。不過這個方案也存在不足,就是我們很難在手機上實現一個可靠的服務。
Android操作系統允許在低內存情況下殺死系統服務,所以你的通知服務很可能被操作系統Kill掉了。前兩個方案存在明顯的不足,第三個方案也有不足,不過我們可以通過良好的設計來彌補,以便於讓該方案可以有效的工作。畢竟,我們要知道GMail,GTalk以及GoogleVoice都可以實現實時更新的。
3. MQTT協議實現Android推送
採用MQTT協議實現Android推送 MQTT是一個輕量級的消息發佈/訂閱協議,它是實現基於手機客戶端的消息推送服務器的理想解決方案。 wmqtt.jar 是IBM提供的MQTT協議的實現。我們可以從這裏下載該項目的實例代碼,並且可以找到一個採用PHP書寫的服務器端實現。
架構如下所示:

wmqtt.jar 是IBM提供的MQTT協議的實現。我們可以從如下站點下載它。你可以將該jar包加入你自己的Android應用程序中。
4.RSMB實現推送:
Really Small Message Broker (RSMB) ,他是一個簡單的MQTT代理,同樣由IBM提供。缺省打開1883端口,應用程序當中,它負責接收來自服務器的消息並將其轉發給指定的移動設備。
SAM是一個針對MQTT寫的PHP庫。我們可以從這個下載它.
send_mqtt.php是一個通過POST接收消息並且通過SAM將消息發送給RSMB的PHP腳本。
Really Small Message Broker (RSMB) ,他是一個簡單的MQTT代理,同樣由IBM提供。缺省打開1883端口,應用程序當中,它負責接收來自服務器的消息並將其轉發給指定的移動設備。
5. XMPP協議實現Android推送
這是我在項目中採用的方案。事實上Google官方的C2DM服務器底層也是採用XMPP協議進行的封裝。 XMPP(可擴展通訊和表示協議)是基於可擴展標記語言(XML)的協議,它用於即時消息(IM)以及在線探測。這個協議可能最終允許因特網用戶向因特網上的其他任何人發送即時消息。關於XMPP協議我在上篇博文中已經介紹,大家可以參考:http://www.cnblogs.com/hanyonglu/archive/2012/03/04/2378956.html
androidpn是一個基於XMPP協議的java開源Android push notification實現,我會在以後的博文中詳細介紹androidpn。它包含了完整的客戶端和服務器端。經過源代碼研究我發現,該服務器端基本是在另外一個開源工程openfire基礎上修改實現的,不過比較鬱悶的是androidpn的文檔是由韓語寫的,所以整個研究過程基本都是讀源碼。
實現意圖如下圖所示:

androidpn 客戶端需要用到一個基於java的開源XMPP協議包asmack,這個包同樣也是基於openfire下的另外一個開源項目smack,不過我們不需要自己編譯,可以直接把androidpn客戶端裏面的asmack.jar拿來使用。客戶端利用asmack中提供的XMPPConnection類與服務器建立持久連接,並通過該連接進行用戶註冊和登錄認證,同樣也是通過這條連接,接收服務器發送的通知。
androidpn服務器端也是java語言實現的,基於openfire開源工程,不過它的Web部分採用的是spring框架,這一點與 openfire是不同的。Androidpn服務器包含兩個部分,一個是偵聽在5222端口上的XMPP服務,負責與客戶端的 XMPPConnection類進行通信,作用是用戶註冊和身份認證,併發送推送通知消息。另外一部分是Web服務器,採用一個輕量級的HTTP服務器,負責接收用戶的Web請求。服務器架構如下:

最上層包含四個組成部分,分別是SessionManager,Auth Manager,PresenceManager以及Notification Manager。SessionManager負責管理客戶端與服務器之間的會話,Auth Manager負責客戶端用戶認證管理,Presence Manager負責管理客戶端用戶的登錄狀態,NotificationManager負責實現服務器向客戶端推送消息功能。
這個解決方案的最大優勢就是簡單,我們不需要象C2DM那樣依賴操作系統版本,也不會擔心某一天Google服務器不可用。利用XMPP協議我們還可以進一步的對協議進行擴展,實現更爲完善的功能。採用這個方案,我們目前只能發送文字消息,不過對於推送來說一般足夠了,因爲我們不能指望通過推送得到所有的數據,一般情況下,利用推送只是告訴手機端服務器發生了某些改變,當客戶端收到通知以後,應該主動到服務器獲取最新的數據,這樣纔是推送服務的完整實現。

發佈了13 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章