寫作原因:網上看了很多推送文章都沒有完美的解答我的疑惑;主要有以下兩點,1:推送來了我點擊應用圖標進入應用怎麼取到推送消息?2:怎麼保證一定能夠獲取到遠程推送的消息,因為有的遠程推送消息很重要;這裡主要驗證會在哪幾個回調收到內容,行為(手機頂部有消息彈出我叫做行為)是怎樣的
其實收到推送到進入應用有這麼5種場景,1:程序運行在前台來推送了,2:程序運行在後台來推送了,我點擊推送消息進入程序,3:程序運行在後台來推送了,我點擊應用圖標進入程序,4:程序沒運行來推送了,我點擊推送消息進入程序,5:程序沒運行來推送了,我點擊應用圖標進入程序
講推送的文章實在是太多了,我就不啰嗦原理(http://www.jianshu.com/p/ace1b422bad4)和配置(http://www.jianshu.com/p/db9c95c9e29f)了;我直接拿我的項目(項目最低適配iOS8)來從以下三個方面回答上面5種情況下會在哪些回調收到內容,行為是怎樣的
我們從UIApplicationDelegate中找一找哪些是和本地推送相關的回調,可以發現有下面這三個;假設現在你不知道B和C什麼意思,我也是後面才想起來的(有點癡呆了),不過都寫了這麼多了就不想刪除了:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {}//A回調 (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void(^)())completionHandler {}//B回調 - (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler {}//C回調
細心的小伙伴可能說了,A回調後面不是說讓你用XXX回調代替嗎?哥們,這個函數有效期是iOSx-iOS10,你慌啥啊,等iOS11出來了再換呗;然後B和C描述一樣說明功能一樣,我們這裡使用B,C是iOS9-iOS10,B是iOS8-iOS10我們要適配版本;這裡我們還不知道B和C是什麼時候調用,沒關系我們慢慢來做實驗,我們把A和B寫到AppDelegate.m中;然後我們分別來進行試驗
我在我項目中創建一個按鈕,給按鈕響應添加一個只觸發一次的本地推送(代碼就不寫了,都會寫);在這兩個回調中打上斷點,現在我們運行程序點擊按鈕然後讓程序運行到前台,慢慢等待本地推送觸發(看點網站)~~~
斷點如約執行,先是執行了A回調,我們XCode下方打印一下notification看看是什麼鬼:
{fire date = 2016年10月24日 星期一 中國標准時間 下午4:03:08, time zone = Asia/Shanghai (GMT+8) offset 28800, repeat interval = 0, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = (null), user info = { action = GENERAL; "company_no" = 10295; content = "\U4e8b\U52a1\U63d0\U9192: boot1"; "from_user_no" = 21175; "target_id" = 15812; time = 1477296248000; "to_user_no" = 21175; type = CALENDARTIP; unread = 1; }}
內容大概是觸發這次推送的時間(fire date)+時區(time zone)+間隔周期(repeat interval)+重復次數(repeat count)+下次觸發時間(next fire date)+添加到本地推送的內容(user info),好了沒有什麼問題,然後我們繼續執行程序,B怎麼不執行了?我擦,我們回過頭看看B回調上面的注釋:
// Called when your app has been activated by the user selecting an action from a local notification.
// A nil action identifier indicates the default action.
// You should call the completion handler as soon as you've finished handling the action.
依我考過英語四級(只是考過,沒有考過)的水平翻譯一下,這個回調被觸發當用戶從本地通知點擊一個action,一個不為nil的action指示默認的action,你應該寫一下完成回調當你握住了這個action(我已經被我的英語水平屈服了);不過意思大概懂了是從通知欄點擊某一項激活項目,那麼啥算激活項目?後台進入前台還是被殺死的項目啟動了?不管了,結論很重要:
會觸發哪些回調:應用在前台,只會觸發A回調
什麼行為:沒行為
依然和上面一樣,我們點擊按鈕然後把程序運行到後台;在這兩個回調中打上斷點,慢慢等待本地推送觸發(看點網站)~~~
好了,這時候手機頂部彈出消息了,應用圖標右上角也有數字了,注意這時候兩個回調一個都沒有觸發,就像這樣:
通知欄有通知應用圖標有數字好了,我們興奮的點一下通知欄,好的,A回調先被觸發,我們打印一下notification:
{fire date = 2016年10月24日 星期一 中國標准時間 下午4:25:21, time zone = Asia/Shanghai (GMT+8) offset 28800, repeat interval = 0, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = (null), user info = { action = GENERAL; "company_no" = 10295; content = "\U4e8b\U52a1\U63d0\U9192: boot3"; "from_user_no" = 21175; "target_id" = 15815; time = 1477297581000; "to_user_no" = 21175; type = CALENDARTIP; unread = 1; }}
這個和上面的一樣,不解釋了,我們繼續運行,好的B沒有被觸發,結論:
會觸發哪些回調:點擊通知欄從後台進入前台,只會觸發A回調
什麼行為:圖標有數字,通知欄有通知
依然重復上面的步驟,點擊按鈕,把應用運行到後台,在這兩個回調中打上斷點,慢慢等待本地推送觸發(看點網站)~~~
好了,這時候手機頂部彈出消息了,應用圖標右上角也有數字了;注意這時候兩個回調一個都沒有觸發,和上面的一樣,然後我們點擊應用圖標進入應用:
點應用圖標進入前台好的,你沒有看錯,A和B一個都沒有觸發,那我怎麼獲取到本地推送消息呢,你在逗我嗎?結論:
會觸發哪些回調:點擊應用圖標從後台進入前台,不會觸發A回調,不會觸發B回調
什麼行為:圖標有數字,通知欄有通知
我還在想這個要怎麼打斷點呢,因為程序沒有運行。。。那我們就用一個UIAlertView顯示notification吧(後面都用顯示代替斷點,因為XCode8進入斷點實在是太慢);這裡我們在啟動程序時:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}
這裡面也顯示一下launchOptions,因為程序啟動萬一附帶有數據呢;同樣的,點擊按鈕然添加本地通知後把程序殺死,慢慢等待本地推送觸發(看點網站)~~~
好了,手機頂部推送如約而至,這時候回調肯定也不會觸發,我們點擊通知欄action啟動程序:
啟動參數果然,啟動參數裡面帶上了我們的推送內容;我們點擊取消,然後A和B的提示框沒有彈出,結論:
會觸發哪些回調:程序為運行,點擊通知欄啟動程序,不會觸發A、B回調,啟動參數有推送內容
什麼行為:圖標有數字,通知欄有通知
依然如此,我們進應用點擊按鈕天津愛推送,然後殺死程序,等待推送;推送如約而至,這時候兩個回調也不會觸發,我們點擊應用圖標進入程序,會看到下面的效果:
啟動參數點擊取消,繼續運行,然後A和B的提示框沒有彈出,結論:
會觸發哪些回調:程序未運行,點擊應用圖標啟動程序,不會觸發A、B回調,啟動參數也沒有內容
什麼行為:圖標有數字,通知欄有通知
好了,是不是很蛋疼,A和B加一起B永遠都不會觸發;接下來我們來驗證只寫其中一個函數是怎樣的(這時候我還沒有想起來B是干啥的,還在試錯呢)
驗證方法和上面的一樣,我就不截圖了(但是我真的重復了一遍哦),直接寫結論
會觸發哪些回調:應用在前台,會觸發A回調
什麼行為:沒有行為
會觸發哪些回調:應用在後台,點擊通知欄進入前台,會觸發A回調
什麼行為:圖標有數字,通知欄有通知
會觸發哪些回調:應用在後台,點擊應用圖標進入前台,不會觸發A回調
什麼行為:圖標有數字,通知欄有通知
會觸發哪些回調:程序未運行,點擊通知欄啟動程序,不會觸發A回調,啟動參數有內容
什麼行為:圖標有數字,通知欄有通知
會觸發哪些回調:程序未運行,點擊應用圖標啟動程序,不會觸發A回調,啟動參數也沒有內容
什麼行為:圖標有數字,通知欄有通知
好的,和上面一樣,所以我們現在只寫B回調驗證一下
馬上就可以做完本地推送了,有點激動;同理,直接來結論(我還是沒有想起來B是干嘛的)
會觸發哪些回調:應用在前台,不會觸發B回調
什麼行為:沒有行為
居然沒有觸發,我都不相信自己的眼睛,於是我又重新測了一次,還是沒有觸發
會觸發哪些回調:應用在後台,點擊通知欄進入前台,不會觸發B回調
什麼行為:圖標有數字,通知欄有通知
會觸發哪些回調:應用在後台,點擊應用圖標進入前台,不會觸發B回調
什麼行為:圖標有數字,通知欄有通知
會觸發哪些回調:程序未運行,點擊通知欄啟動程序,不會觸發B回調,啟動參數有內容
什麼行為:圖標有數字,通知欄有通知
會觸發哪些回調:程序未運行,點擊應用圖標啟動程序,不會觸發B回調,啟動參數也沒有內容
什麼行為:圖標有數字,通知欄有通知
好了,現在是時候谷歌一下B函數到底是干嘛的了,為啥都沒有觸發;我在這裡找到了答案http://www.bozhiyue.com/ios/2016/0811/358999.html,好吧我終於知道什麼意思了;B函數是點擊這裡會觸發:
這才是action啊,我的天所以我們把結論重新整理一下(好吧,這時候終於步入正軌了),
會觸發哪些回調:應用在前台,不會觸發B回調(因為沒有點擊action)
什麼行為:沒有行為
會觸發哪些回調:程序運行在後台,推送action不會進入前台,不會觸發B回調
什麼行為:圖標有數字,通知欄有通知
還是沒有觸發,我去;這又是鬧哪樣?能不能少點套路,我們繼續谷歌;http://www.jianshu.com/p/803bfaae989e這裡說到遠程推送可以觸發,那是不是本地推送不會觸發呢?而且我也是加了自定義action的:
自定義action那到底是什麼意思呢?我們繼續往下面做實驗,看看到後面的遠程推送會不會觸發
會觸發哪些回調:應用在後台,點擊應用圖標進入前台,不會觸發B回調(因為沒有點擊action)
什麼行為:圖標有數字,通知欄有通知
會觸發哪些回調:應用未運行,點擊推送消息action不會啟動程序,不會觸發B回調
什麼行為:圖標有數字,通知欄有通知
會觸發哪些回調:應用在後台,點擊應用圖標進入前台,不會觸發B回調(因為沒有點擊action)
什麼行為:圖標有數字,通知欄有通知
好吧,我得再寫一篇文章專門寫怎麼自定義推送action還有上面5種情況對應的行為了,可這裡不觸發可能是我沒有加正確;
那我們現在來看看遠程推送,這次終於弄明白A和B是干嘛的了;所以我們做本地推送兩個回調都要寫上,因為作用不一樣。
遠程推送必須真機,提醒一下!我們先在UIApplicationDelegate中找找遠程推送相關的回調(和action有關的我們就不管了,另起一篇文章寫action):
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {}//B - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {}//C
然後B回調https://docs.kii.com/cn/guides/cloudsdk/ios/managing-push-notification/push-to-user/receiving-messages/有解釋說的是靜默推送使用B回調,那麼啥是靜默推送呢?http://www.devlizy.com/ios-ding-shi-huo-qu-he-jing-mo-tui-song/這裡給出了解釋,也就是說你的程序在後台收到遠程推送將直接觸發這個回調而不用等應用進入前台,這麼好玩,但是我們不驗證這個;C回調就是收到遠程推送了,C回調注釋說明了用B接收靜默推送,用XXX接收遠程推送,我們不管;所以我們在AppDelegate.m中加上C一個回調就行了,內容就像這樣:
遠程推送回調由於我們項目已經集成了個推三方推送,要實現不使用第三方推送來測試;我們就要用到下面的工具來測試環境模擬推送了(你們不用下載,看我表演就行了)。
測試環境模擬遠程推送這個工具我們下載安裝後,啟動就看到這個界面:
模擬推送工具怎麼用就不說了吧,這麼簡單;我們先獲取設備token,然後我們在獲取時得到下面的錯誤:
獲取token失敗趕緊谷歌,找到了http://blog.csdn.net/u013263917/article/details/24712797和http://blog.csdn.net/soindy/article/details/46537095,於是我重新在官網生成一次開發者證書、推送證書和描述文件等;還是一樣的問題;我在想是不是因為我項目集成了個推,然後我把個推關閉了;還是一樣的問題(此刻我心裡有點慌);然後http://www.jianshu.com/p/c2bb07786fd1說打開這裡:
開啟推送這個紅色的錯誤不用解決,然後可以看到這裡:
測試和正式不一樣這時候就能得到設備token了:
能獲取token了用上模擬推送的工具開始驗證!
啟動真機,然後我們點擊這裡模擬推送(以下用"push"按鈕代替說明):
推送等待;然後我們程序彈窗了,內容就是工具模擬的內容,結論:
會觸發哪些回調:應用在前台,會觸發C回調
什麼行為:沒有行為
把應用切換到後台,點擊工具的"push"按鈕,等待推送;點擊推送進入前台彈出提示框,結論:
會觸發哪些回調:程序運行在後台,點擊推送會進入前台,觸發C回調
什麼行為:圖標有數字,通知欄有通知
依然,切換到後台,點擊工具"push"按鈕,等待;沒有彈窗,結論:
會觸發哪些回調:程序運行在後台,點擊應用圖標會進入前台,不會觸發C回調
什麼行為:圖標有數字,通知欄有通知
我們把程序殺死,點擊工具"push"按鈕,等待;點擊推送欄進入程序,啟動參數顯示了,沒有觸發A回調,結論:
會觸發哪些回調:程序未運行,點擊推送進入前台,不會觸發C回調,啟動參數有內容
什麼行為:圖標有數字,通知欄有通知
殺死程序,點擊"push"按鈕,等待;點擊圖標啟動程序,啟動參數沒有,沒有觸發C回調,結論:
會觸發哪些回調:程序未運行,點擊應用圖標進入前台,不會觸發C回調,啟動參數無內容
什麼行為:圖標有數字,通知欄有通知
這個和本地推送是吻合的,但是發現了沒,原生遠程推送沒辦法保證用戶一定能得到數據,因為從應用圖標進入程序是得不到的,所以只有服務器存客戶端進應用就拉取是不?那麼第三方推送做了嗎?我們滿懷期待的來測試一下
同樣的,我們不講怎麼配置個推http://docs.getui.com/mobile/ios/overview/;集成之後個推接收推送的回調長得像這樣(你們不用集成,看我就行):
- (void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId {}//A
在回調中加上顯示內容代碼:
個推回調同樣的我們要加上原生的遠程推送來看看會不會也顯示出來:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {}//B
同樣的我們啟動程序,然後讓後台給我們發一個個推推送
等待推送;這時候個推A回調彈窗了,原生B沒有執行,結論:
會觸發哪些回調:應用在前台,會觸發個推A回調,不會觸發原生B回調
什麼行為:沒有行為
這裡我們可以認為是個推推過來的,不管原生的事情,先這麼理解吧
然後,我們把程序切換到後台,等待推送;這時候我們點擊推送進入前台,個推A顯示了,然後原生B也彈出來了,我們來看看原生的是什麼內容:
原生的被觸發了這個內容不是我讓後台發送的內容,應該是個推那邊附加的,那麼結論:
會觸發哪些回調:程序運行在後台,點擊推送會進入前台,觸發個推A回調,然後觸發原生B回調
什麼行為:圖標有數字,通知欄有通知
依然如此,切換到後台,等待推送;點擊應用圖標進入程序,個推A觸發,原生B沒有觸發,結論:
會觸發哪些回調:程序運行在後台,點擊應用圖標會進入前台,觸發個推A回調,不觸發原生B回調
什麼行為:圖標有數字,通知欄有通知
這就比較好了嘛,應用圖標進入都會有推送內容,這就是我想要的功能
把程序殺死,等待推送;點擊推送進入程序,啟動參數有內容但不是我讓後台發送的內容(也是附加內容),然後會觸發個推A回調,不會觸發原生B回調,結論:
會觸發哪些回調:程序未運行,點擊推送進入程序,啟動參數有內容,觸發個推A回調,不觸發原生B回調
什麼行為:圖標有數字,通知欄有通知
附加內容還是很好理解的,就是提醒你一下有消息,然後等你正在進入的時候再給你發真正的內容
依然殺死程序,等待推送;點擊應用圖標進入程序,啟動參數沒有內容,個推A觸發,原生B沒有觸發,結論:
會觸發哪些回調:程序未運行,點擊圖標進入程序,啟動無內容,觸發個推A回調,不觸發原生B回調
什麼行為:圖標有數字,通知欄有通知
好了,第三方推送能保證消息一定能發送到用戶,這點比較好的,你可能會說個推怎麼做到的?給你一個網址去看看
英語真的是一個好東西,做東西之前要多看文章,看不懂就要多驗證
1:推送內容會在啟動參數或本地推送回調中獲取,2:應用圖標進入程序不會獲取到任何內容
1:推送內容會在啟動參數或遠程推送回調中獲取,2:應用圖標進入程序不會獲取到任何內容,3:服務器要保存推送內容,以免重要數據丟失
1:用戶在程序就一定能從個推回調中得到推送內容,2:原生遠程推送回調和啟動參數是附加內容不用處理
首先,自己懵逼了居然忘記下面這個回調是干嘛的,於是花了一上午來才坑:
-(void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void(^)())completionHandle{}//自定義推送消息的action被點擊
然後,我前面的個推推送測試都是在測試環境進行的沒有任何問題,然後第二天我又去了正式環境發現表現不一樣了,我有點慌了馬上加了個推服務方QQ,然後終於明白了,是自己證書的問題http://www.qingpingshan.com/rjbc/ios/139338.html;還終於弄明白了公司在個推首頁為啥注冊了兩個同樣的應用:
兩個一樣的應用這就是一個拿來測試環境,一個正式環境啊!