準(zhǔn)備篇
Tip 1:推送通知(Push Notification)必須購買Apple開發(fā)者賬號(hào)没炒,并使用特定的推送證書
- 使用免費(fèi)賬號(hào)不能推送晓勇。
- 如果使用第三方推送服務(wù),比如【極光推送】,也必須購買開發(fā)者賬號(hào)役首。因?yàn)樗械牡谌蕉紩?huì)將推送請(qǐng)求發(fā)送至APNs(Apple Push Notification service 蘋果推送通知服務(wù)),所有推送均是由APNs下發(fā)显拜。
- 如何注冊(cè)及正確的配置證書衡奥,參考這里iOS-推送證書設(shè)置指南;
原理篇
Tip 2:推送通知本身是iOS系統(tǒng)的行為
所以在App沒有運(yùn)行(沒有在前臺(tái)也沒有在后臺(tái))的時(shí)候:
- 仍然可以推送及接收(通知中心通知、頂部橫幅远荠、刷新App右上角的小圓點(diǎn)【即
badge
矮固,以下簡(jiǎn)稱角標(biāo)】等都會(huì)有系統(tǒng)來控制和展示)。 - 收到推送時(shí)譬淳,是無法在App的代碼中獲取到通知內(nèi)容的档址。因?yàn)樯澈袡C(jī)制,此時(shí)App的任何代碼都不可能被執(zhí)行邻梆。
Tip 3:手機(jī)向APNs注冊(cè)推送服務(wù)
- 在代碼中注冊(cè)推送服務(wù):
#ifdef __IPHONE_8_0
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
#else
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes];
#endif
在第一次觸發(fā)這段代碼的時(shí)候守伸,會(huì)有一個(gè)系統(tǒng)彈窗,詢問你是否允許該App要給你推送信息浦妄。當(dāng)你選擇允許的時(shí)候尼摹,系統(tǒng)會(huì)打包“App + 手機(jī)唯一標(biāo)識(shí) + 證書”信息發(fā)送至“APNs服務(wù)器”见芹,注冊(cè)推送服務(wù),APNs系統(tǒng)會(huì)對(duì)該手機(jī)安裝的該App是否有推送權(quán)限進(jìn)行驗(yàn)證蠢涝。所以必須是加入了Apple Device 的手機(jī)玄呛,使用對(duì)應(yīng)App的推送證書才能夠成功注冊(cè)。
如果注冊(cè)成功惠赫,則可以在
AppDelegate.m
的如下方法中獲取到deviceToken
把鉴,它是對(duì)“該手機(jī) + 該App ”組合的一個(gè)唯一標(biāo)識(shí)。當(dāng)使用遠(yuǎn)程推送時(shí)儿咱,只需要將推送消息發(fā)給指定的deviceToken
就可以使推送信息傳達(dá)給指定手機(jī)的指定App上庭砍。因此如果你使用第三方,就需要在這個(gè)方法里將deviceToken
傳給第三方混埠。(iOS 9 為了更好的保護(hù)用戶隱私怠缸,會(huì)出現(xiàn)多次重復(fù)/安裝App導(dǎo)致deviceToken
不斷變化的情況。有時(shí)會(huì)出現(xiàn)一條推送手機(jī)會(huì)收到2次的問題钳宪,屬于iOS 9 的系統(tǒng)問題)揭北。
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[JPUSHService registerDeviceToken:deviceToken];//將 deviceToken 傳給極光推送
}
- 如果以上步驟均成功,此時(shí)你能夠取到第三方提供的設(shè)備注冊(cè) id吏颖。能否取到該 id 值搔体,可以作為判斷設(shè)備是否能夠成功推送的標(biāo)準(zhǔn)(點(diǎn)Tip 6 - Registration ID)。因?yàn)楫?dāng)你取到該值時(shí)半醉,必然:
- 推送證書配置正確(你擁有了推送權(quán)限)疚俱。
- 設(shè)備成功在APNs注冊(cè)并返回了
deviceToken
(APNs能識(shí)別你的設(shè)備了)。 - 返回的
deviceToken
傳給第三方缩多,成功在第三方生成了唯一標(biāo)識(shí)注冊(cè) id(第三方能將你的設(shè)備信息傳給APNs了)呆奕。
- 綜上,注冊(cè)及接收推送必須使用真機(jī)衬吆,必須連網(wǎng)梁钾。
Tip 4:推送通知從服務(wù)端 --> App代碼的過程
- 使用你們公司或第三方的服務(wù)端向APNs發(fā)送推送請(qǐng)求(請(qǐng)參考蘋果 APNs 的相關(guān)資料,或者第三方推送提供了更簡(jiǎn)單的
REST API
)逊抡。 - APNs 接收并驗(yàn)證推送請(qǐng)求姆泻。
- APNs 找到設(shè)備下發(fā)推送。
- 手機(jī)收到推送通知冒嫡,系統(tǒng)根據(jù)App狀態(tài)進(jìn)行處理:
- 前臺(tái)收到:
- 系統(tǒng)會(huì)將通知內(nèi)容傳到
didReceiveRemoteNotification
麦射;
- 系統(tǒng)會(huì)將通知內(nèi)容傳到
- 后臺(tái)收到:
- 如果開啟了
Remote Notification
,系統(tǒng)將推送傳到didReceiveRemoteNotification:fetchCompletionHandler:
灯谣,(見Tip 5 - 后臺(tái)推送)潜秋,否則此時(shí)代碼中收不到推送。 - 展示橫幅胎许、通知中心峻呛、聲音罗售、角標(biāo)。
- 如果開啟了
- 退出收到:
- 如果點(diǎn)擊 推送橫幅/通知中心钩述,而啟動(dòng)App寨躁,系統(tǒng)將通知傳到
didFinishLaunchingWithOptions
。 - 展示橫幅牙勘、通知中心职恳、聲音、角標(biāo)方面。
- 如果點(diǎn)擊 推送橫幅/通知中心钩述,而啟動(dòng)App寨躁,系統(tǒng)將通知傳到
- 前臺(tái)收到:
推送通知內(nèi)容篇
Tip 5:推送通知分為 本地/遠(yuǎn)程 2 種類型:
- 本地通知:可指定推送時(shí)間放钦,在該時(shí)間準(zhǔn)時(shí)彈出推送通知。
- 遠(yuǎn)程推送通知:分為 普通推送/后臺(tái)推送/靜默推送 3種類型恭金。存在延遲問題(由于Tip 1 第 2 點(diǎn)操禀,APNs的不穩(wěn)定及高峰時(shí)段的巨量請(qǐng)求所致)。
- 普通推送:
- 就是我們?cè)谑謾C(jī)上平時(shí)見到的推送通知横腿。包含聲音颓屑、橫幅、角標(biāo)耿焊、自定義字段揪惦。
- App:
- 處于前臺(tái),不會(huì)展示橫幅罗侯,可通過
didReceiveRemoteNotification
(iOS 7 before)didReceiveRemoteNotification:fetchCompletionHandler:
(iOS 7 after)獲取通知內(nèi)容(前臺(tái)展示橫幅的方法看這里)丹擎。 - 處于后臺(tái),會(huì)展示橫幅歇父,無法獲取通知內(nèi)容。
- 處于退出再愈,會(huì)展示橫幅榜苫,無法獲取通知內(nèi)容。
- 點(diǎn)擊圖標(biāo)啟動(dòng)翎冲,無法獲取通知內(nèi)容垂睬。
- 點(diǎn)擊通知橫幅啟動(dòng),在
didFinishLaunchingWithOptions
獲取通知內(nèi)容抗悍。
- 處于前臺(tái),不會(huì)展示橫幅罗侯,可通過
- 通知內(nèi)容類似如下:
- 普通推送:
{
"_j_msgid" = 200806057; // 第三方附帶的 id驹饺,用于統(tǒng)計(jì)點(diǎn)擊
aps = {
alert = "顯示內(nèi)容";
badge = 1; // App 角標(biāo),可推送 n缴渊、+n赏壹、-n 來實(shí)現(xiàn)角標(biāo)的固定、增加衔沼、減少
sound = default; // 推送聲音蝌借,默認(rèn)系統(tǒng)三全音昔瞧,如需使用自己的聲音,需要將聲音文件拖拽&拷貝至 Xcode 工程目錄任意位置菩佑,并在推送時(shí)指定其文件名
};
key1 = value1; // 自定義字段自晰,可設(shè)置多組,用于處理內(nèi)部邏輯
key2 = value2;
}
- 后臺(tái)推送
- 各種顯示效果跟普通推送完全一樣稍坯。
- 必須攜帶
"content-available" = 1;
酬荞。 - 必須攜帶
alert
、badge
瞧哟、sound
中至少 1 個(gè)字段
混巧。 - 僅 iOS 7 以后支持。
- 必須在 Xcode 工程中:TARGETS -> Capabilities -> Background Modes -> Remote notifications 開啟該功能绢涡,具體參照iOS 7 Background Remote Notification牲剃。
- App:
- 處于前臺(tái),可通過
didReceiveRemoteNotification
(iOS 7 before)didReceiveRemoteNotification:fetchCompletionHandler:
(iOS 7 after) 獲取通知內(nèi)容雄可。 - 處于后臺(tái)凿傅,可通過
didReceiveRemoteNotification:fetchCompletion Handler:
獲取通知內(nèi)容 // 獲取情況中與普通推送的唯一不同點(diǎn),此時(shí) iOS 系統(tǒng)允許開發(fā)者在 App 處于后臺(tái)的情況下数苫,執(zhí)行一些代碼聪舒,大概提供幾分鐘的時(shí)間,可以用來偷偷的刷新 UI虐急、切換頁面箱残、下載更新包等等操作。 - 處于退出止吁,無法獲取通知內(nèi)容被辑。
- 點(diǎn)擊圖標(biāo)啟動(dòng),無法獲取通知內(nèi)容敬惦。
- 點(diǎn)擊推送橫幅啟動(dòng)盼理,在
didFinishLaunchingWithOptions
獲取通知內(nèi)容。
- 處于前臺(tái),可通過
- 通知內(nèi)容類似如下:
json
{
"_j_msgid" = 2090737306;
aps = {
alert = "顯示內(nèi)容";
badge = 1;
"content-available" = 1; // 必帶字段
sound = default;
};
key1 = value1;
}
- 靜默推送
- 沒有任何展示效果俄删。
- 必須攜帶
"content-available" = 1;
宏怔,因此靜默必然是后臺(tái)的。 - 必須不攜帶
alert
畴椰、badge
臊诊、sound
。 - 可攜帶自定義字段斜脂。
- App :
- 處于前臺(tái)抓艳,可通過
didReceiveRemoteNotification
(iOS 7 before)didReceiveRemoteNotification:fetchCompletionHandler:
(iOS 7 after) 獲取通知內(nèi)容。 - 處于后臺(tái)帚戳,可通過
didReceiveRemoteNotification:fetchCompletion Handler:
獲取通知內(nèi)容 //獲取情況中與普通推送的唯一不同點(diǎn)壶硅,此時(shí) iOS 系統(tǒng)允許開發(fā)者在 App 處于后臺(tái)的情況下威兜,執(zhí)行一些代碼,大概提供幾分鐘的時(shí)間庐椒,可以用來偷偷的刷新 UI椒舵、切換頁面、下載更新包等等操作约谈。 - 處于退出笔宿,無法獲取通知內(nèi)容。
- 處于前臺(tái)抓艳,可通過
- 通知內(nèi)容類似如下:
json
{
"_j_msgid" = 3938587719;
aps = {
alert = "";
"content-available" = 1; // 必帶字段
};
key1 = value1;
}
推送目標(biāo)篇
別名棱诱、標(biāo)簽泼橘、Registration ID 均是第三方提供的用于更方便地指定推送目標(biāo)的功能。
Tip 6:推送根據(jù)目標(biāo)的不同可分為:
- 廣播
- 無差別的發(fā)送給所有用戶迈勋。
- 別名 alias 推送
- 第三方提供的功能炬灭。
- 一個(gè)手機(jī)的一款 App 只能設(shè)置一個(gè) alias (可修改)。
- 建議對(duì)每一個(gè)用戶都取不同的別名靡菇,以此來確定唯一的用戶(也可多個(gè)用戶取 1 個(gè)別名)重归。
- 推送時(shí)可指定多個(gè) alias 來下發(fā)同一內(nèi)容。
- 僅指定 alias 的用戶能夠收到推送厦凤。
- 標(biāo)簽 tag 推送
*第三方提供的功能鼻吮。
*可設(shè)置多個(gè)、可增加较鼓、清空椎木。
*用于指定多樣的屬性,如 『1000』+『daily』+『discount』 可用于表示月消費(fèi)超過 1k博烂、喜歡購買日用品香椎、偏好折扣商品的用戶。
*如果要?jiǎng)h除禽篱,需要在上次設(shè)置時(shí)畜伐,將設(shè)置的 tags 保存至 NSUserDefaults,本次剔除不需要的 tag 后谆级,再重新設(shè)置。
*推送時(shí)可指定多個(gè) tag 來下發(fā)同一內(nèi)容讼积。
*手機(jī)如果設(shè)置了推送指定的多個(gè) tag 中任一個(gè)tag肥照,都能夠收到推送消息。如指定 『1000』+『globe』+『original』 (千元級(jí)消費(fèi)者勤众、全球購舆绎、原價(jià)),那么設(shè)置了 『100』+『globe』+『discount』(百元級(jí)消費(fèi)者们颜、全球購吕朵、折扣價(jià))的用戶可以收到該推送消息猎醇。 - Registration ID 推送
- 第三方提供的功能。
- 在 Tip 3 的第 3 步時(shí)將
deviceToken
提供給第三方之后努溃,其服務(wù)器會(huì)自動(dòng)生成的指向該手機(jī)的唯一 id硫嘶。 - 可在推送時(shí)指定多個(gè) id 來下發(fā)消息。
- 可用于對(duì)核心用戶梧税、旗艦用戶的精準(zhǔn)推送沦疾。
應(yīng)用內(nèi)消息篇
Tip 7:應(yīng)用內(nèi)消息(以下簡(jiǎn)稱消息 )和推送通知的區(qū)別,消息:
- 不需要 Apple 推送證書第队。
- 由第三方的服務(wù)器下發(fā)哮塞,而不是 APNs。
- 相比通知凳谦,更快速忆畅,幾乎沒有延遲,可用于 IM 消息的即時(shí)送達(dá)尸执。
- 能夠長(zhǎng)時(shí)間保留離線消息家凯,可獲取所有歷史消息內(nèi)容。
- 通過長(zhǎng)連接技術(shù)下發(fā)消息剔交,因此:
- 手機(jī)必須啟動(dòng)并與第三方服務(wù)器建立連接肆饶。
- 如果手機(jī)啟動(dòng)立刻切至后臺(tái),很可能沒有建立連接岖常。
- 手機(jī)必須處于前臺(tái)才能收到消息驯镊。
- 手機(jī)從后臺(tái)切回前臺(tái),會(huì)自動(dòng)重新建立連接竭鞍,并收到離線消息板惑。
- 沒有任何展示(橫幅、通知中心偎快、角標(biāo)冯乘、聲音),因此可以:
- 自定義字段實(shí)現(xiàn) UI 效果晒夹。
- 完全在靜默情況下處理 App 內(nèi)部邏輯裆馒。
- 使用一些 App Store 審核不會(huì)通過的功能,在審核時(shí)關(guān)閉功能丐怯,上架后通過接收消息喷好,開啟相關(guān)功能。
組合大招篇
Tip 8:tags 的組合技巧
- 見 Tip 5 - 標(biāo)簽 tag 推送读跷。
- 可以在服務(wù)端來統(tǒng)計(jì)分析用戶行為梗搅,然后將指定的 tags 發(fā)送至手機(jī),手機(jī)接收后再為用戶打上對(duì)應(yīng)的 tags。
Tip 9:通知+消息的組合技巧
- 首先來看通知和消息特性的對(duì)比:
通知 | 消息 | |
---|---|---|
送達(dá)時(shí)間 | 可能存在幾秒延遲 | 幾乎無延遲 |
獲取時(shí)機(jī) | 處于前臺(tái)或后臺(tái)能獲取內(nèi)容 | 僅處于前臺(tái)能獲取內(nèi)容 |
離線內(nèi)容 | 保留一段時(shí)間无切,過期會(huì)拋棄荡短,無法查詢歷史內(nèi)容 | 始終保留,可查詢?nèi)繗v史內(nèi)容 |
系統(tǒng)展示 | 會(huì)展示(靜默推送或App處于前臺(tái)不展示) | 不展示 |
- 由于各自的特性都存在差異哆键,因此二者結(jié)合使用是使得 App 推送性能最大化的必然選擇:
- 情景一:
QQ/微信 聊天:會(huì)同時(shí)下發(fā)一組通知+消息掘托,如果用戶沒有啟動(dòng)QQ,雖有延遲但必然能夠先收到通知洼哎,在收到通知的提醒之后烫映,用戶打開App,此時(shí)收到了離線消息噩峦,即時(shí)更新 UI锭沟,與好友即時(shí)的 發(fā)送/接收 消息。(在收到通知后识补,斷網(wǎng)族淮,然后啟動(dòng) App,你會(huì)發(fā)現(xiàn)此時(shí)手機(jī)里并不會(huì)顯示剛剛通知的內(nèi)容凭涂,因?yàn)樗且揽坷∠硭⑿马撁娴淖@保皇遣粔蚍€(wěn)定的通知)。 - 情景二:(有 請(qǐng)留言補(bǔ)充...)切油。
- 情景一: