Android推送全鏈路簡析

前言

國內的Android推送就是個悲劇

國內Android缺少Google的生態(tài),如Google的Paly Store,Google Mobile Services(GSM)等涯鲁,導致衍生出很多畸形的產業(yè)卫袒,比如五花八門的APP市場扣唱,光怪陸離的推送平臺汞舱,這里要說的是推送平臺。Google本身的GSM服務是包含一套推送在里面的隆夯,跟iOS系統(tǒng)的推送類似钳恕,它保證每臺手機維護一個推送通道就能收到各方推送,但由于Google沒法進入中國市場蹄衷,國產Android基本上算被閹割了一個核心部件忧额,由此衍生的種種弊端數不勝數,首當其沖的就是推送宦芦。

國內的手機廠商基本都有自家的推送服務宙址,來替代GSM的缺失轴脐,性能调卑、用法參差不齊。在離線場景下(APP死亡)大咱,如果想要收到推送恬涧,就必須接入對應廠家的推送服務,否則壓根收不到碴巾。所以Android APP在誕生之初基本就要集成華為push溯捆、小米push、魅族push厦瓢、oppo push提揍、Vivo push等,相對GSM煮仇,復雜且沒有增益劳跃,就好比用江南七怪代替了黃老邪,難用的一B浙垫。然而刨仑,你別無選擇。不過國內各種廠商倒是樂此不疲夹姥,他們多了一個觸達用戶及統(tǒng)計的渠道杉武,并且還能不受Google挾制,對于開發(fā)者而言辙售,就要麻煩很多轻抱,工作量平白翻了很多倍;有的聊天APP為了走自家的推送SDK旦部,還要琢磨各種黑科技:包活祈搜,APP相互喚起等封拧,惡之花,開的漫山遍野夭问。更有意思的是泽西,為了解決這種問題,制定出規(guī)范缰趋,還促生個各種機構捧杉,像推送聯盟,綠色聯盟等秘血,但并沒什么卵用味抖,成立3年,亂象依舊灰粮,很多說Android很垃圾仔涩,那推送的這個問題要負一大半責任。

吐槽完粘舟,你仍然要接熔脂。

推送概念

為什么一定要接廠商的推送SDK呢?不接入收不到推送嗎柑肴?想要弄清這個東西霞揉,就要對推送有個簡單的了解,推送:它的點在推(push上晰骑,與其對應的是拉(Pull)适秩,核心就是客戶端跟服務器建立一個長鏈接,服務器會將信息分發(fā)到各個客戶端硕舆,簡化示意如下:

image

對于手機端APP來說秽荞,推送分APP在線推送還是離線推送,其實就是APP是否存活抚官,APP存活情況下扬跋,有多種選擇,如果APP通過Socket跟自家服務器建立了鏈接耗式,則可以由自家服務器直接推送到APP端胁住,也可以通過后端推送到第三方推送服務,借由第三方推送給APP端刊咳,也就是在線情況下彪见,可以不用接入第三方SDK。但是在APP死亡的情況娱挨,只有一種方式:借由第三方推送服務余指,推送給手機端,這種場景,APP必須接入第三方廠商SDK酵镜,拿華為平臺為例碉碉,其推送模型如下:

華為消息回執(zhí)模式

與兩者對應也有兩種消息的概念:透傳消息與通知欄消息:

  • 透傳消息:APP存活情況下,由推送服務直接把消息發(fā)送給APP應用淮韭,由APP自己選擇如何處理垢粮,注意透傳的前提是APP存活 ,透傳消息可以不用接入第三方SDK靠粪。
  • 通知欄消息:在設備接收到消息之后蜡吧,由系統(tǒng)彈出標準安卓通知,用戶點擊通知欄才激活應用占键,這種場景昔善,APP無需存活(活著也不受影響),離線場景下畔乙,只有通知欄消息這一條路君仆。

透傳消息每個APP自己維護一條通道,離線消息只要一條系統(tǒng)通道牲距,簡單看下兩者對比返咱,示意如下:

image

對于在線透傳消息,由于是在APP存活的情況下收到的嗅虏,APP端可以統(tǒng)計到所有必要信息洛姑,無論是推送達時間、推送內容還是通知的點擊都能統(tǒng)計到皮服;但是離線推送就沒那么幸運,很多信息APP自己是拿不到的参咙,但是龄广,業(yè)務方通常非常關心到達率、點擊率這些數據蕴侧,必須有一個有效的解決方案择同。

推送統(tǒng)計問題 (離線推送)

如何到達率

這里不考慮在線推送,只考慮離線(APP死亡)净宵,那么離線推送APP能統(tǒng)計到達嗎敲才?

答案是 不能,原因其實很簡單择葡,APP進程都死了紧武,怎么統(tǒng)計。這種情況下敏储,通知的展示屬于系統(tǒng)行為阻星,APP壓根無法感知,更無從統(tǒng)計已添。不過妥箕,各三方推送服務平臺扔提供了推送到達統(tǒng)計的能力滥酥,即采用三方推送平臺的回執(zhí),以上面的華為推送模型為例:

華為消息回執(zhí)模式

可以看到畦幢,離線推送的情況下坎吻,華為設備在展示完通知欄消息后,會給華為Push服務一個回執(zhí)宇葱,而華為Push服務會把這個回執(zhí)頭傳給開發(fā)者服務器禾怠,如此,APP服務端就能判斷推送是否到達贝搁。

如何統(tǒng)計點擊率

同樣吗氏,在離線推送的場景下,能統(tǒng)計到點擊事件嗎雷逆?關于這個場景弦讽,不同的廠商ROM及SDK真是亂七八糟,有的支持膀哲,有的不行往产,簡單整理下如下:

ROM 小米 華為 魅族 oppo vivo
App是否可以統(tǒng)計到離線點擊事件

因此,各方平臺給的方式并沒太多參考意義某宪,必須通過其他方式來統(tǒng)計點擊仿村,離線推送基本都是通過scheme方式來處理,可以通過加參數來搞定兴喂,后續(xù)詳述蔼囊。

推送送達率=本次推送真正送達的設備數/所覆蓋的所有設備數(按理說,是應該清理掉無效設備)

哪些因素影響送達率

    1. 留存率衣迷。已經卸載了APP畏鼓,肯定收不到,但是有些三方平臺可能會歸結到分母中壶谒,需要自家后臺根據回執(zhí)手動清理regID云矫。
    1. 消息有效期,基本所有第三方PUSH平臺都支持設置有效期汗菜,有效期越短让禀,觸達設備就越少,送達率會下降陨界,可以適當選擇有效時間巡揍。
    1. 聯網情況, 在有效期內普碎,設備沒聯網吼肥,也無法送達,但會被計入分母
    1. 目標人群設備的選取,活躍人群設備送達率肯定要高于全量推送

因此為了能精準的計算送達率缀皱,APP服務端要定期清理無效regID(推送token)斗这,否則統(tǒng)計的送達率也會偏低

各離線推送平臺接入事項

很多大公司都有自家的推送SDK來處理透傳消息,小公司一般不具備這個能力啤斗,所以在接入Push的時候也分兩種情況表箭,

  • 1:有自己加的PushSDK,
  • 2:沒有自家PushSDK

如果APP有自己的PushSDK钮莲,那只要接入第三方離線推送能力就好了免钻,一些關于透傳的處理配置可以完全不用關心,用自己PushSDK那套就可以崔拥。如果沒有自家PushSDK极舔,那就需要選擇一個SDK進行透傳處理,當然链瓦,仍要接入第三方離線推送能力拆魏。不過即使如此,各家ROM的接入規(guī)則也個不相同慈俯,比如小米有個奇葩的權限叫:“后臺彈出界面權限 ”渤刃,如果后端服務Push姿勢不對,可能會引入奇葩問題:比如贴膘,手機能收到PUSH卖子,但是拉不起界面,坑爹刑峡。

簡單看下各ROM計入注意事項洋闽,只看離線能力,不考慮透傳:

小米

關于MIPUSH的接入氛琢,直接看官方文檔即可喊递,沒太多問題,需要注意的是阳似,小米有個奇葩的權限設置:后臺彈出界面權限 ,該權限默認是關閉铐伴,這個選項可能會影響推送通知的點擊行為撮奏,小米有兩大類點擊行為:

完全自定義點擊行為

在這種行為下,開發(fā)者可以攔截通知點擊事件当宴,自定義如何處理后續(xù)事件畜吊,點擊后,MiPushMessage通過PushMessageReceiver繼承類的onNotificationMessageClicked方法傳到APP進程户矢,開發(fā)者可自行處理玲献,如果想要啟動界面,只需要在其中調用context.startActivity方法即可,但是捌年,這種自定義的行為會受到后臺彈出界面權限的影響瓢娜,尤其是高版本的MIUI ROM中。

image

你會發(fā)現礼预,在這些手機上眠砾,此方式壓根沒法拉起APP,除非通過先啟動一個Service托酸,然后在Service中拉起褒颈,非常像小米的一個BUG,并且励堡,即使通過此下策能拉起谷丸,你會發(fā)現,拉起速度非常慢应结,可能是過多AMS交互通信導致的刨疼,所以這種策略可以斃了。

預定義點擊行為

預定義點擊行為不用用戶在onNotificationMessageClicked中處理摊趾,系統(tǒng)會直接拉起目標頁面币狠,小米支持三種預定義點擊行為:

  • (1) 打開當前的Launcher Activity
  • (2) 打開當前app內的任意一個Activity
  • (3) 打開網頁。

APP一般會采用第二種行為砾层,打開APP任意一個Activity漩绵,其實最終會選擇一個DeepLink Activity,由其路由到其他界面肛炮。服務端調用Message.Builder類的extra(String key, String value)方法止吐,將key設置為Constants.EXTRA_PARAM_NOTIFY_EFFECT,value設置為Constants.NOTIFY_ACTIVITY便可以達到該效果侨糟,用戶點擊了客戶端彈出的通知消息后碍扔,封裝消息的MiPushMessage對象通過Intent傳到客戶端,客戶端可在Activity中解析秕重,并自行處理后續(xù)流程不同。離線推送情況下,推送服務端核心字段如下:

image

采用離線非透傳消息溶耘,并利用extra自定義Click行為二拐,最后推送給小米的消息格式簡化如下:

{
    title=通知標題, 
    description=通知內容, 
    restrictedPackageNames=[com.test.example], 
    notifyType=1, 
    notifyId=1249808047, 
    <!--打開任意Activity配置-->
    extra.intent_uri=yanxuan://re?opOrderId=crm_a1d05c1d3d1743e192a08b461a376785_20200715,
    extra.notify_effect=2
}

extra.intent_uri的值就是APP端定義的私有scheme,點擊通知會直接拉起相應的DeepLink Activity凳兵,從而喚起應用百新,至于DeepLink Activity最終路由到哪個界面,可以從extra.intent_uri中解析出來庐扫。對于上文層說過的click事件不易統(tǒng)計的問題饭望,可以通過在scheme家參數的方式解決仗哨,如下:

extra.intent_uri= yanxuan://re?opOrderId=0200715, 

轉為

extra.intent_uri= yanxuan://re?opOrderId=0200715&platform=xiaomi 

之后在路由Activity中可以解析出platform參數,從而標記click事件及來源平臺铅辞。預定義行為系統(tǒng)會幫我們處理好喚起厌漂,在APP中,不需要在onNotificationMessageClicked再次響應click事件了巷挥,避免重復處理桩卵。后面其余各方SDK的能力基本都跟小米類似,大同小異倍宾,沒多少花樣雏节。

華為

流程同小米類似,按文檔即可高职,預定義行為有如下四種:

  • 1:用戶定義Uri钩乍,打開目標界面
  • 2:點擊后打開特定網頁
  • 3:點擊后打開應用
  • 4:點擊后打開富媒體信息

一般選擇自定義Uri行為,所有數據通過intent uri傳輸給APP怔锌,依舊是私有scheme的DeepLink實現方式寥粹。對應參數意義如下:

image

基本上,選擇type=1 同 intent uri配合埃元,uri生成格式如下:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?name=abc&age=180"));
String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);

