background_task

简述

iOS于2008年⾯面世时,只能有⼀一个第三⽅方应⽤用处于活动状态(位于前台)。这意味着应⽤用需要执 ⾏行的任务都必须位于前台的时候完成,否则任务将暂停并在应⽤用下次启动的时候执⾏行。iOS4推 出后,向第三⽅方应⽤用提供了后台功能。鉴于iOS设备的系统资源有限,以及省电,对后台处理有 ⼀一些限制,就是不能干扰前台应⽤用,也不能消耗太多电量。

iOS支持后台任务处理方式:

  1. 在后台完成耗时任务。这种方式适用于完成大量数据的下载或更新等任务,他们需要的时间超过了用户与应用交互的时间。
  2. 执行iOS允许的后台活动,如播放音乐、与蓝牙设备互交、监测GPS数据以获得位置发生重大变化、位置永久性网络连接让VoIP型应用能够正常运行。

检查设备是否支持后台任务

在编写使用多任务功能的代码时,必须检查设备是否支持多任务

1
2
3
4
5
6
UIDevice* device = [UIDevice currentDevice];
if (! [device isMultitaskingSupported])
{
NSLog(@"当前设备不⽀支持多任务.");
return;
}

在后台完成任务

要在后台执⾏行任务,应告诉应⽤用这项任务需要能够在后台运⾏行。另外,还应考虑需要多少内存 以及多⻓长时间才能完成。如果任务完成需要的时间超过10-15分钟,很可能任务还未完成应⽤用就 被终⽌止了。所以任务应该包含处理提前终⽌止的逻辑,并能够在重新启动应⽤用后继续执⾏行。操作 系统给应⽤用指定⼀一段时间,供它完成后台任务,但如果如果操作系统发现资源紧缺,也可能提 早终⽌止应⽤用。

后台任务的通用执行过程:

  1. 向应用请求后台任务标识符,并指定一个用来处理终止程序的快。
  2. 仅当应⽤用完了后台时间,或系统发现资源使用率过⾼进⽽决定终⽌应⽤时,终⽌处理程序才会被调⽤用。
  3. 执⾏后台任务逻辑。这包括从请求后台任务标识符到结束后台任务之间的所有代码。
  4. 让应用结束后台任务,并让后台标识符失效。
获取后台任务标识符

获取后台任务标识符同时制定终止处理程序块,使用__block 是为了block内部要对其修饰的变量修改。

1
2
3
4
5
__block NSInteger counter = 0;
__block UIBackgroundTaskIndentifier bTaskIndentifier = [[UIApplication shareApplication] beginBackgroundTaskWithExpirationHandler:
^{
...
}];
终止处理程序

系统在指定的时间或资源⽤完后,将调⽤后台任务的终止处理程序。应用即将关闭前,将在主程中调⽤用终处理程序。给终⽌止处理程序提供的时间不多(最多几秒),所以它执⾏行的操作应尽可能少。

1
2
3
4
5
__block UIBackgroundTaskIdentifier bTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:
^{
[[UIApplication sharedApplication] endBackgroundTask:bTask];//让应用指导后台任务结束
bTask = UIBackgroundTaskInvalid;//让后台任务标识符失效
}];
执行后台任务

获取后台任务标⽰符后,就可以开始在后台执⾏行任务了。再执⾏行后台任务过程中,注意从应⽤那⾥获取后台任务余下的时间。可据此决定是否接着执⾏其他的代码。通常在余下的时间还有几秒时终⽌止后台任务,让它有时间执⾏行扫尾工作。后台任务完成后,还需要做两项重要⼯作: 1. 对共享应⽤用实例调用endBackgroundTask 让应⽤用知道后台任务已结束;2. 将变量bTask设置为UIBackgroundTaskInvalid ,让这个后台任务标⽰示符⽆无效。从获取后台任务标示符到结束后台任务之间的所有代码将在后台执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
__block UIBackgroundTaskIdentifier bTask =
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:
^{
[[UIApplication sharedApplication] endBackgroundTask:bTask];//让应用指导后台任务结束
bTask = UIBackgroundTaskInvalid;//让后台任务标识符失效
}];
NSInteger timeDuration = 1 * 60;
NSLog (@"Background task starting , task ID is %u",bTask);
for (int counter = 0; counter <= timeDuration;counter ++ )
{
[NSThread sleepForTimeInterval:1];
//剩余运行时间
NSTimerInterval remainingTime = [[UIApplication sharedApplication] backgroundTimeRemaining];
if (remainingTime == DBL_MA){
NSLog(@"Background Processed %d. Still in foreground.",counter);
}else {
NSLog(@"Background Processed %d. Time remaining is: %f",counter,remainingTime);
}
}
dispatch_sync(dispatch_get_main_queue()
{
[self.backgroundButton setEnabled:YES];
[self.backgroundButton setTitle:@"Start Background Task" forState:UIControlStateNorm];
}
[[UIApplication sharedApplication] endBackgroundTask:bTask];
bTask = UIBackgroundTaskInvalid;

实现后台任务

iOS⽀支持⼀组具体的后台任务,这些活动可不断地进⾏下去,不像使⽤后台任务标示符那样受到限制。这些活动不受时间上的限制,注意这些活动不应使用过多的系统资源,以避免被操作系统强⾏终⽌止。

后台活动类型
  • 后台播放音频
  • 跟踪设备位置
  • 支持ip语音应用
  • 现在‘报刊杂志’应用的新内容
  • 与外置或蓝牙配件通信
  • 在后台取回内容
  • 使用推送通知启动后台下载