iOS-推送詳解

準(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ù)

  1. 在代碼中注冊(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
  1. 在第一次觸發(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è)。

  2. 如果注冊(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 傳給極光推送
}
  1. 如果以上步驟均成功,此時(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了)呆奕。
  1. 綜上,注冊(cè)及接收推送必須使用真機(jī)衬吆,必須連網(wǎng)梁钾。

Tip 4:推送通知從服務(wù)端 --> App代碼的過程

  1. 使用你們公司或第三方的服務(wù)端向APNs發(fā)送推送請(qǐng)求(請(qǐng)參考蘋果 APNs 的相關(guān)資料,或者第三方推送提供了更簡(jiǎn)單的 REST API)逊抡。
  2. APNs 接收并驗(yàn)證推送請(qǐng)求姆泻。
  3. APNs 找到設(shè)備下發(fā)推送。
  4. 手機(jī)收到推送通知冒嫡,系統(tǒng)根據(jù)App狀態(tài)進(jìn)行處理:
    • 前臺(tái)收到:
      • 系統(tǒng)會(huì)將通知內(nèi)容傳到didReceiveRemoteNotification麦射;
    • 后臺(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)方面。

推送通知內(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)容抗悍。
      • 通知內(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;酬荞。
    • 必須攜帶alertbadge瞧哟、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)容。
    • 通知內(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)容。
    • 通知內(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ǔ)充...)切油。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蝙斜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子澎胡,更是在濱河造成了極大的恐慌孕荠,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件攻谁,死亡現(xiàn)場(chǎng)離奇詭異稚伍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)戚宦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門个曙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人受楼,你說我怎么就攤上這事垦搬。” “怎么了艳汽?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵猴贰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我骚灸,道長(zhǎng)糟趾,這世上最難降的妖魔是什么慌植? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任甚牲,我火速辦了婚禮义郑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘丈钙。我一直安慰自己非驮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布雏赦。 她就那樣靜靜地躺著劫笙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪星岗。 梳的紋絲不亂的頭發(fā)上填大,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音俏橘,去河邊找鬼允华。 笑死,一個(gè)胖子當(dāng)著我的面吹牛寥掐,可吹牛的內(nèi)容都是我干的靴寂。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼召耘,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼百炬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起污它,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤剖踊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后轨蛤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜜宪,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年祥山,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了圃验。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缝呕,死狀恐怖澳窑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情供常,我是刑警寧澤摊聋,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站栈暇,受9級(jí)特大地震影響麻裁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一煎源、第九天 我趴在偏房一處隱蔽的房頂上張望色迂。 院中可真熱鬧,春花似錦手销、人聲如沸歇僧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诈悍。三九已至,卻和暖如春兽埃,著一層夾襖步出監(jiān)牢的瞬間侥钳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工柄错, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慕趴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓鄙陡,卻偏偏與公主長(zhǎng)得像冕房,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子趁矾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345