后台推送通知(Background update notification)

一:后台推送通知功能介绍

后台推送是iOS7新增的功能,通过后台推送可以把客户端App唤醒,唤醒之后App将获得30秒的后台运行时间。注意这里写的是后台时间运行时间,有些方法不支持background mode 运行。

被kill掉的App,在发起静默后是不能被唤醒的。

Tips

application:didReceiveRemoteNotification:fetchCompletionHandler:

Use this method to process incoming remote notifications for your app. Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running in the foreground, the system calls this method when your app is running in the foreground or background. In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.

https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application?language=objc

不能通过不断发送后台推送保持App长时间处于后台时间,每小时能推送的Silent Notification次数有限制;

Tips

Background update notifications are not meant as a way to keep your app awake in the background beyond quick refresh operations, nor are they meant for high priority updates. APNs treats background update notifications as low priority and may throttle their delivery altogether if the total number becomes excessive. The actual limits are dynamic and can change based on conditions, but try not to send more than a few notifications per hour.

https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW8


二:设置后台推送

为了能让App支持后台推送,必须确保apns推送内容的aps字典中包含content-available字段且它的值为1。同时如果该推送有通知用户信息,那么推送内容中也可以添加alert,sound或者badge。反之如果是静默推送更新内容,那么可以不添加这几个字段。

推送内容的aps字典中添加content-available后,还需要在项目工程中background modes 中设置 Remote notifications。如下图:


设置了content-available 以及Remote notifications 之后,那么在Appdelegate的application:didReceiveRemoteNotification:fetchCompletionHandler: 收到后台推送通知。


三:使用后台推送的业务 – 日志上报


产品中有使用后台推送的业务-日志上报。假设用户使用App过程中出现了异常,而开发不能重现,或者产品运营中出现异常,需要捞用户日志进行分析定位,需要获取用户App日志进行分析定位。

这种情况下可以给指定用户下发后台推送让后台运行的App或者休眠中的App上报日志动作,从而无需用户操作配合或者不打扰用户的情况下进行上报日志。


以上的业务场景,归纳起来就是后台网络上报操作,那么涉及的主要类就是 NSURLSession,NSURLSessionDataTask, NSURLSessionUploadTask。

在Session 中的Task行为取决于三件事情:Session类型,Task类型,以及 Task的创建是否在App处于前端发生。

Session的类型

defaultSessionConfiguration 默认的会话行为类似于其他基础网络请求方法。他会通过磁盘对数据和凭证进行存储。

ephemeralSessionConfiguration 该会话不会存在任何数据到磁盘;所有缓存,凭证等等都是在RAM中进行存贮。因为当session无效的时候,数据也被清除。

backgroundSessionConfigurationWithIdentifier: 类似 defaultSessionConfiguration,但是它是在另外独立的进程处理网络数据传输。而且它有一些注意事项。


Task的类型

NSURLSessionDataTask

NSURLSessionUploadTask   支持后台上传数据

NSURLSessionDownloadTask   支持后台下载数据


后台传输注意事项

当使用backgroundSessionConfiguration:初始化configuration对象并且把分配给Session会话后,那么该Session会话就支持后台传输数据。

后台Session会话,因为实际的传输是由一个单独的进程,它与你的App交互相对比较昂贵,因此一些功能不可用,导致以下限制:

1:Session 会话必须是通过delegate 进行回调处理,不能使用block。(使用delegate处理与同一个进程使用方法一致)

2:仅支持http 以及 https协议

3:仅支持从file使用upload task (使用data 对象 或者 stream的方式上传数据会失败)

4:当在后台传输数据的时候,分配给Session的configuration对象的discretionary属性必须是true。(允许后台任务调度系统的自由裁量权的最佳性能)

后台任务完成操作


在切到后台之后,Session的Delegate不会再收到,Task相关的消息,直到所有Task全都完成后,系统会调用ApplicationDelegate的application:handleEventsForBackgroundURLSession:completionHandler:回调,把通知App后台Task已经完成,这里你需要completionHandler的bloack存起来下面会用到,接着每一个后台的Task就会调用Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:和URLSession:task:didCompleteWithError: 。


各个Task在Session的delegate调用之后,最后会调用Session的Delegate回调URLSessionDidFinishEventsForBackgroundURLSession:。这个时候你可以调用上面保存completionHandler的bloack,告知系统你的后台任务已经完成,系统可以安全的休眠你的App。

四:实施过程问题

以下是开发过程总结的问题

1:如果不是background创建的task,如果app处于后台中接受到后台推送,那么该任务将不能保证被完成的执行。

(测试过程中,经常是发送第一次推送,通过抓包看到http被发送成功,但response没能回到回调中。需要发送第二次推送或者把app切换到前台,那么response才能执行delegate回调)

2:处理 Session 以及 Task 不能使用block

3:使用NSURLSessionUploadTask 上传数据的时候,只能使用 uploadTaskWithRequest: fromFile:方法。调用方式是传入request以及file的URL,该方法官方文档说明它会忽略request中bogy(An NSURLRequest object that provides the URL, cache policy, request type, and so on. The body stream and body data in this request object are ignored.)。但是在具体开发过程对于fileURL我传入nil,然后再request中设置body也是能上传成功。这里与官方文档说明有点不一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章