写在前面给大家推荐一个不错的站点 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
声明:此文一部分来自网络,一部分来自官方文档(翻译),另一部分是作者的总结
文五
后台执行被第一次提到
文六
后台执行官方文档
在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程序须要定期被唤醒去检查它的服务。
为了easy实现这个行为。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不是真正的多任务系统,在用户按下Homebutton后,全部应用程序都会进入后台状态,而且大部分都会迅速进入暂停状态。应用程序的全部工作内存都在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秒的运行时间。而一些须要在后台下载或者与server保持连接的App是怎样突破600秒的限制的呢?像网易公开课就能够在后台持续下载。优酷也
“”
阅读器
iOS
我们知道iOS开启后台任务后能够获得最多600秒的执行时间。而一些须要在后台下载或者与server保持连接的App是怎样突破600秒的限制的呢?像网易公开课就能够在后台持续下载,优酷也能够在后台持续缓存。这是怎么做到的呢?一般来说。要实现iOS长时间后台执行,须要声明VOIP、Audio或GPS。
Audiosession
实现方法非常easy。就是在后台一直播放一个无声的音乐文件。这样就相当于声明了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由于受系统控制而不在此列。我的观察是,每次有新的数据来暂时,程序会被唤醒并执行大约几秒钟,然后再次进入休眠。
Stackoverflow上的说法是10秒钟,但我不确定,可能是我的试验不够精确。