IOS的后台运行

来源:互联网 发布:临沂php招聘 编辑:程序博客网 时间:2024/04/30 09:18


写在前面给大家推荐一个不错的网站  www.joblai.com


本文章由央广传媒开发部冯宝瑞整理,哈哈

http://www.cocoachina.com/bbs/read.php?tid=149564

文一  

我从苹果文档中得知,一般的应用在进入后台的时候可以获取一定时间来运行相关任务,也就是说可以在后台运行一小段时间。  
还有三种类型的可以运行在后以,  
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];  
 
 
 

http://m2.img.libdd.com/farm3/0/BB676FA305DE3B6020F0152F253B0B00_220_300.JPEG 


我们知道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秒钟,但我不确定,可能是我的试验不够精确。 


文章来源www.joblai.com

1 1