IOS的後台運行
文一
我從蘋果文檔中得知,一般的應用在進入背景時候可以擷取一定時間來運行相關任務,也就是說可以在後台運行一小段時間。
還有三種類型的可以運行在後以,
1.音樂
2.location
3.voip
文二
在IOS後台執行是本文要介紹的內容,大多數應用程式進入後台狀態不久後轉入暫停狀態。在這種狀態下,應用程式不執行任何代碼,並有可能在任意時候從記憶體中刪除。應用程式提供特定的服務,使用者可以請求後台執行時間,以提供這些服務。
判斷是否支援多線程
UIDevice* device = [UIDevice currentDevice];
BOOL backgroundSupported = NO;
if ([device respondsToSelector:@selector(isMultitaskingSupported)])
backgroundSupported = device.multitaskingSupported;
聲明你需要的背景工作
Info.plist中添加UIBackgroundModes索引值,它包含一個或多個string的值,包括
audio:在後台提供聲音播放功能,包括音頻流和播放視頻時的聲音
location:在後台可以保持使用者的位置資訊
voip:在後台使用VOIP功能
前面的每個value讓系統知道你的應用程式應該在適當的時候被喚醒。例如,一個應用程式,開始播放音樂,然後移動到後台仍然需要執行時間,以填補音訊輸出緩衝區。添加audio鍵用來告訴系統架構,需要繼續播放音頻,並且可以在合適的時間間隔下回調應用程式;如果應用程式不包括此項,任何音頻播放在移到後台後將停止運行。
除了添加索引值的方法,IOS還提供了兩種途徑使應用程式在後台工作:
Task completion—應用程式可以向系統申請額外的時間去完成給定的任務
Local notifications—應用程式可以預先安排時間執行local notifications 傳遞
文三
如何讓程式後台播放音樂
http://developer.apple.com/library/ios/#qa/qa1668/_index.html
文四
如果你的應用程式需要後台運行,可以使用以下方法:
1。應用程式可以請求一個有限的時間內完成一些重要任務。
2。應用程式可以聲明為支援特定服務需要定期後台執行時間。
3。應用程式可以使用本地產生使用者在指定的時間的警報,應用程式正在運行與否的通知。
原文地址:http://blog.csdn.net/diyagoanyhacker/article/details/7071055
作者:禚來強
聲明:此文一部分來自網路,一部分來自官方文檔(翻譯),還有一部分是作者的總結
文五
後台運行被第一次提到
http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS4.html#//apple_ref/doc/uid/TP40009559-SW1
文六
後台運行官方文檔
http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW3
在IOS後台執行是本文要介紹的內容,大多數應用程式進入後台狀態不久後轉入暫停狀態。在這種狀態下,應用程式不執行任何代碼,並有可能在任意時候從記憶體中刪除。應用程式提供特定的服務,使用者可以請求後台執行時間,以提供這些服務。
判斷是否支援多線程
UIDevice* device = [UIDevice currentDevice];
BOOL backgroundSupported = NO;
if ([device respondsToSelector:@selector(isMultitaskingSupported)])
backgroundSupported = device.multitaskingSupported;
聲明你需要的背景工作
Info.plist中添加UIBackgroundModes索引值,它包含一個或多個string的值,包括
audio:在後台提供聲音播放功能,包括音頻流和播放視頻時的聲音
location:在後台可以保持使用者的位置資訊
voip:在後台使用VOIP功能
前面的每個value讓系統知道你的應用程式應該在適當的時候被喚醒。例如,一個應用程式,開始播放音樂,然後移動到後台仍然需要執行時間,以填補音訊輸出緩衝區。添加audio鍵用來告訴系統架構,需要繼續播放音頻,並且可以在合適的時間間隔下回調應用程式;如果應用程式不包括此項,任何音頻播放在移到後台後將停止運行。
除了添加索引值的方法,IOS還提供了兩種途徑使應用程式在後台工作:
Task completion—應用程式可以向系統申請額外的時間去完成給定的任務
Local notifications—應用程式可以預先安排時間執行local notifications 傳遞
實現長時間的背景工作
應用程式可以請求在後台運行以實現特殊的服務。這些應用程式並不連續的運行,但是會被系統架構在合適的時間喚醒,以實現這些服務
1、 追蹤使用者位置:略
2、在背景播放音頻:
添加UIBackgroundModes中audio值,註冊後台音頻應用。這個值使得應用程式可以在後台使用可聽的背景,如音樂播放或者音頻流應用。對於支援音頻和視頻功能的應用程式也可以添加該值以保證可以繼續持續的運行流。
當audio值設定後,當你的應用程式進入後台後,系統的多媒體架構會自動阻止它被掛斷,但是,如果應用程式停止播放音頻或者視頻,系統將掛斷應用程式。
當你的應用程式在後台時,你可以執行任意的系統音頻架構去初始化後台音頻。你的應用程式在後台時應該限制自身,使其執行與工作相關的代碼,不能執行任何與播放內容無關的任務
由於有多個應用程式支援音頻,前台的應用程式始終允許播放音頻,背景應用程式也被允許播放一些音頻內容,這取決於audio session object的設定。應用程式應該始終設定它們的audio session object,並小心的處理其他類型的音頻相關notifications和中斷。詳見audio session programming guide。
3、實現VOIP應用:
VOIP程式需要穩定的網路去串連和它相關的服務,這樣它才能接到來電和其他相關的資料。系統允許VOIP程式被掛斷並提供組件去監聽它們的sockets,而不是在任意時候都處於喚醒狀態。設定VOIP應用程式如下:
A、 添加UIBackgroundModes中的VOIP索引值
B、 為VOIP設定一個應用程式socket
C、 在移出後台之前,調用setKeepAliveTimeout:handler:方法去建立一個定期執行的handler,你的應用程式可以運行這個handler來保持服務的串連。
D、 設定你的audio session去處理這種切換
釋義:
A、大多數VOIP應用需要設定後台audio 應用去傳遞音頻,因此你應該設定audio 和voip兩個索引值。
B、為了使應用程式在後台時保持穩定的串連,你必須tag你的主通訊socket專門應用於VOIP,tagging這個socket來告訴系統,它必須在你的應用程式中斷時接管這個socket。這個切換本身對於你的應用程式時透明的,當新的資料到達socket的時候,系統會喚醒應用程式,並將socket的控制權返回給應用程式,這樣應用程式就可以處理新來的資料。
你只需要tag用於voip服務的socket,這個socket用來接收來電或者其他相關的資料來保持你的VOIP服務的串連。根據收到的資訊,這個socket要決定下一步的動作。比如一個來電,你會想彈出一個本地的通知來告知使用者;對於其他不是那麼關鍵的資料,你可能會想悄悄的處理這些資料並讓系統將應用程式重新中斷。
在IOS中,sockets是用流或者更進階的結構,設定一個VOIP的socket,你只需要在通常的設定中添加一個特殊的key來標明這個介面是用於串連VOIP服務的,下表列出了流的介面和設定:
設定流介面用於voip
介面
設定
NSInputStream 和NSOutputStream
對於 Cocoa streams, 使用 setProperty:forKey: 方法添加
NSStreamNetworkServiceType
屬性給
stream.
改屬性的值設為
NSStreamNetworkServiceTypeVoIP.
NSURLRequest
對於 URL loading system, 使用 setNetworkServiceType:
method of your NSMutableURLRequest object to set the network service
type of the request. The service type should be set to
NSURLNetworkServiceTypeVoIP.
CFReadStreamRef和CFWriteStreamRef
For Core Foundation streams, use the CFReadStreamSetProperty or
CFWriteStreamSetProperty function to add the kCFStreamNetwork-
ServiceType property to the stream. The value for this property should be
set to kCFStreamNetworkServiceTypeVoIP.
(注意:當設定socket的時候,你需要在你的主訊號通道中設定合適的service type key。當設定聲道時,不需要設定這個key)
由於,VOIP應用程式需要一直運行以確保收到來電,所以如果程式通過一個非零的exit code退出,系統將自動重啟這個應用程式(這種退出方式可以發生在記憶體壓力大時終止程式運行)。儘管如此,中斷應用程式會release所有的sockets,包括那個用於串連voip 服務的socket。因此,當程式運行時,它需要一直從頭建立socket。
C、 為了防止斷連,voip程式需要定期被喚醒去檢查它的服務。為了容易實現這個行為,IOS通過使用(UIApplication setKeepAliveTimeout:handler:)方法建立一個特殊的控制代碼。你可以在applicationDidEnterBackground方法中建立該控制代碼。一旦建立,系統至少會在逾時之前調用該控制代碼一次,來喚醒你的應用程式。
這個keep-alive handler在後台執行,必須儘快的返回參數,它有最多30秒的時間來執行所需的任務,如果這段時間內控制代碼沒有返回,那麼系統將終止應用程式。
當你建立了handler之後,確定應用程式所需的最大逾時。系統保證會在最大逾時之前調用handler,但是這個時間是不確定的,所以你的handler必須在你申明的逾時之前做好執行程式的準備。
D、設定audio session,詳見Audio Session Programming Guide.
在後台完成有限長度的任務
在被終止之前的任意時間,應用程式會調用beginBackgroundTaskWithExpirationHandler:方法讓系統給出額外的時間來完成一些需要在後台長時間執行的任務。(UIApplication的backgroundTimeRemaining屬性包含程式啟動並執行總時間)
可以使用task completion去保證那些比較重要但是需要長時間啟動並執行程式不會由於使用者切入後台而突然關閉。比如,你可以用這項功能來將使用者的資訊儲存到disk上或者從網路下載一個重要的檔案。有兩種方式來初始化這樣的任務:
1、將長時間啟動並執行重要任務用beginBackgroundTaskWithExpirationHandler:和endBackgroundTask:封裝。這樣就在程式突然切入背景時候保護了這些任務不被中斷。
2、當你的應用程式委託applicationDidEnterBackground:方法被調用時再啟動任務
中的兩個方法必須是一一對應的,endBackgroundTask:方法告訴系統任務已經完成,程式在此時可以被終止。由於應用程式只有有限的時間去完成背景工作,你必須在逾時或系統將要終止這個程式之前調用這個方法。為了避免被終止,你也可以在一個任務開始的時候提供一個expiration handler和endBackgroundTask:方法。(可以查看backgroundTimeRemaining屬性來確定還剩多少時間)。
一個程式可以同時提供多個任務,每當你啟動一個任務的時候,beginBackgroundTaskWithExpirationHandler:方法將返回一個獨一無二的handler去識別這個任務。你必須在endBackgroundTask:方法中傳遞相同的handler來終止該任務。
Listing 4-2 Starting a background task at quit time
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication* app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^{
// Do the work associated with the task.
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
上述例子中,bgTask變數是一個類的成員變數,儲存著指向該背景工作標示的指標。
在expriation handler中,可以添加關閉任務所需的代碼。儘管如此,加入的代碼不能執行太長的時間,當expriation handler被調用的時候,該程式已經非常接近被關閉,所以只有極短的時間來清除狀態資訊並終止任務。
安排Local Notification的傳遞
UILocalNotification類提供了一種方法來傳遞local notifications。和push notifications需要設定remote server不同,local notifications 在程式中安排並在當前的裝置上執行。滿足如下條件可以使用該能力:
1、一個基於時間的程式,可以在將來特定的時間讓程式post 一個alert,比如鬧鐘
2、一個在後台啟動並執行程式,post 一個local notification去引起使用者的注意
為了安排local notification 的傳遞,需要建立一個UILocalNotification的執行個體,並設定它,使用UIApplication類方法來安排它。Local notification對象包含了所要傳遞的類型(sound,alert,或者badge)和時間何時呈現) 。UIApplication類方法提供選項去確定是立即傳遞還是在指定的時間傳遞。
Listing 4-3 Scheduling an alarm notification
- (void)scheduleAlarmForDate:(NSDate*)theDate
{
UIApplication* app = [UIApplication sharedApplication];
NSArray* oldNotifications = [app scheduledLocalNotifications];
// Clear out the old notification before scheduling a new one.
if ([oldNotifications count] > 0)
[app cancelAllLocalNotifications];
// Create a new notification.
UILocalNotification* alarm = [[[UILocalNotification alloc] init] autorelease];
if (alarm)
{
alarm.fireDate = theDate;
alarm.timeZone = [NSTimeZone defaultTimeZone];
alarm.repeatInterval = 0;
alarm.soundName = @alarmsound.caf;
alarm.alertBody = @Time to wake up!;
[app scheduleLocalNotification:alarm];
}
}
(可以最多包含128個 local notifications active at any given time, any of which can be configured to repeat at a specified interval.)如果在調用該notification的時候,程式已經處於前台,那麼application:didReceiveLocalNotification:方法將取而代之。
小結:關於詳解在IOS後台執行的內容介紹完了,希望本文對你有所協助!
文七
iOS不是真正的多任務系統,在使用者按下Home按鈕後,所有應用程式都會進入後台狀態,並且大部分都會迅速進入暫停狀態,應用程式的所有工作記憶體都在RAM中,在暫停時它完全不執行。因此,切換回這樣的應用程式非常快。但是如果系統需要更多的記憶體給當前處於活動狀態的應用程式,就有可能終結暫停狀態的應用程式,它們的記憶體也將被釋放。
一方面,應用程式在進入後台狀態時,需要釋放一些資源,使自身的暫停快照更小,從而減少從RAM中清除的風險,另一方面,為了避免被終結而丟失使用者的資料,需要在使用者離開時儲存他們的進度資訊,這些工作,需要在5秒鐘內完成,不然會被系統認定有異常被強制退出。可能通過接收應用程式發送的通知(UIApplicationDidEnterBackgroundNotification)來觸發處理,如果在處理代碼中加上下面這條語句則必然會導致異常退出:
view plain
[NSThread sleepForTimeInterval:10];
可以通過一種方法來請求更多後台時間來避免此問題。假設接收通知而觸發的處理方法是applicationDidEnterBackground:
view plain
-(void)applicationDidEnterBackground{
NSLog(@%@,NSStringFromSelector(_cmd));
//得到當前應用程式的UIApplication對象
UIApplication *app = [UIApplication sharedApplication];
//一個背景工作標識符
UIBackgroundTaskIdentifier taskID;
taskID = [app beginBackgroundTaskWithExpirationHandler:^{
//如果系統覺得我們還是運行了太久,將執行這個程式塊,並停止運行應用程式
[app endBackgroundTask:taskID];
}];
//UIBackgroundTaskInvalid表示系統沒有為我們提供額外的時候
if (taskID == UIBackgroundTaskInvalid) {
NSLog(@Failed to start background task!);
return;
}
NSLog(@Starting background task with %f seconds remaining, app.backgroundTimeRemaining);
[NSThread sleepForTimeInterval:10];
NSLog(@Finishing background task with %f seconds remaining,app.backgroundTimeRemaining);
//告訴系統我們完成了
[app endBackgroundTask:taskID];
}
我們知道iOS開啟背景工作後可以獲得最多600秒的執行時間,而一些需要在後台下載或者與伺服器保持串連的App是如何突破600秒的限制的呢?像網易公開課就可以在後台持續下載,優酷也
“”
閱讀器
iOS
我們知道iOS開啟背景工作後可以獲得最多600秒的執行時間,而一些需要在後台下載或者與伺服器保持串連的App是如何突破600秒的限制的呢?像網易公開課就可以在後台持續下載,優酷也可以在後台持續緩衝,這是怎麼做到的呢?一般來說,要實現iOS長時間後台運行,需要聲明VOIP、Audio或GPS。
Audiosession
實現方法很簡單,就是在後台一直播放一個無聲的音樂檔案,這樣就相當於聲明了Audio,就可以輕鬆突破600秒的限制了。
通過播放“靜默”音讓程式在後台執行的做法(即在audiounit回呼函數中使用kAudioUnitRenderAction_OutputIsSilence標誌位),雖然確實可以實現後台執行,但實踐中限制很多。最大的問題就在於程式的audiosession不能被打斷。當程式執行在後台時,只要另一個程式使用kAudioSessionCategory_RecordAndPlay(比如Skype)或者kAudioSessionCategory_SoloAmbientSound(印象中使用這個session的不多),那麼本程式就會被立即打斷。
打斷本身不是問題,但當播放程式被打斷時,唯一能夠獲得的只有處理audiosessioninterruption的很短一段時間。我的實驗測試大概是3到5秒,但因為程式隨後立即暫停,無法掛調試器,所以很難準確估計,然後程式就會被立即轉入休眠狀態。這點時間和applicationDidEnterBackground回呼函數所用的時間大體相當,但是因為這個打斷中間還伴隨一個播音的回調動作,程式結構不是很好組織,在很多情況下是不夠做現場儲存工作的。
不推薦播放“靜默”音的另一個問題它的恢複播放需要的情境非常麻煩。比如當一個iOS程式在後台被VOIP喚醒時,它是不能直接獲得audiounit重新開始播音的。如果此時調用AudioOutputUnitStart(),會返回一個錯誤碼,哪怕前台沒有任何一個程式在運行也是如此。此時你不可能讓程式重新進入穩定運行狀態。有些沒經驗的程式員喜歡利用audiosessioninterruptionhandler做所謂的自動播放恢複,但他們其實都沒有注意到audiosessioninterruption的狀態恢複回調並不會保證被調用。目前實測能自動回復調用的,大概也就只有內建的電話撥號程式,以及一些非常特殊的情境(比如你用一個MP3播放器打斷audiosession,然後殺掉MP3播放器進程,然後把被打斷的程式重新置回前台)。這樣經常導致的結果,就是你開心地發現程式沒問題,然後在放進生產環境中發現各種時不時的崩潰或啟動失敗。
VOIPsocket
VOIPSocket可以在後台運行。當程式進入後台時,事實上整個程式被暫停運行,但VOIPsocket因為受系統控制而不在此列。我的觀察是,每次有新的資料來臨時,程式會被喚醒並執行大約幾秒鐘,然後再次進入休眠。Stackoverflow上的說法是10秒鐘,但我不確定,可能是我的實驗不夠精確。