說Android端外推送比較煩,實際有兩層意思:首先是說實現上比較麻煩,至今業界也沒有找到一種完美的解決方案,Android程序員一般須要同時集成多家推送平臺(若是有本身的端內推送,還要考慮與端內推送的配合);其次是說Android推送的市場現狀比較混亂,不管選擇哪一家,都讓人糾結萬分,不免心情煩躁。不管是你花費了多少功夫,作了多少優化,仍然可能存在推送不到或推送延遲的狀況。html
網上已經有不少關於Android推送的討論,但不多有站在App開發者(特別是開發App的創業團隊)的角度來進行介紹的文章。本文的目的,就是站在一個App開發團隊的角度,集中討論兩方面的問題:android
一般大廠的App都會區分端內推送和端外推送(端指的是客戶端),具體說來:git
從這個過程來看,大廠的App的推送策略能夠歸納爲:優先使用本身的推送,實在不行再走第三方推送平臺。爲何這樣呢?由於本身的推送系統更快、更有保障:程序員
咱們雖然算不上大廠,但咱們維護的微愛App也是有本身獨立的端內推送的,而端外採用另外幾家推送平臺,後面咱們再詳細講。github
那爲何本文只討論端外推送呢?由於討論端內推送和討論端外推送是徹底不一樣的兩個話題。討論端外推送,咱們主要是在討論怎麼對各家的推送平臺進行選擇,以及集成各家SDK的時候咱們應該重點注意哪些問題。這一般是不少初創團隊更須要的。編程
而討論端內推送,主要應該討論一個推送系統的具體實現,這是一個比較複雜的問題,並非一篇文章就能討論清楚的。在這裏,咱們只是浮光掠影地瀏覽一下這個話題可能涉及到的內容,但不作展開討論:安全
綜上,本文要討論的重點是端外推送。服務器
端外推送咱們必須依賴第三方的推送平臺了。微信
這個狀況其實原本跟iOS上相似。在端內推送系統的長鏈接失效的時候,咱們就只能經過其它的推送平臺來完成。在iOS上咱們只用使用APNs就好了。網絡
而在Android上,跟APNS對應的服務是谷歌的GCM (Google Cloud Messaging),但很惋惜它在國內的可用性不高(主要緣由是手機廠商對Android系統的定製化,可能會將GCM服務裁減掉,以及國內運營商的一些限制)。若是咱們作的是一個海外的應用,那麼端外推送基本只用考慮GCM就能夠了。
那國內的Android推送平臺有哪些能夠選擇呢?
根據我我的瞭解到的信息,我列出了下面這些(排名不分前後):
上面提到的各推送平臺大致能夠分爲三大類:
要對這些推送平臺進行選擇,咱們首先要知道各種推送平臺的優點分別是什麼。
首先,對於手機廠商的推送,他們的推送服務在他們本身生產的手機上屬於系統級別的服務,理論上來講,手機系統對他們自家的推送限制最小。
好比,在小米手機上,不在系統自啓動名單裏的App,在手機重啓後,App聲明的後臺Service並不會自動運行。可是,小米推送做爲手機系統級服務,仍然是能夠收到推送的。
一樣,華爲推送的技術團隊也對外宣稱(原話):
華爲Push,在華爲手機上是系統級別的服務,穩定性等各方面確定都會好些。
可是,即便是系統級別的推送服務,也不是百分百保證消息送達。這裏比較奇葩的是華爲推送,下面是他們技術支持給出的描述(原話):
華爲手機上:
Emui3.0上,Push廣播有很大機率被限制,如: Mate7 3.0版本,榮耀6plus,P7 3.0版本,4X, 4A等。
Emui3.1上,Push廣播基本不被限制,但個別型號機型存在問題,如:榮耀5x等。
Emui4.0及以上,Push廣播有較高几率被限制,不被限制的機型如:榮耀暢玩4C,榮耀暢玩4X,Mate S,P8 MAX等。
如廣播被限制,須要將應用設爲開機啓動項。因此對於及時性或到達率要求很是高的應用,咱們建議應用要考慮替代方案。
後續Push版本,華爲將採用新的設計方案,解決被限制的問題,但發佈計劃待定。另外,至於限制的問題,其實華爲sdk仍是能接收到推送消息的,當將消息經過廣播發送給應用是,若是手機管家查到該應用處於stop狀態,那麼會攔截該廣播的。
看完以後的感受:還真他媽複雜!
總之,華爲手機上的推送,華爲推送本身也不太徹底能搞得定的。可是,咱們考慮再三,彷佛也沒有更好的選擇了。
再說第二類:專業的第三方推送。他們的優點看什麼呢?看他們「保活」和「互拉」的能力。舉個例子,假設你接入了友盟,而剛好今日頭條也接入了友盟。有一天你的App被殺死了,可是今日頭條的裝機量估計比你的要大啊,這時用戶啓動了今日頭條,那麼推送系統也就會經過共享的推送通道順便把你推送消息送達到手機上,而後還可能把你的進程也喚醒(被「保活」了)。
這麼說來,選第三方推送平臺,這個推送平臺的規模效應就很重要了。那如何得知他們的規模和市場份額呢?最好的辦法是問內部的朋友。不然,其實也沒什麼好的辦法,每家確定對外都說本身最好啊。有一個不太精準的方法,就是看他們的合做客戶裏有哪些大的app,到他們官網上的合做案例裏去看。這個信息總不能亂寫把。
而對於BAT大廠的推送呢?看起來並無什麼優點。各家的「全家桶」採用的「保活」陣營和推送通道,跟他們開放出來的是兩碼事。好比,你不要覺得用了騰訊信鴿推送,就能占上微信的光。
這裏須要單獨提一下的是阿里雲的移動推送。在他們官網上提到,手機淘寶就是用了阿里雲的這個推送。不過仔細研究一下會發現,手機淘寶也在同時使用其它的第三方推送平臺啊(好比友盟推送)。兩個平臺到底誰借誰的力更多呢?不得而知啊。
綜合上面的分析,咱們在微愛的Android客戶端裏使用的推送方案基本以下所述:
注意:小米推送在非小米手機上固然也能工做,只不過就不是系統級別的服務了,受的限制就多一點。同理,華爲手機也同樣。咱們之因此這樣選擇,是爲了讓不一樣的推送運行在各自擅長的環境裏。
基本的架構圖以下:
原本呢,對於推送平臺的選擇問題,到這裏就應該結束了。可是,最近發生了一件事,讓咱們以爲被X-Push這家坑了一把,這讓咱們忽然意識到了一個選擇陷阱。如今把它分享出來,好讓你們選擇的時候必定要擦亮眼睛。
事情大體通過是這樣的:咱們開始集成X-Push這家推送的時候,使用的是免費版服務。可是,咱們用了一段時間以後,他們的銷售找了過來。宣稱他們SDK裏的「看護功能」,是付費功能,若是不付費,技術那邊就會經過一些操做關閉這一功能。這裏他們提到的「看護功能」,大概就是本文前面提到的「保活」和「互拉」的能力。
這個事情的關鍵點在於什麼呢?
若是把這件事的所有細節寫出來,恐怕還須要額外的5000字。因爲本文的主要目的仍是分享技術選型的經驗,因此這裏點到爲止,能把事情的大體通過說清楚就行了。等這件事塵埃落定之後,咱們也許還有機會再從新拿出來說一講這個故事。
可是,這裏你要記住的是,在你選擇一家推送平臺以前,必定要找人問清楚對方收費的模式,有沒有隱性的消費陷阱。記住:沒有人主動會告訴你喲。
你們也別問這家X-Push究竟是哪家了,你們本身去體會。這裏能起到提醒的做用就夠了。
對於小的創業團隊來講,本身實現端內的長鏈接推送系統,成本仍是不小的。
其實呢,各個第三方推送平臺也是能夠在端內使用的。並且,他們通常也對iOS的APNs推送也有封裝。因此,在資源緊缺的狀況下,小團隊在初期也能夠選擇某家第三方推送平臺作本身所有的推送服務,能快速地同時支持Android和iOS兩個平臺推送。等後邊人手充裕了,再考慮進行優化,或加入新的推送渠道。
具體怎樣選擇,還在於你本身權衡。
一般第三方推送平臺都支持兩種推送消息類型:通知欄消息和透傳消息。
通知欄消息,在被送達用戶的設備後,直接以系統通知的形式展現給用戶。它不會繼續被傳遞到App。
而透傳消息,在被送達用戶的設備後,還會繼續路由到App,經過回調App的某個BroadcastReceiver的形式將消息傳遞到App內部。而後由App決定如何處理和顯示這個消息。
這兩類消息在送達率的保證上有所不一樣,固然在提供的編程能力上也很是不一樣。
透傳消息在整個消息傳遞過程當中比通知欄消息多了一步,所以就增長一些被系統限制的機率。因此說,通知欄消息比透傳消息應該能提供更好的送達率。
好比,小米推送的文檔中就這樣描述:
在一些 Android 系統(如 MIUI)中,受到系統自啓動管理設置的限制,應用不能在後臺自啓動。在這類系統中,若是在發送消息的時候對應的應用沒有被啓動,透傳類消息將不能順利送達。所以,對於對送達率要求很高的消息,建議儘可能採用通知欄提醒的方式推送消息
若是App有本身的端內推送系統,那麼這種通知欄推送消息就更合適一些。當端內推送的長鏈接失效時,咱們經過通知欄消息把提醒展現給用戶,由用戶喚起咱們的App,而後真正的消息數據再經由端內推送達到客戶端。
實際上,咱們就是採用通知欄消息這種推送方式的。
而透傳消息,提供了對消息數據的更靈活的操縱能力。App若是僅僅經過通知欄消息,是沒法接觸到消息數據自己的。
因此,若是App沒有本身的端內推送系統,而是採用第三方推送做爲端內推送通道,那麼就只能使用透傳消息。
另一個例子,若是App想自定義通知提醒的樣式,以及提示聲音,恐怕也只能經過透傳消息來本身實現。通知欄消息一般提供不了那麼靈活的配置。
這裏有一點須要說明的是,當透傳消息送達設備後,若是在試圖路由到App內部的時候,發現App進程不在,那麼理想狀況下它應該「拉起」App進程。因此,照此推測,若是前面提到的那家X-Push關閉了「看護功能」的話,那麼透傳消息會受到多大的影響呢?結果可想而知。另外,X-Push那家的銷售說了,關閉「看護功能」,對通知欄消息的「消息觸達效果」也是有影響的。無語......
咱們使用第三方推送平臺,最關鍵的地方在於前兩個步驟:
這裏的推送token,在不一樣的推送平臺上的叫法不太同樣,好比在小米推送中被稱爲reg id,在華爲推送中被稱爲token,在個推中被稱爲cid,在友盟推送被稱爲Device Token。總之,它是推送平臺對設備的惟一標識。咱們這裏統稱它爲「推送token」是爲了方便討論。
App的客戶端拿到它以後,必需要同步到本身的服務器,並與本身的用戶ID創建起對應關係。這樣當咱們想推送消息給咱們的某個用戶的時候,咱們才能查到對應的推送token。
前面說的初始化和推送token同步這兩個步驟,看起來很簡單,只是調用SDK的現成接口,再把它發送給服務器而已。可是,好的代碼不只能在正常狀況下工做,還應該充分考慮失敗狀況。有什麼樣的失敗狀況須要咱們考慮呢?咱們以小米推送爲例來分析一下:
上述第一種初始化錯誤,理應由推送SDK來處理。若是失敗,它應該會有重試機制,直到成功獲取了推送token,它再從新調用App把推送token傳過來。好比,小米推送平臺也是這麼宣稱的,初始化可能出現的錯誤,App開發者不用考慮。若是你充分信任推送平臺,那麼這個錯誤實際上是能夠不用去考慮的;不然,你能夠在App裏增長某些機會來檢測初始化是否已經成功(能夠經過檢測是否已經拿到推送token來肯定),而後在恰當的時機從新調用初始化代碼。固然,在作這個事情以前,你最好與推送平臺溝通清楚,確保重複調用初始化代碼不會產生什麼反作用。
上述第二種錯誤,就必須靠App開發者本身處理了。這裏咱們實際上須要在App客戶端和服務器之間抽象出一條強的通訊通道,咱們把同步推送token的請求放進去,這條通訊通道可以在失敗發生的時候自動重試。
這裏的代碼寫得是否是足夠健壯(robust),不一樣level的程序員就高下立判了。
咱們能夠說,恰當而全面地處理失敗狀況才能真正體現工程師的意義,這也是工程和理論研究的不一樣點之一。
推送作得好很差,以及咱們選擇推送平臺選的好很差,關鍵在於送達率高不高。送達率這個概念,一直是個很混亂的概念,有些平臺會宣稱送達率能達到98%以上,而又有一些人說行業平均水平也就60%左右。
爲何說法如此迥異呢?是由於你們在說的其實不是一個送達率。
友盟的消息推送業務線負責人陳漠沙曾專門寫過一篇文章,來澄清送達率概念的一些誤解,文章寫得至關好,建議作推送業務的同窗必定要讀一下:
關鍵是要分清此文中定義的「在線送達率」和「通用送達率」。
「在線送達率」,各個推送平臺優化到最後,可能都差很少。估計都能達到98%以上。
而「通用送達率」纔是真真正正把消息推送到你的App的最終的送達率,這個也纔是用戶最終能感覺到的送達率。App開發者須要真正關注的也是這個。
「通用送達率」大概來說,是最終到達App的消息數與開始發出的消息數的比率(在必定時間內監測)。跟這個比率直接有關的因素是兩個:
因此,這麼提及來,不一樣的App因爲業務不一樣,推送調用方式也不一樣,那麼他們的通用送達率就沒有實質的可比性。
那假如咱們推送作了某個優化,或者某天換了一個更好的第三方推送平臺,咱們怎麼知道這個改動是好仍是壞呢?答案是咱們能夠本身跟本身比。持續監測通用送達率,比較改動先後的變化。
GitHub上有一個討論Android推送的帖子(由@Trinea建立):
這個帖子從2015年5月份開始討論至今,仍然沒有人給出一個完美的解決方案。
隨着各個手機廠商的市場份額的變化,以及推送平臺市場的變化,Android推送也是一個不斷處於變化中的話題。今天的結論,換到明天,也許就未必再適用。
因此,推送服務的實現者們也固然要擁抱變化。必定要確保你的推送架構可以很容易地切換某個第三方的推送渠道。
多年的創業經驗告訴咱們,不僅是推送服務,也包括衆多其它的雲服務,僅僅依賴一家平臺的作法,都是極其愚蠢的。
因爲國內的各大手機廠商對於安卓系統作了各類不一樣的定製,增長了不少安全性的限制,致使推送成了一個很複雜的問題。而這個市場中又沒有哪一家完美解決了全部手機設備的推送送達的問題。同時,微信因爲其先發優點和規模優點,進入了各大廠商受保護的白名單,進一步拉開了與其餘App在推送送達率上的距離。
最後不禁得感慨一句,若是谷歌一直在中國,還會有這種亂局出現嗎?
(完)
其它精選文章: