目錄
一、簡介
二、APNs推送流程
三、什么是deviceToken
四、消息體
五、APNs推送中的問題
APNs 簡介
Apple Push Notification service (APNs),即蘋果推送通知服務(wù)。
為什么會(huì)有 APNs ?
由于移動(dòng)設(shè)備內(nèi)存、CPU、電量的局限性,iOS 不允許 APP 的進(jìn)程常駐后臺(tái)(事實(shí)上可以申請(qǐng)后臺(tái)運(yùn)行一段時(shí)間,最長約10分鐘)。
當(dāng)用戶主動(dòng)殺掉APP或者APP進(jìn)入后臺(tái)超過限定時(shí)長時(shí),就意味著該APP進(jìn)程的結(jié)束。這很大程度保障了前臺(tái)APP的流暢性,也延長了手機(jī)的使用時(shí)長。這也是蘋果用戶體驗(yàn)好的原因之一。但是這也意味著,服務(wù)器無法主動(dòng)和用戶交互(如推送實(shí)時(shí)消息等)。為了解決這個(gè)限制,蘋果推出了APNs,允許設(shè)備和服務(wù)器分別與蘋果的推送通知服務(wù)器保持長連接狀態(tài)。
iOS的通知
iOS分本地通知和遠(yuǎn)程通知,(APNs)是遠(yuǎn)程通知功能的核心.
- 本地通知是由本地應(yīng)用觸發(fā)的。一般是基于時(shí)間的一種通知形式,如鬧鐘、待辦事件等的提醒。
- 遠(yuǎn)程通知是通過我們自己的服務(wù)器推送消息的一種通知形式。
APNs推送流程
假如我們的蘋果設(shè)備(AC電腦、筆記本、iPad、iPhone等)安裝了一個(gè)名叫XXX的應(yīng)用。那么我們具體是怎樣接收到推送通知的那??接下來我們就說說具體這個(gè)過程。下面是蘋果APNs官方簡介 中提供的APNs推送流程的圖

Provier 代表我們自己的應(yīng)用服務(wù)器
APNs 代表蘋果的APNs推送服務(wù)器
接著是代表的就是蘋果的設(shè)備
Client App 代表我們開發(fā)的應(yīng)用
說明:
- 安裝了XXX應(yīng)用的蘋果設(shè)備需要向APNs服務(wù)器注冊(cè),注冊(cè)成功后APNs服務(wù)器會(huì)返回一個(gè)deviceToken,并且二者之間會(huì)維持一個(gè)長連接(這個(gè)長連接是基于SSL協(xié)議的TCP流通訊)
- 拿到這個(gè)deviceToken后我們將這個(gè)deviceToken發(fā)給我們自己的服務(wù)器
- 當(dāng)有消息需要被推送時(shí),我們自己的服務(wù)器會(huì)將消息按指定的格式結(jié)合設(shè)備的deviceToken一并打包 然后發(fā)給APNs服務(wù)器
- APNs將新消息推送給我們的設(shè)備上,然后就在設(shè)備的屏幕上顯示出來了 (因?yàn)槲覀兊脑O(shè)備和APNs服務(wù)器二者之間維持了一個(gè)長連接)
注意說明:
真正完成推送的是APNS服務(wù)器。消息一定是由APNs服務(wù)器推送給我們的設(shè)備的,我們自己的應(yīng)用服務(wù)器只是將需要推送的消息告訴APNs服務(wù)器。至于如何維護(hù)消息隊(duì)列或如何保證消息能被推送到指定的設(shè)備上,這些都由蘋果APNs做好的。
什么是deviceToken ?
deviceToken是一個(gè)APP裝在一個(gè)設(shè)備上的唯一標(biāo)識(shí)符。一個(gè)APP在不同的設(shè)備上deviceToken不一樣;一個(gè)APP刪除之后再次安裝deviceToken也不一樣。
在項(xiàng)目代碼AppDelegate里面有一個(gè)回調(diào)方法,當(dāng)APNs注冊(cè)成功通過該回調(diào)方法可以獲取到返回的deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
上面說過當(dāng)有消息需要被推送時(shí),我們自己的服務(wù)器會(huì)將消息按指定的格式結(jié)合設(shè)備的deviceToken一并打包 ,APNs拿到這個(gè)包之后驗(yàn)證這個(gè)包結(jié)構(gòu)是否正確并提取其中的信息后,再將消息推送到指定的設(shè)備。
接下來就來看看這個(gè)包的結(jié)構(gòu):

這個(gè)包分五個(gè)部分
- 第一個(gè)部分是命令標(biāo)示符
- 第二個(gè)部分是我們的deviceToken的長度
- 第三個(gè)部分是我們的deviceToken字符串
- 第四個(gè)部分是推送的消息體(Payload)的長度
- 最后一個(gè)部分也就是真正的消息內(nèi)容了,里面包含了推送消息的基本信息。(比如消息內(nèi)容,應(yīng)用icon右上角顯示的數(shù)字角標(biāo)以及推送消息到達(dá)時(shí)所播放的聲音等)
接下來詳細(xì)看一下Payload(消息體)的結(jié)構(gòu)

Payload(消息體)其實(shí)就是個(gè)JSON結(jié)構(gòu)體。上面的圖只是簡單的一種消息體更多詳細(xì)類型的消息體類型,請(qǐng)看消息體蘋果官方相關(guān)介紹
- alert里的就是會(huì)顯示在用戶手機(jī)上的推送標(biāo)題內(nèi)容
- badge顯示的數(shù)量(注意是整型)是會(huì)在應(yīng)用icon右上角顯示的數(shù)量,提示有多少條未讀消息等
- sound就是當(dāng)推送信息送達(dá)是手機(jī)播放的聲音,傳defalut就標(biāo)明使用系統(tǒng)默認(rèn)聲音,如果傳比如“xxx.wav”就會(huì)播放在我們應(yīng)用工程目錄下名稱為xxx.wav的音頻文件,比如當(dāng)手機(jī)鎖屏?xí)rQQ在后臺(tái)收到新消息時(shí)的滴滴聲。
安全架構(gòu)
為了保證安全性,APNs用連接信任(connection trust)和token信任(token trust)來控制通信入口,你要用APNs則必須用通過這兩種驗(yàn)證。
連接信任
連接信任第一個(gè)作用是保證APNs連接的provider是蘋果已經(jīng)同意可通信的,然后第二個(gè)是保證與APNs連接的設(shè)備的合法性,第二步是APNs處理的,你所要處理的是provider與APNs之間的連接安全性。
服務(wù)器與APNs之間的連接信任
每個(gè)服務(wù)器都必須要有唯一的provider證書和私鑰,都是用來驗(yàn)證連接的。provider證書就是在開發(fā)者官網(wǎng)申請(qǐng)的。
服務(wù)器通過TLS驗(yàn)證和APNs連接,HTTPS中用的也是TLS協(xié)議,即四步握手,首先初始化TLS連接,即provider(服務(wù)器)發(fā)送請(qǐng)求給APNs,APNs服務(wù)器返回APNs證書(即公鑰)給provider,然后服務(wù)端收到后生成provider證書后再返回給APNs,APNs收到后驗(yàn)證后即可以建立TLS連接,不過APNs用的不是HTTPS,而是HTTP/2,具體過程如下圖
APNs推送中的問題
問題一: 當(dāng)應(yīng)用從設(shè)備卸載后,推送的消息改如何處理??
我們知道當(dāng)應(yīng)用從設(shè)備卸載后,是收不到推送消息的。但是,如何讓APNs和Provider知道不再向這臺(tái)卸載了應(yīng)用的設(shè)備推送消息呢?
針對(duì)這個(gè)問題蘋果也已經(jīng)幫我們解決了(那就是Feedback Service)。它是APNS的一部分,APNs會(huì)持續(xù)的更新Feedback service的列表,當(dāng)我們的Provider將信息發(fā)給APNs服務(wù)器,APNs推送信息到我們的設(shè)備時(shí),如果這時(shí)設(shè)備無法將消息推送到指定的應(yīng)用(應(yīng)用已經(jīng)刪除),就會(huì)向APNs服務(wù)器發(fā)送一個(gè)反饋信息,而這個(gè)信息就記錄在Feedback service中。按照這種方式,Provider應(yīng)該定時(shí)的去檢測Feedback service的列表,然后刪除在自己數(shù)據(jù)庫中記錄的存在于反饋列表中的deviceToken,從而不再向這些設(shè)備發(fā)送推送信息。連接Feedback service的過程同樣使用長連接的方式,連接上后,直接接收由APNs傳輸給我們的反饋列表,傳輸完成后斷開連接,然后我們根據(jù)這個(gè)最新的反饋列表在更新我們自己的數(shù)據(jù)庫,刪除那些不再需要推送信息的設(shè)備的deviceToken。
從Feedback service讀取的數(shù)據(jù)結(jié)構(gòu)如下:

結(jié)構(gòu)中包含三個(gè)部分
- 第一部分是一個(gè)時(shí)間戳,記錄的是設(shè)備失效后的時(shí)間信息
- 第二個(gè)部分是deviceToken的長度
- 第三部分就是失效的deviceToken,我們所要獲取的就是第三部分,跟我們的數(shù)據(jù)庫進(jìn)行對(duì)比后,刪除對(duì)應(yīng)的deviceToken,下次不再向這些設(shè)備發(fā)送推送信息
問題二:iOS 重復(fù)推送之謎 文章地址
問題三:收不到 APNs 推送怎么辦?
- 首先要知道服務(wù)器推送成功,并不代表設(shè)備就能收到推送。服務(wù)器推送成功只是將消息交給了蘋果服務(wù)器而已,蘋果服務(wù)器還需要設(shè)備在線才能推送的。
- 其次 deviceToken 可能會(huì)在 APP 卸載重裝后發(fā)生變化,客戶端對(duì)此需要制定相應(yīng)的匯報(bào)策略,以便服務(wù)器及時(shí)更新存儲(chǔ)的 deviceToken 。
客戶端只要能上報(bào)正確的 deviceToken 就可以說明客戶端實(shí)現(xiàn)沒問題了。否則檢查客戶端是否開啟了遠(yuǎn)程推送通知服務(wù),Bundle Identifier 是否與申請(qǐng)的推送證書匹配。 - 檢查服務(wù)器內(nèi)存緩存的 deviceToken 或者數(shù)據(jù)庫存儲(chǔ)的 deviceToken 是否與客戶端匯報(bào)的一致。
排查服務(wù)器配置的證書是否過期,是否與客戶端的 Bundle Identifier 匹配,或者是否勿用了其他類型的推送證書。
采用抓包工具(如 Wireshark )抓包分析,看看服務(wù)器是否將消息交給蘋果服務(wù)器,客戶端是否收到了相應(yīng)的推送通知。
參考文檔:
國內(nèi) 90%以上的 iOS 開發(fā)者,對(duì) APNs 的認(rèn)識(shí)都是錯(cuò)的
iOS 必知必會(huì) - APNs篇
蘋果推送機(jī)制APNs(一)