注册
iOS

iOS推送通知及静默推送相关

    在IOS推送服务中,Apple提供了两种不同方式的推送形式,一种是在通知栏上面显示的推送;另一种则是不带消息提醒的推送,俗称“静默消息”。

1. 普通推送和静默推送的区别

        普通推送:收到推送后(有文字有声音),点开通知,进入APP后,才执行

- (void)application:(UIApplication didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void result))handler *)application *)userInfo (^)(UIBackgroundFetchResult


        静默推送:(Silent Push)并不是必须要“静默”(通常是没有文字没有声音),只要推送payload中aps字典里包含了"content-available": 1的键值对,都具有静默推送的特性,不用点开通知,不用打开APP,就能执行

-(void)application:(UIApplication )application)userInfo didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void (^)(UIBackgroundFetchResultresult))handler


用户完全感觉不到所以静默推送又被我们称做 Background Remote Notification(后台远程推送)。

        静默推送是在iOS7之后推出的一种推送方式。它与其他推送的区别在于允许应用收到通知后在后台(background)状态下运行一段代码,可用于从服务器获取内容更新。

PS:注册消息通知时通常的弹窗询问权限有什么用呢?其实只是请求用户允许在推送通知到来时能够有alert, badge和sound,而并不是在请求注册推送本身的权限。静默推送即使用户不允许应用的推送,静默推送依然会送达用户设备,只是不会有alert, badge和sound。这也符合静默推送的正常使用场景。



2. 远程推送时 , 应用的几种状态及对应回调方法

     (1) . 应用开启时 , 应用在前台

     (2) . 应用开启时 , 应用在后台

     (3) . 应用未启动(应用被杀死)

从苹果APNS服务器远程推送时:

不使用时(iOS10以后可用)

1 . 如果应用处于 (1) 状态 , 则不会发出声音 , 会直接调用appDelegate的代理方法didReceiveRemoteNotification(didReceiveRemoteNotification:fetchCompletionHandler:)

2 . 如果应用处于 (2) 状态 , 则会发出提示音, 点击推送消息 , 则会调用appDelegate的代理方法didReceiveRemoteNotification

3 . 如果应用处于 (3) 状态,则会发出提示音 , 点击推送消息 , 则会开启应用 , 在下面这个方法中会带上launchOptions这个参数,如果实现了application:didReceiveRemoteNotification:fetchCompletionHandler:这个方法,则还会调用这个方法

注:didReceiveRemoteNotification指以下两个方法。两个方法互斥。在两方法都实现的情况下方法2优先级高

1. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo

2. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler


iOS10使用时

1 . 如果应用处于 (1) 状态 , 会发出声音 , 会直接调用appDelegate的代理方法userNotificationCenter:willPresentNotification:withCompletionHandler

2 . 如果应用处于 (2) 状态 , 则会发出提示音, 点击推送消息 , 则会调用appDelegate的代理方法

userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler

3 . 如果应用处于 (3) 状态,则会发出提示音 , 点击推送消息 , 则会开启应用 , 在下面这个方法中会带上launchOptions这个参数,如果实现了userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler这个方法,则还会调用这个方法



2. 静默推送及app的状态切换

        在大多数情况下,启动一个app后都是进入前台,比如我们点击应用图标或点推送通知来启动应用。其实app在某些后台事件和特定条件下是可以直接启动到后台(launch into the background)的。

    2.1 应用状态之一Suspended

        这种状态其实和Background类似,而且从用户角度讲应用现在看起来确实是在“后台”,但它和Background状态不同的是Suspended下已经不能执行代码了。应用何时会进Suspended就是玄学了,这是由iOS系统自动控制的,而且不会有任何回调,可以看到UIApplicationDelegate里并没有像applicationWillBecomeSuspended:这种东西。这种状态下的应用虽然还在内存中,但是一旦设备内存吃尽,比如开了炉石传说的游戏,那么系统就会优先干掉(文档上用的是purge这个词)处于Suspended状态的应用,而且也不会有回调。

    2.2 应用启动到前台的生命周期(以点击应用图标开始)

    AppDelegate中走的回调方法 

 · application:willFinishLaunchingWithOptions:

· application:didFinishLaunchingWithOptions:

· applicationDidBecomeActive:


    静默推送可以使应用启动到后台

        前提是应用先被退到后台,过一段时间被系统移入Suspended状态,然后又被系统在内存吃紧时回收了内存(相当于应用已经被系统正当杀掉,而非用户双击Home键杀掉),在这以后,该应用收到静默推送即会启动应用到后台。

    AppDelegate中走的回调方法变为

 · application:willFinishLaunchingWithOptions:

· application:didFinishLaunchingWithOptions:

· applicationDidEnterBackground:


        这个过程中,系统不会显示应用的window,就是说我们不会看到手机屏幕上突然鬼畜一下应用启动,但是应用的第一屏会被加载和渲染,比如你的window.rootViewController是一个TabBarController,那么它及其默认选中的selectedViewController都会被加载和渲染。这是因为系统认为在后台执行完任务后可能会有UI上的更新,所以在applicationDidEnterBackground:方法执行结束后便会有个快速的截图,来更新用户双击Home时看到的那个应用截图。


3. 收到静默推送时的后续该如何处理。

        application:didReceiveRemoteNotification:fetchCompletionHandler:

        这是应用收到静默推送的回调方法,我们最多有30s的时间来处理数据,比如静默推送表示某个列表或资源有更新,你可以在此处下载数据,在下载处理完数据后需要尽快调用completionHandler(...)告诉系统处理完毕。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

[Downloader fetchData:^(id x){ // 处理数据,更新UI 等

completionHandler(UIBackgroundFetchResultNewData);

}];

}


        如果这次是启动到后台的情况,调用completionHandler(...)后会使应用马上进入之前的状态。那就有可能遇到这样的问题:很多时候我们需要在启动时发送一堆业务上的API请求,如果这次静默推送没有数据需要下载和处理,就会刚把启动处的API请求发出,就调用了completionHandler(...),导致发出的这些请求在下次打开应用时显示超时。这种情况下我们可以强行延时下completionHandler(...)的调用,来保证能在这次收到那些API的返回。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

completionHandler(UIBackgroundFetchResultNoData);

});



4. 静默推送


应用想收到静默推送需要满足的条件:

1.应用在前台/后台 (应用被杀死就收不到了)

2.应用实现了

application:didReceiveRemoteNotification:fetchCompletionHandler:/application:didReceiveRemoteNotification:

3. 消息定义时需设置:"content-available" = 1

流程:

  1. 移动端注册消息,向APNs服务器获取deviceToken,并提交给后台保存;

  2. 后台定义消息,并推送给APNs服务器。APNs根据deviceToken做分发。

  3. 移动端收到推送消息后的逻辑处理。

消息定义示例:

特殊说明:

1. APNS去掉alert、badge、sound字段实现静默推送,增加增加字段"content-available":1,也可以在后台做一些事情。

//静默推送消息格式

{

"aps":{

"alert":"",

"content-available":1

},

"userInfo":"test"

}


*/

小结:

1.应用在后台/前台/被杀死,都可以收到普通的远程推送

2.应用在后台/前台时,可以通过静默推送,修改一些数据

3.应用被杀死时(相当于应用已经被系统正当杀掉,而非用户双击Home键杀掉),可以通过Background Fetch短时间唤醒应用



作者:Aliv丶Zz
链接:https://www.jianshu.com/p/0275d9a9592b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册