後臺推送通知(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也是能上傳成功。這裏與官方文檔說明有點不一致。

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