cocoa_chen

Remote Notification

2017-08-01

本内容是静默推送的技术调研内容以及相关的应用场景讨论

项目配置

Xcode的项目配置中切换到Capablities选项,打开PushNotifications开关来允许推送,打开Background Modes开关并勾选Remote notifications来支持静默推送功能,同时勾选Location updates来允许后台读取位置信息。

在AppDelegate中实现application:didReceiveRemoteNotification:fetchCompletionHandler:方法,如果同时也实现了application:didReceiveRemoteNotification:方法的话,当Remote Notification到来时,该方法不会执行,而是会调用application:didReceiveRemoteNotification:fetchCompletionHandler:,所以可能需要将application:didReceiveRemoteNotification:方法的代码逻辑迁移过去。

Payload设置

推送的Payload的aps字段中可包含alertbadgesound以及content-available字段信息。其中content-available是静默推送的关键字段,将该值设置为1即可启用静默推送,禁用的话只需从Payload中移除该字段。如果想达到不提示用户的目的,将alertbadgesound字段删掉即可,同时添加自定义的key。如{"aps":{"content-available":1,"type":"0"}}就是个简单的静默推送的Payload,且不会在界面上有什么提示。

Details

以下是Payload包含content-available字段且为1时的情况(不打扰用户删掉alert,sound,badge字段)

  • 当App在前台(Foreground)状态时,该状态可执行代码,会直接调用application:didReceiveRemoteNotification:fetchCompletionHandler:,可从userInfo字段中读取出Payload信息
  • 当App在后台(Background)状态时,该状态可执行代码,会调用application:didReceiveRemoteNotification:fetchCompletionHandler:方法
  • 当App在挂起(Suspended)状态时,该状态不会执行代码。当收到静默推送时,系统会自动启用App将状态切换到Background,并开始调用application:didReceiveRemoteNotification:fetchCompletionHandler:方法
  • 当App在杀死(Not Running)状态时,即用户双击Home键并强制杀死App,收到静默推送时,系统并不会执行任何回调。在这种情况下,用户需要重新打开App或者重启手机来让系统在下次接收到静默推送时能成功唤起App。

当处理完Remote Notification的逻辑时,需要及时调用application:didReceiveRemoteNotification:fetchCompletionHandler:方法的completionHandler来标识是否有新数据或者失败了(如获取到新数据的代码为completionHandler(UIBackgroundFetchResultNewData)),否则系统就会终止App。App有最多30秒的时间来处理推送并且调用completionHandler,最好是在处理完推送内容时就及时调用handler代码块。同时系统会跟踪App在处理推送的后台任务中所消耗的运行时间(elapsed time),电量消耗(power usage)数据成本(data costs),如果App在处理Remote Notifications中消耗了大量的电量,那么在收到静默推送时系统可能不会永远都及时唤醒App来响应事件。当推送频率超过一定限制后,Apple会将带有content-available标志的推送阻塞,以保证用户设备不被频繁唤醒。按照Apple的说法,这个频率在一小时内个位数次的推送的话不会有太大问题。

应用场景

1.网络请求:可正常执行,超时时间至多30秒,用NSURLSession代码实测有效

2.位置访问:需要在Capablities中的Background Modes勾选Location updates,同时位置服务是可用的,可用[CLLocationManager locationServicesEnabled]判断,并且iOS8之后需要有位置的kCLAuthorizationStatusAuthorizedAlways访问权限,以确保应用在后台也可以访问位置信息。如果用户禁用了手机或者App的后台应用刷新,也并不能在后台获取到位置。因为在iOS9之后的allowsBackgroundLocationUpdates字段默认为NO,所以也需要在调用startUpdatingLocation时将allowsBackgroundLocationUpdates置为YES。位置访问最长时间也是30秒。

3.TTS:代码测试前后台皆可播放。当在后台播放时需要在Capablities中的Background Modes勾选Audio,AirPlay,and Picture inPicture选项,当勾选该选项时,需要在App审核时填写该后台播放场景的入口,否则会被Apple审核人员禁止通过。当不勾选语音后台播放选项时,前台可正常播放,后台时会出现不能唤醒播放的问题

4.音频播放:代码测试前后台都可播放,当在后台播放时需要在Capablities中的Background Modes勾选Audio,AirPlay,and Picture inPicture选项,而且需要在App审核时填写该后台场景的入口,否则Apple审核人员可能会禁止审核通过。

5.本地推送弹窗:可以执行,代码测试可正常显示弹窗。

备注

当用户禁用手机的后台应用刷新功能或者禁用App的后台应用刷新时,并不会收到Remote Notification,故相关代码逻辑也不会执行。可在代码中调用[UIApplication sharedApplication].backgroundRefreshStatus来获取当前App的后台刷新状态,如果该值为UIBackgroundRefreshStatusAvailable时可正常收到Remote Notification,否则会收不到推送内容。在iPhone上,如果手机进入低电量模式,后台应用刷新会自动停用,且无法手动打开,只能通过将设置->电池->低电量模式关闭才可让系统自动恢复上次后台应用刷新状态。

总结

  • 在Payload的aps字段中添加content-available并设置为1可启用静默推送
  • 用户强制杀死App时(双击Home键关闭),系统不会唤醒App,需要用户重新打开App或者重启手机
  • 当系统或者App的后台应用刷新功能被禁用时,收到静默推送时App也不会被唤醒并接收到回调。当手机进入低电量模式时,系统会自动禁用后台应用刷新功能
  • 静默推送唤醒App后,在后台的最长处理时间为30秒,所以需要及时调用completionHandler来告诉系统处理的结果
  • 后台访问位置服务时需要授权kCLAuthorizationStatusAuthorizedAlways使用权限以确保后台也可访问位置,如果此时App处于后台,系统会弹窗提示用户授权。iOS9之后在调用startUpdatingLocation时将allowsBackgroundLocationUpdates置为YES
  • 当需要在后台播放音频或者TTS时,需要在Capablities中的Background Modes勾选Audio,AirPlay,and Picture inPicture选项,并且在App审核内容处填写后台播放的场景入口以便Apple审核人员复现,否则可能会被拒绝App新版本通过
Tags: iOS
使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章