iOS后台运行的相关方案总结

1、完全不申请后台运行

一般来说,在完全没有申请后台运行的情况下,App退到后台后,只有5s的时间来执行代码,之后程序将被挂起。

2、申请3分钟的后台运行时间

在没有申请像音频播放、后台定位、newsstand、VoIP等后台运行权限时。苹果也给我们提供了一种可以延长后台运行时间的方法。

1
2
3
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^ __nullable)(void))handler  NS_AVAILABLE_IOS(4_0) NS_REQUIRES_SUPER;
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithName:(nullable NSString *)taskName expirationHandler:(void(^ __nullable)(void))handler NS_AVAILABLE_IOS(7_0) NS_REQUIRES_SUPER;
- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier NS_AVAILABLE_IOS(4_0) NS_REQUIRES_SUPER;

在使用方法大致如下:

1
2
3
4
5
6
7
__block UIBackgroundTaskIdentifier identifer = UIBackgroundTaskInvalid;
identifer = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"msg_sync" expirationHandler:^{
     if(identifer != UIBackgroundTaskInvalid) {
        [[UIApplication sharedApplication] endBackgroundTask:identifer];
        identifer = UIBackgroundTaskInvalid;
     }
}];

我们可以看到通过调用beginBackgroundTaskWithName:expirationHandler:我们获取到了3分钟的后台运行时间。在时间到后expirationHandler的handler回调会触发。这时我们必须要调用endBackgroundTask来停止后台运行,否则App进程可能会被系统kill掉。
剩余的后台运行时间我们可以通过backgroundTimeRemaining来获取。

3、伪无限后台

伪无限后台,需要结合BackgroundModes和方法2。需要我们申请后台运行权限。这里常用的方法就是播放一个无声音乐,来让用户感知不到后台的存在。实现过程:
• 首先需要申请后台播放音乐权限:

• 接下来就是进入后台后,不断的轮播无声音乐和通过方法2申请后台三分钟的运行时间。代码如下:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
NSTimer *timer = nil;
BOOL background = NO ;
AVAudioPlayer *player = nil;
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
-(void)applicationDidEnterBackground:(NSNotification *)notifi
{
    background = YES;
    timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(countTime) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
-(void)applicationWillEnterForeground:(NSNotification *)notifi
{
    background = NO;
}
-(void)countTime{
    if (background == NO) {
        [timer invalidate];
        return;
    }
    if ([[UIApplication sharedApplication] backgroundTimeRemaining] < 60.) {//当剩余时间小于60时,开如播放音乐,并用这个假前台状态再次申请后台
        [self playMusic];
        //申请后台
        [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            NSLog(@"我要挂起了");
        }];
    }
}
-(void)playMusic{
    NSURL *url=[[NSBundle mainBundle]URLForResource:@"silence.mp3" withExtension:Nil];
    player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:Nil];
    [player prepareToPlay];
    [player play];
}

4、后台唤醒

当应用进入后台后,如果已经处于挂起状态或者已经被杀死了有没有什么办法可以自动唤醒App呢?答案是有。
系统给了我们很多可以后台唤醒应用的方案,下面就来一一介绍:

利用CLLocationManager

CLLocationManager两种方式可以在后台唤醒App:

  • 使用关键位置定位startMonitoringSignificantLocationChanges
  • 使用区域检测Region Monitoring

startMonitoringSignificantLocationChanges使用的是基站定位,会在定位基站发生变化时回调结果。Region Monitoring则是需要用户建立一个地理围栏, 只有用户在进出地理围栏时才会在后台唤醒App。
对于后台唤醒策略来说,startMonitoringSignificantLocationChanges会更加具有可行性。
但是这个方法有个很大的缺点:即使监测到基站位置发生了变化,系统也不会即使唤醒App,官方文档上写的时间是15分钟,但实际测试这个时间并不固定,还可能会更大。

iOS静默推送

先看看静默推送与普通推送的区别:

普通推送:收到推送后(有文字有声音),点开通知,进入APP后,才执行
-application:didReceiveRemoteNotification:fetchCompletionHandler:

静默推送:收到推送(没有文字没有声音),不用点开通知,不用打开APP,就能执行
-application:didReceiveRemoteNotification:fetchCompletionHandler:,用户完全感知不到。

静默推送的使用:

静默推送不仅在定义上和其他的推送方式不同,在推送内容上也和其他推送不同。在后台给应用的推送内容中只要满足下面的条件,该推送就是静默推送:

如果只携带content-available: 1 不携带任何badge,sound 和消息内容等参数,则可以不打扰用户的情况下进行内容更新等操作即为“Silent Remote Notifications”**


静默推送的缺点是:
1、如果应用已经被Kill。是无法自动拉起应用的。所以它自能在应用后台挂起的情况下使用。
2、静默推送和startMonitoringSignificantLocationChanges一样都无法保证应用被实时唤醒。官网说法如下:
静默推送不是让您的应用程序在快速刷新操作之后保持醒来的方式,也不是用于高优先级更新的方式。APN将后台更新通知视为低优先级,如果总数过多,APN可能会将其传输完全限制在一定程度。实际的限制是动态的,可以根据条件进行更改,但不要每小时发送一次以上的通知。原文链接

利用VoIP

VoIP推送被认为是高优先级通知,并且毫无延迟地传送。VoIP推送可以包括比标准推送通知提供的数据更多的数据。如果收到VoIP推送时,您的应用程序未运行,则会自动重新启动。
即使您的应用在后台运行,您的应用也会在运行时处理推送。
VoIP是能真正做到在App挂起和被杀死情况下实时拉起应用的方法。当然它也有一定的局限性,应用必须要是VoIP应用,即应用中有类似视频呼叫或者语音呼叫等功能。

本文作者: ctinusdev
本文链接: https://ctinusdev.github.io/2016/05/10/BackgroundTask/
转载请注明出处!

坚持原创技术分享,您的支持将鼓励我继续创作!