?寫作原因:網上看了很多推送文章都沒有完美的解答我的疑惑;主要有以下兩點,1:推送來了我點擊應用圖標進入應用怎么取到推送消息?2:怎么保證一定能夠獲取到遠程推送的消息,因為有的遠程推送消息很重要;這里主要驗證會在哪幾個回調收到內容,行為(手機頂部有消息彈出我叫做行為)是怎樣的
? 其實收到推送到進入應用有這么5種場景,1:程序運行在前臺來推送了,2:程序運行在后臺來推送了,我點擊推送消息進入程序,3:程序運行在后臺來推送了,我點擊應用圖標進入程序,4:程序沒運行來推送了,我點擊推送消息進入程序,5:程序沒運行來推送了,我點擊應用圖標進入程序
? 講推送的文章實在是太多了,我就不啰嗦原理(http://www.lxweimin.com/p/ace1b422bad4)和配置(http://www.lxweimin.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中;然后我們分別來進行試驗
1:A和B回調都寫上
1)程序運行在前臺來本地推送了
? 我在我項目中創建一個按鈕,給按鈕響應添加一個只觸發一次的本地推送(代碼就不寫了,都會寫);在這兩個回調中打上斷點,現在我們運行程序點擊按鈕然后讓程序運行到前臺,慢慢等待本地推送觸發(看點網站)~~~
? 斷點如約執行,先是執行了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回調
什么行為:沒行為
2)程序運行在后臺來本地推送了,我點擊推送消息進入程序
? 依然和上面一樣,我們點擊按鈕然后把程序運行到后臺;在這兩個回調中打上斷點,慢慢等待本地推送觸發(看點網站)~~~
? 好了,這時候手機頂部彈出消息了,應用圖標右上角也有數字了,注意這時候兩個回調一個都沒有觸發,就像這樣:
? 好了,我們興奮的點一下通知欄,好的,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回調
什么行為:圖標有數字,通知欄有通知
3)程序運行在后臺來本地推送了,我點擊應用圖標進入程序
? 依然重復上面的步驟,點擊按鈕,把應用運行到后臺,在這兩個回調中打上斷點,慢慢等待本地推送觸發(看點網站)~~~
? 好了,這時候手機頂部彈出消息了,應用圖標右上角也有數字了;注意這時候兩個回調一個都沒有觸發,和上面的一樣,然后我們點擊應用圖標進入應用:
?好的,你沒有看錯,A和B一個都沒有觸發,那我怎么獲取到本地推送消息呢,你在逗我嗎?結論:
會觸發哪些回調:點擊應用圖標從后臺進入前臺,不會觸發A回調,不會觸發B回調
什么行為:圖標有數字,通知欄有通知
4)程序沒運行來本地推送了,我點擊推送消息進入程序
? 我還在想這個要怎么打斷點呢,因為程序沒有運行。。。那我們就用一個UIAlertView顯示notification吧(后面都用顯示代替斷點,因為XCode8進入斷點實在是太慢);這里我們在啟動程序時:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}
? 這里面也顯示一下launchOptions,因為程序啟動萬一附帶有數據呢;同樣的,點擊按鈕然添加本地通知后把程序殺死,慢慢等待本地推送觸發(看點網站)~~~
? 好了,手機頂部推送如約而至,這時候回調肯定也不會觸發,我們點擊通知欄啟動程序:
? 果然,啟動參數里面帶上了我們的推送內容;我們點擊取消,然后A和B的提示框沒有彈出,結論:
會觸發哪些回調:程序為運行,點擊通知欄啟動程序,不會觸發A、B回調,啟動參數有推送內容
什么行為:圖標有數字,通知欄有通知
5)程序沒運行來本地推送了,我點擊應用圖標進入程序
? 依然如此,我們進應用點擊按鈕添加推送,然后殺死程序,等待推送;推送如約而至,這時候兩個回調也不會觸發,我們點擊應用圖標進入程序,會看到下面的效果:
? 點擊取消,繼續運行,然后A和B的提示框沒有彈出,結論:
會觸發哪些回調:程序未運行,點擊應用圖標啟動程序,不會觸發A、B回調,啟動參數也沒有內容
什么行為:圖標有數字,通知欄有通知
好了,是不是很蛋疼,A和B加一起B永遠都不會觸發;接下來我們來驗證只寫其中一個函數是怎樣的(這時候我還沒有想起來B是干啥的,還在試錯呢)
2:只寫A回調
? 驗證方法和上面的一樣,我就不截圖了(但是我真的重復了一遍哦),直接寫結論
1)程序運行在前臺來本地推送了
會觸發哪些回調:應用在前臺,會觸發A回調
什么行為:沒有行為
2)程序運行在后臺來本地推送了,我點擊推送消息進入程序
會觸發哪些回調:應用在后臺,點擊通知欄進入前臺,會觸發A回調
什么行為:圖標有數字,通知欄有通知
3)程序運行在后臺來本地推送了,我點擊應用圖標進入程序
會觸發哪些回調:應用在后臺,點擊應用圖標進入前臺,不會觸發A回調
什么行為:圖標有數字,通知欄有通知
4)程序沒運行來本地推送了,我點擊推送消息進入程序
會觸發哪些回調:程序未運行,點擊通知欄啟動程序,不會觸發A回調,啟動參數有內容
什么行為:圖標有數字,通知欄有通知
5)程序沒運行來本地推送了,我點擊應用圖標進入程序
會觸發哪些回調:程序未運行,點擊應用圖標啟動程序,不會觸發A回調,啟動參數也沒有內容
什么行為:圖標有數字,通知欄有通知
? 好的,和上面一樣,所以我們現在只寫B回調驗證一下
3:只寫B回調
? 馬上就可以做完本地推送了,有點激動;同理,直接來結論(我還是沒有想起來B是干嘛的)
1)程序運行在前臺來本地推送了
會觸發哪些回調:應用在前臺,不會觸發B回調
什么行為:沒有行為
居然沒有觸發,我都不相信自己的眼睛,于是我又重新測了一次,還是沒有觸發
2)程序運行在后臺來本地推送了,我點擊推送消息進入程序
會觸發哪些回調:應用在后臺,點擊通知欄進入前臺,不會觸發B回調
什么行為:圖標有數字,通知欄有通知
3)程序運行在后臺來本地推送了,我點擊應用圖標進入程序
會觸發哪些回調:應用在后臺,點擊應用圖標進入前臺,不會觸發B回調
什么行為:圖標有數字,通知欄有通知
4)程序沒運行來本地推送了,我點擊推送消息進入程序
會觸發哪些回調:程序未運行,點擊通知欄啟動程序,不會觸發B回調,啟動參數有內容
什么行為:圖標有數字,通知欄有通知
5)程序沒運行來本地推送了,我點擊應用圖標進入程序
會觸發哪些回調:程序未運行,點擊應用圖標啟動程序,不會觸發B回調,啟動參數也沒有內容
什么行為:圖標有數字,通知欄有通知?
好了,現在是時候谷歌一下B函數到底是干嘛的了,為啥都沒有觸發;我在這里找到了答案http://www.bozhiyue.com/ios/2016/0811/358999.html,好吧我終于知道什么意思了;B函數是點擊這里會觸發:
所以我們把結論重新整理一下(好吧,這時候終于步入正軌了),
1)程序運行在前臺來本地推送了
會觸發哪些回調:應用在前臺,不會觸發B回調(因為沒有點擊action)
什么行為:沒有行為
2)程序運行在后臺來本地推送了,我點擊推送消息的action
會觸發哪些回調:程序運行在后臺,推送action不會進入前臺,不會觸發B回調
什么行為:圖標有數字,通知欄有通知
還是沒有觸發,我去;這又是鬧哪樣?能不能少點套路,我們繼續谷歌;http://www.lxweimin.com/p/803bfaae989e這里說到遠程推送可以觸發,那是不是本地推送不會觸發呢?而且我也是加了自定義action的:
那到底是什么意思呢?我們繼續往下面做實驗,看看到后面的遠程推送會不會觸發
3)程序運行在后臺來本地推送了,我點擊應用圖標進入程序
會觸發哪些回調:應用在后臺,點擊應用圖標進入前臺,不會觸發B回調(因為沒有點擊action)
什么行為:圖標有數字,通知欄有通知
4)程序沒運行來本地推送了,我點擊推送消息的action
會觸發哪些回調:應用未運行,點擊推送消息action不會啟動程序,不會觸發B回調
什么行為:圖標有數字,通知欄有通知
5)程序沒運行來本地推送了,我點擊應用圖標進入程序
會觸發哪些回調:應用在后臺,點擊應用圖標進入前臺,不會觸發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,然后我們在獲取時得到下面的錯誤:
趕緊谷歌,找到了http://blog.csdn.net/u013263917/article/details/24712797和http://blog.csdn.net/soindy/article/details/46537095,于是我重新在官網生成一次開發者證書、推送證書和描述文件等;還是一樣的問題;我在想是不是因為我項目集成了個推,然后我把個推關閉了;還是一樣的問題(此刻我心里有點慌);然后http://www.lxweimin.com/p/c2bb07786fd1說打開這里:
? 這個紅色的錯誤不用解決,然后可以看到這里:
? 這時候就能得到設備token了:
? 用上模擬推送的工具開始驗證!
一:測試C回調
1)程序運行在前臺來遠程推送了
? 啟動真機,然后我們點擊這里模擬推送(以下用"push"按鈕代替說明):
等待;然后我們程序彈窗了,內容就是工具模擬的內容,結論:
會觸發哪些回調:應用在前臺,會觸發C回調
什么行為:沒有行為
2)程序運行在后臺來遠程推送了,我點擊推送消息進入程序
? 把應用切換到后臺,點擊工具的"push"按鈕,等待推送;點擊推送進入前臺彈出提示框,結論:
會觸發哪些回調:程序運行在后臺,點擊推送會進入前臺,觸發C回調
什么行為:圖標有數字,通知欄有通知
3)程序運行在后臺來遠程推送了,我點擊應用圖標進入程序
? 依然,切換到后臺,點擊工具"push"按鈕,等待;沒有彈窗,結論:
會觸發哪些回調:程序運行在后臺,點擊應用圖標會進入前臺,不會觸發C回調
什么行為:圖標有數字,通知欄有通知
4)程序沒運行來遠程推送了,我點擊推送消息進入程序
? 我們把程序殺死,點擊工具"push"按鈕,等待;點擊推送欄進入程序,啟動參數顯示了,沒有觸發A回調,結論:
會觸發哪些回調:程序未運行,點擊推送進入前臺,不會觸發C回調,啟動參數有內容
什么行為:圖標有數字,通知欄有通知
5)程序沒運行來遠程推送了,我點擊應用圖標進入程序
殺死程序,點擊"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
? 同樣的我們啟動程序,然后讓后臺給我們發一個個推推送
1)程序運行在前臺來個推推送了
? 等待推送;這時候個推A回調彈窗了,原生B沒有執行,結論:
會觸發哪些回調:應用在前臺,會觸發個推A回調,不會觸發原生B回調
什么行為:沒有行為
? ?這里我們可以認為是個推推過來的,不管原生的事情,先這么理解吧
2)程序運行在后臺來個推推送了,我點擊推送消息進入程序
? 然后,我們把程序切換到后臺,等待推送;這時候我們點擊推送進入前臺,個推A顯示了,然后原生B也彈出來了,我們來看看原生的是什么內容:
? 這個內容不是我讓后臺發送的內容,應該是個推那邊附加的,那么結論:
會觸發哪些回調:程序運行在后臺,點擊推送會進入前臺,觸發個推A回調,然后觸發原生B回調
什么行為:圖標有數字,通知欄有通知
3)程序運行在后臺來個推推送了,我點擊應用圖標進入程序
? 依然如此,切換到后臺,等待推送;點擊應用圖標進入程序,個推A觸發,原生B沒有觸發,結論:
會觸發哪些回調:程序運行在后臺,點擊應用圖標會進入前臺,觸發個推A回調,不觸發原生B回調
什么行為:圖標有數字,通知欄有通知
? 這就比較好了嘛,應用圖標進入都會有推送內容,這就是我想要的功能
4)程序沒運行來個推推送了,我點擊推送消息進入程序
? 把程序殺死,等待推送;點擊推送進入程序,啟動參數有內容但不是我讓后臺發送的內容(也是附加內容),然后會觸發個推A回調,不會觸發原生B回調,結論:
會觸發哪些回調:程序未運行,點擊推送進入程序,啟動參數有內容,觸發個推A回調,不觸發原生B回調
什么行為:圖標有數字,通知欄有通知
?附加內容還是很好理解的,就是提醒你一下有消息,然后等你正在進入的時候再給你發真正的內容
5)程序沒運行來個推推送了,我點擊應用圖標進入程序
依然殺死程序,等待推送;點擊應用圖標進入程序,啟動參數沒有內容,個推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;還終于弄明白了公司在個推首頁為啥注冊了兩個同樣的應用:
這就是一個拿來測試環境,一個正式環境啊!
?然后我已經寫好了自定義action,你們可以點看看下面的拓展閱讀!