我从苹果文档中得知,通常的应用在进入后台的时候能够获取必定时间来运行相关任务,也就是说能够在后台运行一小段时间。html
还有三种类型的能够运行在后以,
1.音乐
2.location
ios
3.voip网络
在IOS后台执行是本文要介绍的内容,大多数应用程序进入后台状态不久后转入暂停状态。在这种状态下,应用程序不执行任何代码,并有可能在任意时候从内存中删除。应用程序提供特定的服务,用户能够请求后台执行时间,以提供这些服务。session
判断是否支持多线程多线程
UIDevice* device = [UIDevice currentDevice];app
BOOL backgroundSupported = NO;框架
if ([device respondsToSelector:@selector(isMultitaskingSupported)])socket
backgroundSupported = device.multitaskingSupported;async
声明你须要的后台任务ide
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://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 传递
实现长时间的后台任务
应用程序能够请求在后台运行以实现特殊的服务。这些应用程序并不连续的运行,可是会被系统框架在合适的时间唤醒,以实现这些服务
一、 追踪用户位置:略
二、在后台播放音频:
添加UIBackgroundModes中audio值,注册后台音频应用。这个值使得应用程序能够在后台使用可听的背景,如音乐播放或者音频流应用。对于支持音频和视频功能的应用程序也能够添加该值以保证能够继续持续的运行流。
当audio值设置后,当你的应用程序进入后台后,系统的多媒体框架会自动阻止它被挂断,可是,若是应用程序中止播放音频或者视频,系统将挂断应用程序。
当你的应用程序在后台时,你能够执行任意的系统音频框架去初始化后台音频。你的应用程序在后台时应该限制自身,使其执行与工做相关的代码,不能执行任何与播放内容无关的任务
因为有多个应用程序支持音频,前台的应用程序始终容许播放音频,后台的应用程序也被容许播放一些音频内容,这取决于audio session object的设置。应用程序应该始终设置它们的audio session object,并当心的处理其余类型的音频相关notifications和中断。详见audio session programming guide。
三、实现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上或者从网络下载一个重要的文件。有两种方式来初始化这样的任务:
一、将长时间运行的重要任务用beginBackgroundTaskWithExpirationHandler:和endBackgroundTask:包装。这样就在程序忽然切入后台的时候保护了这些任务不被中断。
二、当你的应用程序委托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 在程序中安排并在当前的设备上执行。知足以下条件可使用该能力:
一、一个基于时间的程序,能够在未来特定的时间让程序post 一个alert,好比闹钟
二、一个在后台运行的程序,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)来触发处理,若是在处理代码中加上下面这条语句则必然会致使异常退出:
能够经过一种方法来请求更多后台时间来避免此问题。假设接收通知而触发的处理方法是applicationDidEnterBackground:
-(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];
}
文八: