iOS 推送方案需要了解的知识

如果是按照需求开发推送功能,那么只需要按照对应要求实施代码就可以了;但是如果要拿出一个iOS推送方案,就需要先对iOS系统的推送知识有个系统性的了解再说了。

一、静默推送与普通推送

静默推送
静默推送消息到来时不会有声音、震动、通知图标, 会唤醒APP运行在后台,会调用application:didReceiveRemoteNotification:fetchCompletionHandler: 方法,唤醒后有最多30S的时间来处理任务。值得注意的是,如果是用户手机Home键,手动退出APP,此APP在用户再次启动或者重启了手机之前,系统不会唤醒APP;

肯定还是要看官方的解释
A silent notification is a remote notification that doesn't display an alert, play a sound, or badge your app’s icon. It wakes your app in the background and gives it time to initiate downloads from your server and update its content.
// 以上是说:静默推送消息到来时会唤醒APP运行在后台,不会有声音、震动、通知图标.

Important
the system doesn't guarantee their delivery. In addition, the delivery of silent notifications may be throttled if the total number becomes excessive. The actual number of silent notifications allowed by the system depends on current conditions, but don't try to send more than two or three silent notifications per hour.
// 以上说:如果静默推送涉及用户过多会被“节流”,不要超过每小时2-3条。

To send a silent notification, create a remote notification whose aps dictionary includes only the content-available key, as shown in Listing 1. You may include custom keys in the payload, but the aps dictionary must not contain any keys that would trigger user interactions.
// 以上说: 发送静默推送时aps里面只能有一个键值对 "content-available" : 1

{
   "aps" : {
      "content-available" : 1
   },
   "customKey1" : "bar",
   "customKey2" : 42
}

普通推送
不包含"content-available": 1的键值对,至于具体会不会有声音震动与用户的设置有关。

本地推送

  • 可以设置UNCalendarNotificationTrigger(按日期触发 )、UNLocationNotificationTrigger(按照地点触发)、UNTimeIntervalNotificationTrigger(指定时间点触发);
  • 可以自定义播放音频,不过音频文件需要在程序bundle或者在Library/Sounds目录里面(可以安装iMazing来查看真机的APP目录)
二、推送的图解及远程推送的注册

远程推送消息如何来到用户的手机? 按照下图的步骤走一遍就清楚了


APNs实现原理图解.jpg
if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        center.delegate = self;
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
       }];
    } else if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0){// iOS8-iOS9
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound) categories:nil];
        [application registerUserNotificationSettings:settings];
    }

[application registerForRemoteNotifications];

需要注意的是远程推送的注册在注册方法调用后就会去得到一个deviceToken,与用户时候允许接收通知无关。也就是用户不同意的情况下,只要获取未出错,都能得到deviceToken. 且这个deviceToken不是固定的。

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog(@"deviceToken = %@",deviceToken);
    NSString *token=[NSString stringWithFormat:@"%@",deviceToken];
    token=[token stringByReplacingOccurrencesOfString:@"<" withString:@""];
    token=[token stringByReplacingOccurrencesOfString:@">" withString:@""];
    token=[token stringByReplacingOccurrencesOfString:@" " withString:@""];
    // TODO
}
三、收到推送后调用的方法总结

因为iOS 8以下、iOS 8 - iOS 10、iOS 10以上系统对方法的调用都不同,所以需要弄清楚推送消息来临时会调用的方法才能做出合适的处理。这里只写iOS 8 以上需要实现的方法。

// 方法A:经过了公司测试机测试的可以信赖😁
//  1. iOS 8-iOS10 系统的普通推送,APP处于前台运行或者点击远程推送消息进入APP都会来到这个方法
//  2. 只要是静默推送消息,会调用此方法。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;

// 方法B:iOS10以上的方法,适用于iOS10以上设备
// 推送消息到达时用户APP正处于前台运行中会调用这个方法
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;

// 方法C: iOS10以上的方法,适用于iOS10以上设备
// 用户通过点击推送通知进入APP时会调用这个方法
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler;

// 这个是弃用的方法,实现方法A即可忽略这个方法
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;

用一个图来总结上面就是:方法的标号看上面!!!

推送的方法调用.png

三、iOS10以上推送插件开发-UNNotificationServiceExtension、UNNotificationContentExtension
  1. 系统在展示通知之前,可以唤起app附带的UNNotificationServiceExtension,并且允许它改动通知的内容;
  2. 用户在对通知右滑查看、下拉或者3d touch的时候,通知会展开,展开后页面的布局可以由app附带的UNNotificationContentExtension来决定。
  3. 插件的使用可查看:https://www.jianshu.com/p/f77d070a8812
  4. 不使用VoIP push 的APP要实现到账语音播报功能等,使用UNNotificationServiceExtension是很好的选择
四、推送测试工具推荐

下面这个测试工具能帮助你测试推送消息
https://github.com/noodlewerk/NWPusher?spm=5176.100239.blogcont4803.8.59EeIh

推送插件的测试:步骤如下
第一步: 开发推送证书的生成、导出P12文件、查看APP是否可以接受通知等基本操作----略
第二步:Xcode中选择自己的插件然后点击运行,接下来会弹窗让你选择运行插件到哪个APP,这个时候选择自己的APP就可以了
第三步:打开上面的NWPusher工具,推送消息,即可以断点调试。

五、deviceToken变化之谜

从苹果官方的说法,deviceToken是会变化的
Never cache the device token locally on the user's device. Device tokens can change periodically, so caching the value risks sending an invalid token to your server

也就是说deviceToken是会变化的,而且变化之后上次获取到的deviceToken在有些设备上是不失效的,这就会产生一个bug: 一个推送消息可能会在同一台设备上出现多次,这点是极不好的。
解决办法:
还要获取到设备的另一个唯一标志IDFA(IDFA会在重置系统时变化,需要与keychain配合起来保证唯一性)与deviceToken同时上传给后台,后台记录deviceToken时需要先比对这个唯一标志再决定是替换还是新增。

这点可以在论坛和博客上都可以知道有人踩过坑,如:https://www.jianshu.com/p/a8ebb6c3e569

当然,如果是集成的第三方的推送功能,就不需要你去考虑这个问题了。

只能帮你到这,推荐阅读:
iOS静默推送进阶知识
了解iOS消息推送一文就够:史上最全iOS Push技术详解
iOS推送,看这篇就够了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容