文一
我從蘋果文檔中得知,一般的應用在進入後台的時候可以獲取一定時間來運行相關任務,也就是說可以在後台運行一小段時間。
還有三種類型的可以運行在後以,
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秒鐘,但我不確定,可能是我的試驗不夠精確。