1. 程式人生 > >四種後臺模式push notification 總結(另附送極光推送)

四種後臺模式push notification 總結(另附送極光推送)

iOS 7 中, app 有四種後臺執行模式 ,對應蘋果的後臺介面實現.

1. 無後臺僅推送, 出現在 iOS 3.x 以下大部分系統版本, 表現為 按下 home 鍵就關閉退出,資料有 apple 的推送伺服器傳輸,並不需要應用後臺執行

這樣做,每次退出後,重新進入都需要重新載入,重新請求下載,都需要耗費電量,而且使用者體驗不佳.

2.墓碑式後臺,iOS 4後被大量採用,人稱偽多工,一進入後臺就被凍結,無法操作

3.智慧排程後臺,就是 iOS 新增的 background fetch ,這個後臺,會智慧根據使用者行為自動調整到效率最優的後臺模式,能夠處理不是很有時效性的資訊獲取background fetch 能夠在後臺提前 fetch 到 推送 ,並在 後臺執行這個回撥方法.

iOS系統便會根據應用啟動頻率、時間和當前網路和電量的狀況來智慧分配每個應用的後臺獲取頻率和啟動時長。

//通過極光推送的兩張圖,來比對一下 iOS 7 下多工的優勢


iOS 7 中的後臺 fetch 部分


最後是後臺的靜默推送部分

推送訊息攜帶 content-available: 1 是Background 執行的必須引數,如果不攜帶此欄位則與iOS7 之前版本的普通推送一樣。


4. 真後臺機制:

1、Background Audio,這是後臺的音訊,這個很早之前便有,也是iOS裝置中用得最多的後臺應用,呼叫這個介面可以實現後臺的音樂播放。

2、Location Services,這是後臺的定位,系統會擁有統一頁面進行管理。

3、VoIP,後臺語音服務,類似Skype通話應用需要呼叫,可進行後臺的語音通話。

4、Newsstand,報刊雜誌後臺自動下載更新,其能夠自動實時更新。

5、Background Task  Completion,這個介面早在iOS 4時候便擁有,其可以供任意型別的APP使用,不過在舊系統中,這個介面的後臺限制執行時間僅為10分鐘,意味著當應用退至後臺,其後臺執行僅能持續10 分鐘便會轉至休眠狀態。iOS 7中對這個介面作出了改變,原來的為連續10分鐘,即不論你這10分鐘內使用者是否關閉螢幕進入休眠狀態,應用仍然會在後臺等待10分鐘完結後推出,而新的 改進為假如遇到關閉螢幕休眠的情況,這後臺執行的10分鐘便會跟隨一同休眠,剩餘的後臺時間將會留待使用者再一次喚醒裝置才計算。這樣後臺執行的時間仍然為 10分鐘,但並不連續,這樣做的優點為省電。

如現在有一些詞典應用帶有後臺複製選詞功能,實際上其是利用了這個介面,如果使用者開啟詞典後並推出,即使螢幕關閉,但詞典仍然在後臺執行,電量消耗還是比較大的,在iOS 7上,這個問題可以得到解決。

6、 Remote Notification,這是本次較大的一個改進介面,以往聊天類應用接受推送後點進去需要再收一次資訊,這情況在QQ、微信等應用上最為明顯。不過擁有了這個介面後,這情況將不復存在,以後推送將能夠直接啟動後臺任務。值得注意的是remote notification支援silent notification(靜默推送),這樣dropbox這類同步應用可以在後臺以最節能的模式實時靜默同步了,類似布卡漫畫這種也可以推送正在追的漫 畫的新章節並在後臺靜默下載,待到下載好再給使用者傳送一個本地推送,使用者點開即看無需再聯網

7、Background Transfer Service,後臺上傳下載。iOS最接近傳統多工的後臺介面,可供任意型別的app呼叫,無時間限制。應用場景包括後臺上傳和下載資料,這使得遊戲後臺更新資料包,後臺上傳視訊等等都成為可能,但是正如其名字,它只能用於處理上傳下載這種傳輸類的任務,類似後臺剪下板監控這種它就無能為力了。

//以下部分為轉載總結

著重講一下 Remote notification 中的問題

ios 7中的變化


iOS7中,後臺任務的處理方式發生了改變。系統將在使用者鎖屏後儘快讓裝置進入休眠狀態,以節省電力,這時後臺任務是被暫停的。之後在裝置在特定時間進行系統應用的操作被喚醒(比如檢查郵件或者接到來電等)時,之前暫停的後臺任務將一起進行。就是說,系統不會專門為第三方的應用保持裝置處於活動狀態。

可以看到 iOS 7 ,有一個所謂的心跳機會,特定的系統級應用的操作時,暫停的後臺任務一起進行;這樣做延長電池的續航時間, 帶來更好的使用者體驗

實現後臺獲取程式碼並通知系統

