1.訊息推送基礎
訊息推送,就是在互連網上通過定期傳送使用者需要的資訊來減少資訊過載的一項新技術。推送技術通過自動傳送資訊給使用者,來減少用於網路上搜尋的時間。它根據使用者的興趣來搜尋、過濾資訊,並將其定期推給使用者,協助使用者高效率地發掘有價值的資訊
當我們開發需要和伺服器互動的行動裝置 App時,基本上都需要和伺服器進行互動,包括上傳資料到伺服器,同時從伺服器上擷取資料。
一般情況下,用戶端與伺服器之間通訊用戶端是主動的,但這就存在一個問題就是一旦伺服器資料有更新或者伺服器要下發通知給用戶端只能等用戶端串連的時候才能實現。這種方式使訊息失去了即時性。
如何使用戶端能夠即時的收到伺服器的訊息和通知,總體來說有兩種方式,第一種是用戶端使用Pull(拉)的方式,就是隔一段時間就去伺服器上擷取一下資訊,看是否有更新的資訊出現。第二種就是 伺服器使用Push(推送)的方式,當伺服器端有新資訊了,則把最新的資訊Push到用戶端上。這樣,用戶端就能自動的接收到訊息。
雖然Pull和Push兩種方式都能實現擷取伺服器端更新資訊的功能,但是明顯來說Push方式比Pull方式更優越。因為Pull方式更費用戶端的網路流量,更主要的是費電量,還需要我們的程式不停地去監測服務端的變化。
2. 幾種常見的解決方案實現原理
1)輪詢(Pull)方式:用戶端定時向伺服器發送詢問訊息,一旦伺服器有變化則立即同步訊息。
2)SMS(Push)方式:通過攔截SMS訊息並且解析訊息內容來瞭解伺服器的命令,但這種方式一般使用者在經濟上很難承受。
3)持久串連(Push)方式:用戶端和伺服器之間建立長久串連,這樣就可以實現訊息的及時行和即時性。
3、訊息推送解決方案概述
A、C2DM雲端推送方案
在Android手機平台上,Google提供了C2DM(Cloudto Device Messaging)服務。Android Cloud to Device Messaging (C2DM)是一個用來協助開發人員從伺服器向Android應用程式發送資料的服務。該服務提供了一個簡單的、輕量級的機制,允許伺服器可以通知行動裝置 App程式直接與伺服器進行通訊,以便於從伺服器擷取應用程式更新和使用者資料。
該方案存在的主要問題是C2DM需要依賴於Google官方提供的C2DM伺服器,由於國內的網路環境,這個服務經常不可用。
B、MQTT協議實現Android推送
採用MQTT協議實現Android推送功能也是一種解決方案。MQTT是一個輕量級的訊息發布/訂閱協議,它是實現基於手機用戶端的訊息推送伺服器的理想解決方案。
wmqtt.jar 是IBM提供的MQTT協議的實現。我們可以從這裡(https://github.com/tokudu/AndroidPushNotificationsDemo)下載該項目的執行個體代碼,並且可以找到一個採用PHP書寫的伺服器端實現(https://github.com/tokudu/PhpMQTTClient)。
C、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地址下載它.
D、XMPP協議實現Android推送
Google官方的C2DM伺服器底層也是採用XMPP協議進行的封裝。XMPP(可擴充通訊和表示協議)是基於可延伸標記語言 (XML)(XML)的協議,它用於立即訊息(IM)以及線上探測。這個協議可能最終允許網際網路使用者向網際網路上的其他任何人傳送立即訊息。
androidpn是一個基於XMPP協議的java開源Android push notification實現。它包含了完整的用戶端和伺服器端。但也存在一些不足之處:
1) 比如時間過長時,就再也收不到推送的資訊了。
2)效能上也不夠穩定。
3)如果將訊息從伺服器上推送出去,就不再管理了,不管訊息是否成功到達用戶端手機上。
如果我們要使用androidpn,則還需要做大量的工作,需要理解XMPP協議、理解Androidpn的實現機制,需要調試內部存在的BUG。
E、使用第三方平台
目前國內、國外有一些推送平台可供使用,但是涉及到收費問題、保密問題、服務品質問題、擴充問題等等,又不得不是我們望而卻步。
4、訊息推送完美方案
綜合以上論述,在建立Android訊息推送方面可謂方案多多,但每一款方案都有其優缺點。但無論如何,還是自己搭建一個推送平台是上策。因為你有、他有不如自己有。
在搭建自有推送平台上建議使用《九日升Android訊息推送組件》(http://www.bjjrs.net/product/13629681868537.html)。該組不僅可以拿來即用,並且還可以提供源碼以便擴充,實現自己的特殊需求。
A、推送原理
九日升Android訊息推送組件基於XMPP協議實現Android推送。XMPP(可擴充通訊和表示協議)是基於可延伸標記語言 (XML)(XML)的協議,它用於立即訊息(IM)以及線上探測。這個協議可能最終允許網際網路使用者向網際網路上的其他任何人傳送立即訊息。
九日升Android訊息推送組件實現原理見下圖:
圖1-訊息推送原理圖
九日升Android訊息推送組件由伺服器部分和用戶端部分組成。每一部分都由XMPP協議組件和外部介面組件構成。XMPP協議組件負責伺服器和Android用戶端間的串連管理、訊息通訊,外部介面組件負責接收應用系統、用戶端應用的命令,嚮應用系統發送接收到的通知訊息。
九日升Android訊息組件提供基於Tomcat的伺服器應用和Android開發jar包。其中基於Tomcat的伺服器應用直接在Tomcat上部署即可,Android開發jar包引入Android項目即可。
B 整合方式
1)、伺服器部署
九日升Android訊息組件Tomcat的伺服器應用直接部署在Tomcat中,連接埠號碼任意設定。
2)、用戶端jar包引用
在Android項目中建立libs目錄,然後將提供的Android開發jar包複製到該目錄即可。見下圖:
圖2-jar包引入圖
3)、Android項目AndroidManifest.xml檔案修改
在該檔案中增加以下許可權:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
在該檔案中註冊服務:
<service android:enabled="true"
android:name="com.bjjrs.server.NotificationService"
android:label="NotificationService">
<intent-filter>
<action android:name="com.bjjrs.server.NotificationService" />
</intent-filter>
</service>
至此,九日升Android訊息組件整合工作完成。
C、介面方式
1)、伺服器端介面採用基於http協議的訪問方式,採用http協議從伺服器中擷取各種資訊,實現通知訊息的推送。
如使用以下方式和參數就可以實現各種使用者訊息的查詢:
http://localhost:8080/user.do?action=getAllUser&isOnline=&userID=&userType=&deptID=&deptName=&realName=
使用如下方式就可以實現各種訊息的推送:
http://localhost:8080/notification.do?action=pushNoti&userNames=&title=&content=
2)、Android用戶端介面採用廣播機制。
訊息接收:當XMPP協議組件接收到推送訊息時,將按照一定格式廣播該訊息,通知用戶端其他應用接收並處理該訊息。
訊息發送:用戶端應用需要向伺服器或者其他用戶端傳送立即訊息時,只需按一定格式廣播該訊息,XMPP組件就會自動接收該訊息並發送到指定的其他用戶端。
D、優勢特點
1)、系統整合簡單,無需複雜的設定。
2)、Android用戶端應用和九日升Android訊息推送組件完全分離,通過介面相互調用,實現模組應用最佳化。
3)、用戶端通訊機制採用廣播方式,給用戶端應用帶來極大的靈活性和可擴充性,可以自由處理接收到的推送訊息。
4)、九日升Android訊息推送組件在伺服器端具備訊息儲存、訊息重發、訊息路由等功能,在用戶端部分具備斷線重連、、收到確認、閱讀確認、訊息發送、命令執行等功能,確保訊息能夠推送到用戶端,同時也保證用戶端能夠收到、閱讀訊息。
E、 應用範圍
九日升Android訊息推送組件可在以下情境中使用:
1)、用於訊息推送。如:通知下達、應急指揮等。
2)、使用者及時訊息互動。如線上聊天、工作情況互動等。
3)、用於遠端控制。如控制遠程用戶端的狀態、資料上報等。
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應用程式發送資料的服務。該服務提供了一個簡單的、輕量級的機制,允許伺服器可以通知行動裝置 App程式直接與伺服器進行通訊,以便於從伺服器擷取應用程式更新和使用者資料。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)(XML)的協議,它用於立即訊息(IM)以及線上探測。這個協議可能最終允許網際網路使用者向網際網路上的其他任何人傳送立即訊息。
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協議我們還可以進一步的對協議進行擴充,實現更為完善的功能。採用這個方案,我們目前只能發送文字訊息,不過對於推送來說一般足夠了,因為我們不能指望通過推送得到所有的資料,一般情況下,利用推送只是告訴手機端伺服器發生了某些改變,當用戶端收到通知以後,應該主動到伺服器擷取最新的資料,這樣才是推送服務的完整實現。