最終通過API發(fā)送給華為push平臺數據格式簡化如下:

"msg":{
    "action":{
        "param":{
            "intent":"intent://member?url=http%3A%2F%2Fm.you.163.com%2Fmembership%2Findex&_yanxuan_hwpush=1&_mid=a397314518947995648#Intent;scheme=yanxuan;launchFlags=0x4000000;end"
        },
        "type":1
    },
    "body":{
        "title":"huawei免郵券禮包",
        "content":"快來領取你的每月專屬免運費券涝涤,立即領取>>"
    }
}

同小米類似,如果需要添加額外參數岛杀,放到scheme中阔拳,不再敖述。

魅族

接入類似类嗤,支持四種預定義行為:

  • 打開應用主頁
  • 打開應用內頁面
  • 打開URI頁面
  • 客戶端自定義

同樣選擇預定義Uri頁面糊肠,具體參數如下

image

最終發(fā)送數據格式簡化如下:

 {
     noticeBarType = 0,
     title = 'meizu明天之后?恢復原價', 
     content = '店慶爆款返場!乳膠床墊直降500遗锣,拉桿箱僅7折货裹!??每滿150減25消費券全品類通用,最后1天>>',
     clickType = 2, 
     url = 'yanxuan://yxwebview?url=https%3A%2F%2Fact.you.163.com%2Fact%2Fpub%2FDisjY2u1n9p4SB3.html%3Fanchor%3DSeen3xcj%26opOrderId%3Dcrm_task_20200414160053263_1'
 }

clickType = 2 配合Uri scheme來實現精偿,預定義拉起對應界面弧圆,如果需要添加額外參數,同上笔咽。

oppo

接入類似墓阀,oppo無法感知click事件,支持五種預定義行為(有冗余):

  • 0拓轻,啟動應用;
  • 1经伙,打開應用內頁(activity的intent action)
  • 2扶叉,打開網頁勿锅;
  • 4,打開應用內頁(利用activity全名)
  • 5, Intent scheme URL
image

處理類似枣氧,選click_action_type選擇5溢十,通過私有scheme拉起APP,具體數據格式如下

{
    "notification":{
        "app_message_id":"a467798011733344256",
        "channel_id":"NotificationChannel",
        "click_action_url":"yanxuan://yxwebview?url=https%3A%2F%2Fact.you.163.com%2Fact%2Fpub%2FDisjY2u1n9p4SB3.html%3Fanchor%3DSeen3xcj%26opOrderId%3Dcrm_task_20200414160053263_1",
        "click_action_type":5,
        "content":"明天之后恢復原價",
        "title":"明天之后恢復原價"
    },
    "target_type":2,
    "target_value":"CN_04f112241e183f6309611df2a95d6237"
}

click_action_type= 5 配合 scheme拉起APP达吞,张弛,如果需要添加額外參數,同上酪劫。

vivo

vivo跟oppo很類似吞鸭,不過它也可以收到click事件(并沒什么卵用),因此支持完全自定義(然而不用)覆糟,支持五種Click行為

  • 1:打開APP首頁
  • 2:打開鏈接
  • 3:自定義
  • 4:打開app內指定頁面

同樣刻剥,為了防止禁止后臺啟動,不采用自定義的方式滩字,而直接打開打開app內指定頁面造虏, "skipType":4,

{
    "classification":1,
    "content":"adssdsr345436",
    "notifyType":1,
    "pushMode":1,
    "regId":"15905547110541891320627",
    "requestId":"a467798011733344256",
    "skipContent":"yanxuan://yxwebview?url=https%3A%2F%2Fact.you.163.com%2Fact%2Fpub%2FDisjY2u1n9p4SB3.html%3Fanchor%3DSeen3xcj%26opOrderId%3Dcrm_task_20200414160053263_1",
    "skipType":4,
    "title":"adssdsr345436"
}

skipType:4配合 scheme拉起APP,麦箍,如果需要添加額外參數漓藕,同上。

各ROM接入事項小結

以上是幾種離線推送的接入方式挟裂,整體總結就是:

  • 盡量選擇預定義Uri scheme方式享钞,不要采用自定義的方式
  • 可以在scheme中填加參數,統(tǒng)一鑒別click事件
  • 在預定義的方式下话瞧,不要在click回調中重復處理事件
  • 如果只要離線推送功能嫩与,沒必要處理透傳配置(比如什么Receiver Service之類的配置)

總結

  • 不得不接入第三方SDK是為了離線推送
  • 各家離線推送大同小異,為了統(tǒng)一建議統(tǒng)一采用預定義Uri方式交排,配合私有scheme拉起APP
  • 額外追蹤參數可以通過添加scheme字段解決
  • 不同ROM可能有自己的額外限制划滋,比如小米,盡量避免受其限制

最后埃篓,Android的推送困境是個悲劇...

作者:看書的小蝸牛
原文鏈接:Android推送的群魔亂舞

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末处坪,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子架专,更是在濱河造成了極大的恐慌同窘,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件部脚,死亡現場離奇詭異想邦,居然都是意外死亡,警方通過查閱死者的電腦和手機委刘,發(fā)現死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門丧没,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鹰椒,“玉大人,你說我怎么就攤上這事呕童∑峒剩” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵夺饲,是天一觀的道長奸汇。 經常有香客問我,道長往声,這世上最難降的妖魔是什么擂找? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮烁挟,結果婚禮上婴洼,老公的妹妹穿的比我還像新娘。我一直安慰自己撼嗓,他們只是感情好柬采,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著且警,像睡著了一般粉捻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斑芜,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天肩刃,我揣著相機與錄音,去河邊找鬼杏头。 笑死盈包,一個胖子當著我的面吹牛,可吹牛的內容都是我干的醇王。 我是一名探鬼主播呢燥,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼寓娩!你這毒婦竟也來了叛氨?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤棘伴,失蹤者是張志新(化名)和其女友劉穎寞埠,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體焊夸,經...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡仁连,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了阱穗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怖糊。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡帅容,死狀恐怖,靈堂內的尸體忽然破棺而出伍伤,到底是詐尸還是另有隱情,我是刑警寧澤遣钳,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布扰魂,位于F島的核電站,受9級特大地震影響蕴茴,放射性物質發(fā)生泄漏劝评。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一倦淀、第九天 我趴在偏房一處隱蔽的房頂上張望蒋畜。 院中可真熱鬧,春花似錦撞叽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诈嘿。三九已至,卻和暖如春糠雨,著一層夾襖步出監(jiān)牢的瞬間才睹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工甘邀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留琅攘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓松邪,卻偏偏與公主長得像坞琴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子测摔,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355