在完成了前兩步後,只需要在AppDelegate裡實現-application:performFetchWithCompletionHandler:就行了。系統將會在執行fetch的時候呼叫這個方法,然後開發者需要做的是在這個方法裡完成獲取的工作,然後重新整理UI,並通知系統獲取結束,以便系統儘快回到休眠狀態。獲取資料這是應用相關的內容,在此不做贅述,應用在前臺能完成的工作在這裡都能做,唯一的限制是系統不會給你很長時間來做fetch,一般會小於一分鐘,而且fetch在絕大多數情況下將和別的應用共用網路連線。這些時間對於fetch一些簡單資料來說是足夠的了,比如微博的新條目(大圖除外),接下來一小時的天氣情況等。如果涉及到較大檔案的傳輸的話,用後臺獲取的API就不合適了,而應該使用另一個新的檔案傳輸的API,我們稍後再說。類似前面提到的後臺任務完成時必須通知系統一樣,在在獲取完成後,也必須通知系統獲取完成,方法是呼叫-application:performFetchWithCompletionHandler:的handler。這個CompletionHandler接收一個UIBackgroundFetchResult作為引數,可供選擇的結果有UIBackgroundFetchResultNewData,UIBackgroundFetchResultNoData,UIBackgroundFetchResultFailed三種,分別表示獲取到了新資料(此時系統將對現在的UI狀態截圖並更新App Switcher中你的應用的截圖),沒有新資料,以及獲取失敗。寫一個簡單的例子吧:

<span class="line-number" style="margin: 0px; padding: 0px;">1</span>
<span class="line-number" style="margin: 0px; padding: 0px;">2</span>
<span class="line-number" style="margin: 0px; padding: 0px;">3</span>
<span class="line-number" style="margin: 0px; padding: 0px;">4</span>
<span class="line-number" style="margin: 0px; padding: 0px;">5</span>
<span class="line-number" style="margin: 0px; padding: 0px;">6</span>
<span class="line-number" style="margin: 0px; padding: 0px;">7</span>
<span class="line-number" style="margin: 0px; padding: 0px;">8</span>
<span class="line-number" style="margin: 0px; padding: 0px;">9</span>
<span class="line-number" style="margin: 0px; padding: 0px;">10</span>
<span class="line-number" style="margin: 0px; padding: 0px;">11</span>
<span class="line-number" style="margin: 0px; padding: 0px;">12</span>
<span class="line-number" style="margin: 0px; padding: 0px;">13</span>
<span class="line-number" style="margin: 0px; padding: 0px;">14</span>
<span class="line-number" style="margin: 0px; padding: 0px;">15</span>
<span class="line-number" style="margin: 0px; padding: 0px;">16</span>
<span class="line-number" style="margin: 0px; padding: 0px;">17</span>
<span class="line-number" style="margin: 0px; padding: 0px;">18</span>
<span class="line-number" style="margin: 0px; padding: 0px;">19</span>
<span class="line-number" style="margin: 0px; padding: 0px;">20</span>
<span class="line-number" style="margin: 0px; padding: 0px;">21</span>
<span class="line-number" style="margin: 0px; padding: 0px;">22</span>
<span class="line-number" style="margin: 0px; padding: 0px;">23</span>
<span class="line-number" style="margin: 0px; padding: 0px;">24</span>
//File: YourAppDelegate.m
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    UINavigationController *navigationController = (UINavigationController*)self.window.rootViewController;
    id fetchViewController = navigationController.topViewController;
    if ([fetchViewController respondsToSelector:@selector(fetchDataResult:)]) {
        [fetchViewController fetchDataResult:^(NSError *error, NSArray *results){
            if (!error) {
              if (results.count != 0) {
                  //Update UI with results.
                  //Tell system all done.
                  completionHandler(UIBackgroundFetchResultNewData);
              } else {
                  completionHandler(UIBackgroundFetchResultNoData);
              }
            } else {
                completionHandler(UIBackgroundFetchResultFailed);
            }
        }];
    } else {
        completionHandler(UIBackgroundFetchResultFailed);
    }
}
後臺任務的傳輸是由 NSURLSession 完成的,包括 iOS 9 中徹底放棄 NSURLConnection ,


可以 看到當 app 處於後臺的時候,配置物件的 discretionary 屬性中會建立 Http 是長連線,非同步下載資料

本文涉及到的WWDC2013 Session有

  • Session 204 What’s New with Multitasking
  • Session 705 What’s New in Foundation Networking

在iOS7之前,系統所接受的應用多工可以大致分為幾種:

  • 後臺完成某些花費時間的特定任務
  • 後臺播放音樂等
  • 位置服務
  • IP電話(VoIP)
  • Newsstand 
iOS 7 之後
改變了後臺任務的執行方式 增加了後臺獲取(Background Fetch) 增加了推送喚醒(靜默推送,Silent Remote Notifications) 增加了後臺傳輸(Background Transfer Service)

一些限制

首先,後臺傳輸只會通過wifi來進行,使用者大概也不會開心蜂窩資料的流量被後臺流量用掉。後臺下載的時間與以前的關閉應用後X分鐘的模式不一樣,而是為了節省電力變為離散式的下載,並與其他後臺任務併發(比如接收郵件等)。另外還需要注意的是,對於下載後的內容不要忘記寫到應用的目錄下(一般來說這種可以重複獲得的內容應該放到cache目錄下),否則如果由於應用完全退出的情況導致沒有儲存到可再次訪問的路徑的話,那可就白做工了。

後臺傳輸非常適合用於檔案,照片或者追加遊戲內容關卡等的下載,如果配合後臺獲取或者靜默推送的話,相信可以完全很多很有趣,並且以前被限制而無法實現的功能。