ios后台运行 (转)

官方文档:http://developer.apple.com /library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

中文的好文章

http://www.devdiv.com/thread-47004-1-1.html

http://www.cnblogs.com/haipingwu/archive/2011/03/18/1987962.html

iOS4 请求更多后台时间

http://blog.csdn.net/zhangao0086/article/details/6739266

 

在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.在后台播放音频:

 

1. //后台播放 

AVAudioSession *session= [AVAudioSession sharedInstance]; 

[session setActive:YES error:nil]; 

[session setCategory:AVAudioSessionCategoryPlayback error:nil]; 

 

2. 让后台可以处理多媒体的事件 

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 

Remote-control events originate as commands issued by headsets and external accessories that are intended to control multimedia presented by an application. To stop the reception of remote-control events, you must call endReceivingRemoteControlEvents. 

 

3.系统进入后台运行时,让程序可以运行一段时间。使用此方法争取一定的时间,在程序进入后台后处理一些事情。 

- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler 

This method lets your application continue to run for a period of time after it transitions to the background. 

your application could call this method to ensure that had enough time to transfer an important file to a remote server or at least attempt to make the transfer and note any errors. You should not use this method simply to keep your application running after it moves to the background. 

1. //后台播放
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];

2. 让后台可以处理多媒体的事件
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
Remote-control events originate as commands issued by headsets and external accessories that are intended to control multimedia presented by an application. To stop the reception of remote-control events, you must call endReceivingRemoteControlEvents.

3.系统进入后台运行时,让程序可以运行一段时间。使用此方法争取一定的时间,在程序进入后台后处理一些事情。
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler
This method lets your application continue to run for a period of time after it transitions to the background.
your application could call this method to ensure that had enough time to transfer an important file to a remote server or at least attempt to make the transfer and note any errors. You should not use this method simply to keep your application running after it moves to the background.



3.实现VOIP应用:

 

在后台完成有限长度的任务

官 方文档http://developer.apple.com/library/iOS/#documentation/iPhone /Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

在 被终止之前的任意时间,应用程序会调用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]; 

bgTaskUIBackgroundTaskInvalid

}]; 

// 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]; 

bgTaskUIBackgroundTaskInvalid

}); 

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.fireDatetheDate

alarm.timeZone= [NSTimeZone defaultTimeZone]; 

alarm.repeatInterval0

alarm.soundName= @"alarmsound.caf"; 

alarm.alertBody= @"Time to wake up!"; 

[app scheduleLocalNotification:alarm]; 

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:方法将取而代之。

posted @ 2013-02-25 13:59  李伯波  阅读(639)  评论(0编辑  收藏  举报