本帖最后由 前前前的世 于 2018-5-9 09:42 編輯 一、前言 隨著安卓手機(jī)以及QQ/微信/支付寶/滴滴出行/美圖外賣等一大批移動通信/移動消費(fèi)應(yīng)用的日益普及,,我們無時無刻不在享受著這些移動產(chǎn)品帶來的便利,;但同時也會遇到一些困擾,比如QQ/微信/支付寶消息延遲,、微信/支付寶收款無語音播報,、滴滴出行/美圖外賣商家版在后臺不能及時接單等問題,這些問題歸根到底還是Android應(yīng)用消息推送服務(wù)體驗(yàn)差,。 移動互聯(lián)網(wǎng)時代,,消息推送是移動應(yīng)用的一項(xiàng)重要功能,今天我們來聊聊聊APP消息推送機(jī)制,,順帶著為大家解決微信消息延遲問題,。 二、國內(nèi)APP消息推送機(jī)制 目前中國安卓系統(tǒng)生態(tài)環(huán)境尚不成熟,,設(shè)備碎片化現(xiàn)象嚴(yán)重,,導(dǎo)致不同應(yīng)用與操作系統(tǒng)在適配性方面產(chǎn)生了一系列問題,消息推送服務(wù)也會遇到各種障礙,。雖然在安卓手機(jī)上谷歌有推出GCM服務(wù),,由于GCM需要google service支持,在國內(nèi)基本不能用,。那么,,Android系統(tǒng)上的應(yīng)用又是如何在沒有使用GCM服務(wù)的情況下把消息推送給我們的呢,?有如下三種方式: 1、使用第三方推送SDK 這是谷歌服務(wù)在國內(nèi)運(yùn)行情況不佳的產(chǎn)物,,國內(nèi)有多家第三方推送服務(wù)比如騰訊信鴿,,百度,極光,,個推,,小米等,需要APP接入SDK,,但是第三方推送服務(wù)可能會被系統(tǒng)殺掉,,所以不同手機(jī)系統(tǒng)中不同第三方推送的消息到達(dá)率/及時率參差不齊。 2,、接入廠商統(tǒng)一推送 為了優(yōu)化消息推送成功率,,降低電量和流量消耗,很多手機(jī)廠商也開始為開發(fā)者提供系統(tǒng)級推送服務(wù),,比如EMUI系統(tǒng)的華為推送,、MIUI系統(tǒng)的小米推送、Flyme系統(tǒng)的魅族推送等,,部分開發(fā)者為了提升消息及時性會選擇集成主流的幾家推送,,根據(jù)設(shè)備進(jìn)行區(qū)分,小米設(shè)備使用小米推送,、華為設(shè)備使用華為推送,、其他設(shè)備使用第三方推送。 3,、開發(fā)團(tuán)隊自研發(fā)推送功能 開發(fā)團(tuán)隊自研發(fā)推送功能需要投入開發(fā)成本,、服務(wù)器/帶寬成本,以及后期維護(hù)成本,,而且推送效率并不一定比第三方高,,大部分開發(fā)團(tuán)隊會選擇介入第三方推送。 當(dāng)前像微信這種超級應(yīng)用,,毋庸置疑肯定會選擇自研發(fā),。接下來,我們看下微信的消息推送機(jī)制,。 三,、微信消息推送機(jī)制 在Android下,不管是GCM還是微信,,都是通過TCP長連接來進(jìn)行推送消息的,,TCP長連接存活,,消息Push就及時,。 所以,,微信想要做到消息及時推送,不止微信客戶端要后臺?;?,TCP長連接也要保活,。 1,、如何保活TCP長連接 1)網(wǎng)絡(luò)狀態(tài)變化時及時重連 網(wǎng)絡(luò)狀態(tài)發(fā)生變化比如手機(jī)網(wǎng)絡(luò)和WIFI網(wǎng)絡(luò)切換,、網(wǎng)絡(luò)斷開和連上時,,TCP長連接變?yōu)闊o效連接,所以微信會監(jiān)聽網(wǎng)絡(luò)狀態(tài)變化事件,,及時重建長連接,。 2)及時發(fā)心跳包防止NAT超時 因?yàn)镮P v4的IP(即公網(wǎng)IP)有限,無法滿足人類使用(中國人用都不夠),,所以運(yùn)營商分配給手機(jī)終端的IP是運(yùn)營商內(nèi)網(wǎng)的IP,,手機(jī)要連接Internet,就需要通過運(yùn)營商的網(wǎng)關(guān)做一個網(wǎng)絡(luò)地址轉(zhuǎn)換(NAT),。簡單的說運(yùn)營商的網(wǎng)關(guān)需要維護(hù)一個外網(wǎng)IP,、端口到內(nèi)網(wǎng)IP、端口的對應(yīng)關(guān)系,,以確保內(nèi)網(wǎng)的手機(jī)可以跟Internet的服務(wù)器通訊,。 大部分網(wǎng)絡(luò)運(yùn)營商在鏈路一段時間(幾分鐘或者十幾分鐘)沒有數(shù)據(jù)通訊時,會淘汰NAT表中的對應(yīng)項(xiàng)(即NAT超時),,從而內(nèi),、外網(wǎng)IP之間再無法對應(yīng),造成TCP長連接無效,。說到這里,,可能大家都想到了防止NAT超時的方法:客戶端間隔一定時間發(fā)送一個心跳包給服務(wù)器,及時刷新NAT表,,并告知服務(wù)器客戶端當(dāng)前的狀態(tài),;所以心跳包的主要作用是防止NAT超時,其次是探測連接是否斷開,。 2,、微信智能心跳方案 為了保證微信收消息及時性的體驗(yàn),當(dāng)微信處于前臺活躍狀態(tài)時,,會使用固定心跳,;當(dāng)微信進(jìn)入后臺(或者前臺滅屏)時,微信會使用智能心跳,。 智能心跳實(shí)際上就是先用幾次最小心跳維持長鏈接,,然后動態(tài)的探測到最大的NAT超時時間,,再選定合適的心跳間隔區(qū)間去發(fā)送心跳包,同時在網(wǎng)絡(luò)狀況發(fā)生變化的時候能夠動態(tài)的調(diào)整心跳間隔時間,。 如果心跳間隔不合適,,例如心跳間隔過短,那么可能導(dǎo)致頻繁的喚醒手機(jī)發(fā)送心跳包,,增加耗電,;心跳間隔過長,可能導(dǎo)致這條TCP連接已經(jīng)無效但是無法及時的檢測到,,只能等待下一個心跳包發(fā)送的時候才能感知到,,所以會導(dǎo)致消息接收延遲。 所以探測到一個合適的心跳間隔是非常重要的,,把耗電和消息接收及時性綜合折中來取得一個最佳的體驗(yàn),,這個也是微信使用智能心跳的原因。 四,、微信延遲問題原因揭秘 上文有提到,,微信想要做到消息及時推送,不止微信客戶端要后臺?;?,TCP長連接也要保活(及時發(fā)送心跳),,當(dāng)然保持網(wǎng)絡(luò)始終連接是前提條件,。 原因1:鎖屏斷網(wǎng) 各大廠商均為用戶提供了'休眠狀態(tài)下是否保持網(wǎng)絡(luò)連接'的開關(guān),如果對微信消息及時性要求高的同學(xué),,可以選擇'始終',。 以華為EMUI5.X系統(tǒng)為例,設(shè)置路徑為: 1)進(jìn)入手機(jī)設(shè)置>WLAN>配置>在休眠狀態(tài)下保持WLAN連接,,選擇始終,; 2)進(jìn)入手機(jī)設(shè)置>更多>移動網(wǎng)絡(luò)>始終連接數(shù)據(jù)業(yè)務(wù),打開開關(guān),; 不過我發(fā)現(xiàn),,現(xiàn)在華為最新EMUI8.X系統(tǒng)上,即使不選擇“始終”,,微信也可以及時收到消息,,應(yīng)該是華為意識到微信消息的重要性,對微信加了白名單,。 原因2:運(yùn)營商N(yùn)AT超時時間較短 根據(jù)微信官方文檔介紹,,最小心跳為4.5min,但是國內(nèi)有些地區(qū)有些運(yùn)營商設(shè)置的NAT超時時間比較短(小于4.5min),。在這種網(wǎng)絡(luò)下,,如果是滅屏狀態(tài),,微信的TCP長連接基本上每隔幾分鐘就會斷開,直到重連后才可以收到消息,,加上目前各大廠商的省電策略,本身應(yīng)用在后臺就非常不活躍,,可能無法及時重連,,這個就導(dǎo)致微信延遲概率更高、延遲時間更久,。 這種網(wǎng)絡(luò)很容易識別,,如果你在4G網(wǎng)絡(luò)下/其他運(yùn)營商WiFi下不會延遲,只在特定網(wǎng)絡(luò)下比如家里的WiFi下高概率延遲,,并且多個系列的安卓機(jī)都會延遲,,那么很可能是因?yàn)槟闶褂镁W(wǎng)絡(luò)的NAT超時時間比較短。 針對這類網(wǎng)絡(luò),,曾經(jīng)在貼吧見過網(wǎng)友給過一個解決辦法:打電話給運(yùn)營商客服,,要求把寬帶賬號加到外網(wǎng)。不過很多網(wǎng)友質(zhì)疑可行性,,然后樓主說是找在電信的朋友給加的,。這個操作雖然理論上可以解決延遲問題,但是的確沒有可行性...... 所以,,遇到這種網(wǎng)絡(luò),,如果不想換網(wǎng)絡(luò),但是又希望微信消息及時接收的話,,只能祈禱微信縮短最小心跳間隔,,并且手機(jī)廠商不進(jìn)行管控(所以我說了一堆廢話......)。 原因3:后臺清理微信 待機(jī)時長是用戶挑選機(jī)型時首要考慮的一個因素,,手機(jī)發(fā)熱耗電快也是用戶吐槽非常多的一個問題,。所以電池大小、充電速度,、系統(tǒng)省電策略也是谷歌包括各大廠商在不斷改進(jìn)(有可能越改越瞎)的事情,。 當(dāng)應(yīng)用進(jìn)入后臺或者系統(tǒng)滅屏?xí)r,能殺的全都?xì)⒌簦翰辉谟脩舯Wo(hù)名單里,,殺,!高耗電應(yīng)用,殺,!不聽話應(yīng)用,,殺! 如果對微信消息及時性要求高的同學(xué),,最好把微信加入清理白名單,。 以華為EMUI5.X系統(tǒng)為例,,設(shè)置路徑為:手機(jī)管家>剩余xx%>鎖屏清理應(yīng)用,將微信設(shè)置成鎖屏后不清理,; 不過微信現(xiàn)在作為超級應(yīng)用,,基本沒有廠商敢在后臺殺微信的了,而且基本都會將微信加入受保護(hù)白名單,,想一鍵清理也清理不掉,,只有停止運(yùn)行微信才可以,估計也有部分用戶會覺得很鬧心,。 原因4:谷歌省電策略 1)Android 5.0:JobSchedule(對齊喚醒機(jī)制) 在待機(jī)狀態(tài)下,,如果系統(tǒng)和App沒有發(fā)出動作,安卓其實(shí)是很省電的,。不過,,安卓App頻頻喚醒后臺,令安卓耗電大增,。App每次喚醒設(shè)備1到2秒,,待機(jī)時間就會減少2分鐘。這并不僅僅指的是點(diǎn)亮屏幕,,還有系統(tǒng)在處理應(yīng)用的后臺任務(wù),。 谷歌在Android 5.0上提出API JobScheduler,系統(tǒng)可以批處理一些應(yīng)用喚醒要求,,減少電量消耗,,也叫做對齊喚醒機(jī)制。 當(dāng)然,,谷歌的這個對齊喚醒機(jī)制需要應(yīng)用主動調(diào)用,,并且是針對不需要準(zhǔn)時執(zhí)行并且希望批量處理的任務(wù),所以并不會影響微信消息的及時推送,。 2)Android 6.0:Doze模式,、App Stanbdy 谷歌在Android 6.0上提出了兩個省電特性(Doze模式、App Stanbdy)以延長電池使用時間,。 如果一個用戶斷開充電連接,,滅屏不動手機(jī)一段時間之后,系統(tǒng)會嘗試延緩app后臺的CPU和網(wǎng)絡(luò)活動(延緩應(yīng)用的任務(wù),、同步和標(biāo)準(zhǔn)alarms,,阻止應(yīng)用訪問網(wǎng)絡(luò))減少電量的消耗。 當(dāng)然應(yīng)用可以通過適配來保證基本功能正常運(yùn)行,,用戶也可以選擇將應(yīng)用加入白名單,。 以華為EMUI8.X系統(tǒng)為例,設(shè)置路徑為:設(shè)置>應(yīng)用和通知>應(yīng)用管理>設(shè)置>特殊訪問權(quán)限>忽略電池優(yōu)化>微信,設(shè)置為允許,。 原因5:廠商省電策略 各大廠商的省電策略相比谷歌省電策略,,更加復(fù)雜粗暴,并且應(yīng)用根本無法適配,。目前了解到的廠商省電策略主要有如下幾種: 1)后臺斷網(wǎng)/后臺清理 上文提到,,估計除了超級應(yīng)用可以幸免于此了。并且有些APP即使加入白名單,,依舊會被清理,。 2)對齊喚醒機(jī)制 上文提到,谷歌在Android 5.0上提出的對齊喚醒機(jī)制并不會影響微信消息的及時推送,;但是廠商的對齊喚醒機(jī)制比較粗暴,會將所有應(yīng)用在一定時間段內(nèi)的多次喚醒合并成一次喚醒,,減少系統(tǒng)被喚醒次數(shù),,增加待機(jī)時間。 而微信心跳就依靠這個定時器,,在喚醒的時候發(fā)送心跳給服務(wù)器,,如果被廠商對齊喚醒,心跳間隔就會比原本設(shè)定的長(比如從4.5min變成10min),,那么使用網(wǎng)絡(luò)NAT超時時間<10min的這部分用戶就會出現(xiàn)NAT超時,,微信消息出現(xiàn)延遲。 而不同廠商的針對不同應(yīng)用,、在不同時間段的對齊時間可能還不一樣,。 情況1:如果你白天不會延遲,只有晚上/半夜會延遲,,那么很可能是廠商在夜間做了省電策略,,夜間對齊喚醒時間間隔比較久。 情況2”如果你在4G網(wǎng)絡(luò)下/其他運(yùn)營商WiFi下不會延遲,,只在特定網(wǎng)絡(luò)下比如家里的WiFi下高概率延遲,,并且其他系列手機(jī)均不會延遲,那么很可能是因?yàn)槟闶褂玫倪@款機(jī)型的對齊喚醒時間間隔比較久(當(dāng)然前提是手機(jī)上所有開關(guān)都設(shè)置好),。 手機(jī)廠商的這種做法,,雖然為用戶節(jié)省了功耗,但是卻沒有給用戶足夠的選擇權(quán),,因?yàn)橛行┯脩粝啾裙?jié)省功耗優(yōu)先會選擇消息及時性,。 值得鼓勵的是華為EMUI8.X系統(tǒng)在近期更新的版本上給了用戶選擇權(quán),當(dāng)用戶選擇允許后臺活動后,,不再對微信做對齊喚醒等管控,。設(shè)置路徑為: 在設(shè)置>電池>啟動管理,找到微信,關(guān)閉'自動管理',,打開'手動管理'的三個開關(guān)'允許自啟動''允許關(guān)聯(lián)啟動''允許后臺活動',。 不過當(dāng)前已經(jīng)支持的版本并不多,只看到了P20系列 B108版本,、Mate10系列 B129sp03版本,。不過各位使用華為手機(jī)的朋友還是可以期待下,畢竟旗艦產(chǎn)品已經(jīng)帶了,,其他產(chǎn)品肯定也會陸續(xù)帶上~ 五,、微信消息延遲問題-華為手機(jī)相關(guān)開關(guān)匯總 由于本人使用華為機(jī)比較多,針對華為手機(jī)統(tǒng)一整理了相關(guān)開關(guān),,其他廠商機(jī)型可以自行百度,。 場景1:如果打開微信沒有地球界面,說明微信在后臺沒有被殺,,你需要進(jìn)行如下設(shè)置: 如果是EMUI8.X產(chǎn)品: 1.允許微信后臺活動可以通過設(shè)置允許微信后臺活動,,提升微信接收消息及時性,操作步驟: 在設(shè)置>電池>啟動管理,,找到微信,,關(guān)閉“自動管理”,打開'手動管理'的三個開關(guān)“允許自啟動”“允許關(guān)聯(lián)啟動”“允許后臺活動”,。 注:當(dāng)前已支持產(chǎn)品與版本有P20系列 B108版本,、Mate10系列 B129sp03版本;其他EMUI8.X產(chǎn)品后續(xù)應(yīng)該會陸續(xù)推送版本 2.將網(wǎng)絡(luò)設(shè)置為始終連接 1)進(jìn)入手機(jī)設(shè)置>無線和網(wǎng)絡(luò)>WLAN>配置>在休眠狀態(tài)下保持WLAN連接,,選擇始終,; 2)進(jìn)入手機(jī)設(shè)置>無線和網(wǎng)絡(luò)>移動網(wǎng)絡(luò)>高級>始終連接數(shù)據(jù)業(yè)務(wù),打開開關(guān),; 3)進(jìn)入手機(jī)設(shè)置>無線和網(wǎng)絡(luò)>移動網(wǎng)絡(luò)>高級>WLAN/移動數(shù)據(jù)連接切換提示,選擇自動使用移動數(shù)據(jù)連接,。 3.將微信設(shè)為忽略電池優(yōu)化 設(shè)置>應(yīng)用和通知>應(yīng)用管理>設(shè)置>特殊訪問權(quán)限>忽略電池優(yōu)化>微信,設(shè)置為允許,。 4.關(guān)閉省電模式 點(diǎn)擊手機(jī)管家>剩余xx%,,關(guān)閉省電模式和超級省電的開關(guān)。 5.關(guān)閉省流量模式 手機(jī)管家>流量管理>省流量模式,,關(guān)閉省流量模式,;如果需要使用省流量模式,請打開微信應(yīng)用的開關(guān),,關(guān)閉后將無法在后臺接收新消息,。 6.開啟系統(tǒng)的通知功能 在設(shè)置>應(yīng)用和通知>通知管理中找到微信,根據(jù)需要設(shè)置允許通知,,以及通知方式(在狀態(tài)欄,、橫幅,、鎖屏顯示通知)。 7.開啟微信應(yīng)用內(nèi)部的通知功能 在微信我>設(shè)置>新消息提醒,,打開“接收新消息通知”開關(guān),,并根據(jù)需要打開或關(guān)閉“通知顯示消息詳情”、“聲音”,、“震動”,。 如果是EMUI5.X產(chǎn)品: 1.將網(wǎng)絡(luò)設(shè)置為始終連接 1)進(jìn)入手機(jī)設(shè)置>WLAN>配置>在休眠狀態(tài)下保持WLAN連接,選擇始終,; 2)進(jìn)入手機(jī)設(shè)置>更多>移動網(wǎng)絡(luò)>始終連接數(shù)據(jù)業(yè)務(wù),,打開開關(guān); 3)進(jìn)入手機(jī)設(shè)置>更多>移動網(wǎng)絡(luò)>WLAN/移動數(shù)據(jù)連接切換提示,選擇自動使用移動數(shù)據(jù)連接,; 2.將微信設(shè)為忽略電池優(yōu)化 設(shè)置>應(yīng)用管理>設(shè)置>特殊訪問權(quán)限>忽略電池優(yōu)化>微信,,設(shè)置為允許; 3.關(guān)閉省電模式 點(diǎn)擊手機(jī)管家>剩余xx%,,關(guān)閉省電模式和超級省電的開關(guān),。 4.關(guān)閉省流量模式 手機(jī)管家>流量管理>省流量模式,關(guān)閉省流量模式,;如果需要使用省流量模式,,請打開微信應(yīng)用的開關(guān),,關(guān)閉后將無法在后臺接收新消息,。 5.開啟系統(tǒng)的通知功能 在設(shè)置>通知欄和狀態(tài)欄>通知管理中找到微信,根據(jù)需要設(shè)置允許通知,,以及通知方式(在狀態(tài)欄,、橫幅、鎖屏顯示通知),; 6. 開啟微信應(yīng)用內(nèi)部的通知功能 在微信我>設(shè)置>新消息提醒,,打開“接收新消息通知”開關(guān),并根據(jù)需要打開或關(guān)閉“通知顯示消息詳情”,、“聲音”,、“震動”。 : 場景2:如果打開微信有地球界面,,說明微信在后臺被殺,,所以你無法及時收到消息,你需要進(jìn)行如下設(shè)置: 如果是EMUI8.X產(chǎn)品: 1.將微信設(shè)置為自動管理的應(yīng)用:手機(jī)管家>剩余xx%>啟動管理,,將微信設(shè)置成自動管理,。 2.系統(tǒng)提示微信高耗電提醒時,不要將應(yīng)用直接關(guān)閉,; 3.在使用手機(jī)管家>剩余xx%中一鍵省電時,,如果清理了微信,需要手動再次開啟微信。 4.超級省電模式下,,微信會被關(guān)閉,,如果手機(jī)電量充足,不需要使用超級省電時,,最好關(guān)閉超級省電(手機(jī)管家>剩余xx%) 如果是EMUI5.X產(chǎn)品: 1.將微信設(shè)置為后臺活躍應(yīng)用和允許自啟動應(yīng)用 后臺活躍設(shè)置:手機(jī)管家>剩余xx%>鎖屏清理應(yīng)用,,將微信設(shè)置成鎖屏后不清理; 自啟動應(yīng)用設(shè)置:手機(jī)管家>自啟管理,,將微信勾選成允許開機(jī)自動啟動,; 2.系統(tǒng)提示微信高耗電提醒時,不要將應(yīng)用直接關(guān)閉,; 3.在使用手機(jī)管家>剩余xx%中一鍵省電時,,如果清理了微信,需要手動再次開啟微信,。 4.超級省電模式下,,微信會被關(guān)閉,如果手機(jī)電量充足,,不需要使用超級省電時,,最好關(guān)閉超級省電(手機(jī)管家>剩余xx%) 六、結(jié)束語 想要徹底解決微信消息延遲問題,,除了配置上面的相關(guān)開關(guān)外,,還需要微信、運(yùn)營商網(wǎng)絡(luò),、廠商省電策略這三個模塊統(tǒng)一進(jìn)行優(yōu)化,。這么一看,還是2017年10月份工信部牽頭成立的'安卓統(tǒng)一推送聯(lián)盟'比較靠譜點(diǎn),。 按照工信部泰爾終端實(shí)驗(yàn)室的說法,,未來將由終端廠商提供系統(tǒng)級推送服務(wù),不再允許各 app 在后臺保留常連接,。與此同時,,各終端廠商實(shí)現(xiàn)推送通道接口和功能統(tǒng)一,方便開發(fā)者接入,。在新標(biāo)準(zhǔn)下,,消息將通過統(tǒng)一的服務(wù)器推送至用戶設(shè)備,而不必喚醒應(yīng)用,,與 iOS 的機(jī)制類似,。 雖道阻且長,但相信國內(nèi)安卓環(huán)境會越來越好,! |
|