本内容是静默推送的技术调研内容以及相关的应用场景讨论
项目配置
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字段中可包含alert
、badge
、sound
以及content-available
字段信息。其中content-available
是静默推送的关键字段,将该值设置为1
即可启用静默推送,禁用的话只需从Payload中移除该字段。如果想达到不提示用户的目的,将alert
、badge
和sound
字段删掉即可,同时添加自定义的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新版本通过
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章