推送簡直就是1種輕量級的騷擾方式
自從有了推送,各個公司基本上都在使用推送,這確切是1個比較好的提示方式,Android較iOS強的1個部份,也就是在于Android的Notification。Google教育我們利用好Android的通知模塊,做更多友好的交互,可這句話,翻譯成中文,不知不覺,就變成了在Notification中推送各種廣告,而且僅僅就是1些廣告,Notification各種牛逼的功能,完全不需要,這也背背了Google設計Notification的初衷。
更關鍵的是,現在隨意找1款App,沒有推送的真是鳳毛麟角,更可惡的是,做外賣的App給我推送奧運新聞,1條新聞10幾個App推送,以致于現在很多用戶都非常反感各種推送廣告,就我本人而言,基本上會禁用所有廣告類的App的推送。
本人非常反感推送,借用王思聰的1句話,XXX App每天給我推送各種廣告,還TM是自己做的推送,真是絕了。
輪詢是最簡單的與服務器保持通訊的方式,即循環向服務器通訊。這個方案的特點就是通訊由客戶端主動發起,你需要自己實現輪詢消息隊列、頻率等等參數,在功耗和效果間做權衡,類似于TCP的短連接。
這個其實就是借助短信來實現信息的展現,只不過把短信內容展現到了Notification中,這個方案,到達率確切高,畢竟短信是比較可靠、穩定的,但劣勢也很明顯,就是本錢很高,而且在Android平臺上,短信的權限比較開放,容易被劫持。
長連接和前面提到的短連接,都是基于Socket連接的方式,他們的區分在與,短連接是每次數據傳輸終了后就斷開連接,而長連接不會。所以,基于輪詢的方式,每次都要進行鏈路的連接,性能消耗更大,基于長連接的方式,就是對這點的改進。利用1旦與服務器連接成功,其實不會主動斷開連接,后面的通訊都基于這個通道。目前大部份的推送服務都是基于長連接的推送,在后臺保護1個Service,保持利用與服務端之間的TCP長連接。
iOS這邊使用系統統1的APNs,所有推送消息都由蘋果的服務器進行下發,同時,也由系統進行統1展現和處理。
與iOS1樣,Android一樣有1套內置的推送方案,但很惋惜的是,Google的服務在中國大陸沒法使用,草了個蛋。
專業的第3方推送
手機ROM廠商推送
BAT級別的全家桶
關于第3方推送服務在各個App中的使用率,大家可以參考賈吉鑫的這篇文章:
https://mp.weixin.qq.com/s?__biz=MzA5OTMxMjQzMw==&mid=2648112527&idx=1&sn=b23c1b5f3e32e343ad96d705bd4d63ff
這些推送服務大同小異,基本上1家使用了1個新功能,另外幾家,也會很快推出這個功能,就例如之前比較火的,『同享推送通道進行App喚醒』這個技術,友盟、個推推出后,很快其它推送服務商就支持了,所以開發者其實不需要擔心哪1家推送功能比較強。
這里還需要說下現在的『推送喚醒』這樣1個功能,簡單的說,就是所有安裝了A推送的App,只要有1個還活著,就能夠把其它安裝了A推送的App拉起來,從而提高推送的到達率。有些阿里系、百度系的App,被大家稱作『全家桶』,實際上就是由于這個緣由,這個方式,確切能在1定程度上提高推送到達率,但另外一方面,也破壞了Android生態,增加了功耗,打亂了系統的清算策略。
另外,小米推送、華為推送,大家接入的緣由可能很簡單,就是他們的手機市場占有率比較高,接入他們自家的推送,可以在1定程度上提高到達率,但需要注意的是,推送分為透傳和非透傳兩種方式,透傳即我們自己App處理推送消息,而非透傳,則是交給相應的PushSDK處理,對小米推送、華為推送來講,只有采取非透傳消息,到達率采取保證,而透傳消息,與其它推送并沒有甚么區分,換句話說,小米手機、華為手機,只對非透傳的推送消息做了可靠性保證,但非透傳消息的展現格式非常固定、簡單,且不能自定義,這是1個很大的問題,這點應當是很多開發者的誤區。
最后,很多推送服務都需要在Application中進行初始化,同時,各種被喚醒策略,又會拉起Application,致使推送進程的重復,所以,這里常常需要對進程名進行過濾,非主進程,不進行初始化。
基本都是基于AndroidPN、MQTT、XMPP、長連接這些方式去實現的,自己搭建Push平臺服務,1個最大的問題就是服務真個架構設計,不但本錢高,而且效果不1定好,建議中小企業不要輕易嘗試。
1般來講,類似這類ID都是用于唯1標識利用\用戶的,每一個App在每臺手機上都會生成1個唯1ID。
Android平臺上由于國內存在大量山寨裝備,所以很多裝備的IMEI、Mac地址、AndroidID 都有可能為空或毛病,所以不能單獨作為唯1標識,需要將這些進行組合起來使用。
對利用卸載后RegistrationID的問題,很多PushSDK的策略是,生成1個DeviceID保存到本地存儲,利用被卸載后如果被重新安裝,如果檢測到存儲里的DeviceID還在的話,就判定是同1個裝備,不重新生成RegistrationID。
這些Key基本都是用于驗證App的,每一個包名對應1個加密的Key。
非透傳消息是指推送消息被PushSDK獲得并處理,透傳消息是指推送消息被PushSDK交給宿主利用處理,非透傳消息通常只能設置1些固定的樣式,比較簡單,而透傳消息,可以由App自定義處理,比較靈活。
通過利用使用的appid統計用戶注冊總量。
通過利用使用的appid統計當天的在線用戶數。
通過利用使用的appid統計當天在推送平臺激活過的用戶總數。
在線消息下發數/總下發數。
消息回執數(去重)/消息在線下發數。
到達數/實際下發數。
是指最近3個月內有登錄過(裝備與推送服務端建立長鏈接)的裝備總數,即有效可下發的用戶數。1般的推送服務端認為,裝備在100天內沒有登錄要求,認為該裝備已失效,所以無需再次發送。
實際可推送裝備數(在消息有效期內,有聯網并推送進程正常的裝備,即消息有效期內的在線下發數。消息有效期就是設置的離線時間)。
客戶端SDK接收到消息的裝備數(通過統計客戶端SDK接收到消息后的回執取得)。
用自定義非透傳消息在用戶手機展現過的裝備數。
點擊通知欄消息的裝備數。
那末關于推送,大家實際上最關系的,就是『到達率』。那末這個到達率究竟怎樣計算呢?
首先我們舉個例子來講明上面的這些數據背后的實際意義,例如,我們有1款App,有100w的下載量,每一個App啟動后,都將上報給服務器1個唯1ID,所以,累計注冊量就是100w,也稱發送總量。
那末在服務端準備發送推送的時候,當前手機端推送進程還活著的,也就是說推送的長連接還健在的,就是在線裝備,如果按天算,那末就叫日在線裝備數,我們假定這個數字是60w。
OK,推送發出去后,客戶端收到推送消息,并產生回執,代表完成了1次推送,假定這些完成推送的裝備是55w,這個就是投遞裝備數。1般來講,只要裝備在線,基本都能投遞,所以這個數字和在線裝備數非常接近,不接近的話,這個推送基本就有問題了,其中可能送不達的緣由就在于網絡切換等致使長連接斷掉這類因素。
那末到這里,1般的推送服務商會使用投遞裝備數/在線裝備數的方式來計算到達率,固然,前面我們也說了,這個比例1定是很高的,如果保持長連接的裝備都不能收到推送,那1定是有問題了。
而1般的到達率,應當是投遞裝備數/可投遞裝備數,也就是百日內活躍的裝備數,這樣1除,這個比例1下子就小了很多,由于誰也不知道,這1百天內曾活躍的用戶,第2天是否是就已把你卸載了。所以說,Android下統計推送的到達率1般都很低,而推送服務商宣揚的到達率都很高,這其實就是1個偷換概念的問題,我們說的是1般的到達率,而服務商宣揚的是在線到達率。
而且,這個到達率與iOS完全沒有可比性,由于iOS統1通過APNs來進行推送,且沒法獲得到達回執,所以,iOS基本不存在到達率這1說法,如果有,幾近也是100%,完全沒成心義,所以,如果哪1天有產品或運營跟你說,為何Android的到達率比iOS的到達率差這么多,請絕不客氣的砸它1斤蘋果。
Tag,或叫標簽,是用戶的1種屬性,在給某些用戶設置某類標簽后就能夠針對推送。比如給喜歡『編程』的人打上『編程』的標簽,就能夠只給他們精準推送。
通常情況下,1個裝備(在1個App里)可以設置多個標簽。標簽與別名類似,其對應關系也是保存在推送服務器側的。
Alias,或叫別名,是對已安裝某利用的用戶取個別名進行標識,在對該用戶消息推送時,就能夠用此別名來進行推送。設置了別名后,推送時服務器端指定別名便可。推送服務器端來把別名轉化到裝備ID來找到裝備。
Tag和Alias他們的共同點在于,提供對用戶的精確推送。
目前大部份的第3方推送服務,都是基于長連接的推送方案,下面將對這個方式進行詳細講授。
首先,我們需要了解下1個網絡基本知識——NAT,即網絡地址轉換(Network Address Translation,NAT),這是由于IP地址是有限的,手機不管是通過路由器還是數據網絡,都有1個內網IP地址,同時,路由器上會保護1個外網IP地址,從而構成1個NAT路由表,即內網IP地址:端口,和對應的外網IP地址:端口。這樣通過1層層封裝與解封裝,就到達了內網與外網交換通訊的方式。
由于NAT路由表的大小有效,所以1般路由都有NAT有效期,WIFI下,這個NAT有效期可能會比較長,而在數據流量下,運營商1般都會盡快更新NAT路由表,淘汰無效的裝備,所以,在使用數據流量時,長連接常常容易斷。
那末除NAT路由表主動淘汰過期的裝備以外,切換網絡環境和DHCP服務器租期到期,這些情況都有可能致使NAT路由表改變,從而造成長連接中斷。
前面我們說了,現在的推送服務1般采取的是長連接的通訊方式,而長連接會由于NAT路由表的更新而中斷,所以,客戶端會定時向服務端發送1個心跳包,來定期告知NAT路由表,我還活著,別殺我!這就是心跳包的作用——避免NAT路由表超時,同時檢測連接是不是被斷開。
既然心跳包的作用是避免NAT超時,那末就需要將心跳包的發送頻率設置為小余NAT超時的檢測頻率,而WIFI和數據流量下,對NAT路由表的超時時間又是不1樣的,而且不同的網絡運營商的超時時間,乃至都不1樣,所以,1個比較好的方法就是根據裝備當前網絡環境,來動態的設置心跳時間。
注意,心跳包與輪詢是不1樣的,心跳包建立在長連接上,只要發送數據便可,而輪詢每次都是1個完全的TCP連接。
既然需要定時任務,那末就需要使用AlarmManager來作定時喚醒了,緣由我之前的文章有講過,是關于處理器喚醒的緣由,這里就不贅述了,大家可以參考我之前的文章:
http://mp.weixin.qq.com/s?__biz=MzAxNzMxNzk5OQ==&mid=2649484680&idx=1&sn=bd9086a95b769af8d8644cf681ce66ec#rd
介于各種第3方推送與ROM推送的特點,我們目前采取的推送方案,名為『UniversalPushSDK』,即整合了多個不同的推送渠道,通過模板設計模式來進行整合,并向外暴露統1的接口,這類方式的好處在于UniversalPushSDK利用的各個不同推送特點,提高推送到達率,但是壞處在于,包的體積會大1些。例如,我們現在整合了『小米推送、極光推送、華為推送』,在系統啟動的時候,判斷當前系統,如果是小米系統,則啟用『小米推送』,如果是華為手機,則啟用『華為推送』,其它的Android裝備,則啟用『極光推送』,通過這類方式來設計我們自己的推送SDK,可以在1定程度上,利用好各個推送平臺的特性。
那末如果利用這類方式來設計SDK給到不同的App接入,就需要能夠將利用的推送Key做到動態配置,這也是我們遇到的最大的1個問題,解決方法大家可以參考我之前寫的1篇文章:
http://blog.csdn.net/eclipsexys/article/details/51283232
雖然我極力反對這類方案,我堅持認為,做好App,提升用戶使用黏性,才是提升推送到達率的關鍵
上一篇 c實現set集合