iOS 后台运行

iOS后台行,一般有两种方式:

1.UIBackgroundTaskIdentifier后台任务标记时,

2.设置后台运行模式,需要有voip,location功能的才行。不然app上线审核肯定是过不了的。

下面是我学习后台运行的尝试过程。

一.首先创建一个项目功程用来测试后台运行情况。这里我参照别人的一篇文章,在后台增加角标值。

直接上代码。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
        //注册推送,设置角标也需要 不然角标显示不了
    if(version >= 10.0)
    {
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (error) { NSLog(@"request authorization error: %@", error); }
        }];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
}

//进入前台,结速后台任务
- (void) applicationWillEnterForeground:(UIApplication *)application
{
    if(_badgeTimer)
    {
        dispatch_source_cancel(_badgeTimer);
        _badgeTimer = nil;
    }
}


//进入后台,开始后台任务,启动定时器每隔一秒给角标加一
- (void)applicationDidEnterBackground:(UIApplication *)application {
    
    //方法一
    [self stratBadgeNumberCount];
}

- (void)stratBadgeNumberCount{
    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;

    if(_badgeTimer)
    {
        dispatch_source_cancel(_badgeTimer);
        _badgeTimer = nil;
    }
    
    //定时器增加角标
    _badgeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_timer(_badgeTimer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(_badgeTimer, ^{
        
        [UIApplication sharedApplication].applicationIconBadgeNumber++;
    
    });
    dispatch_resume(_badgeTimer);
}

程序运行后,返回后台。程序的角标加到1就不再增加了。 注意如果设置了后台运行模式

voip,locationt等会一直增加的。但是你app里没有这些功能的话app store审核肯定是过不了的。如下图

iOS 后台运行_第1张图片

 二.尝试使用UIBackgroundTaskIdentifier后台任务标记时

1) Background Task仅用于执行短时间的任务,APP切换到后台后,可以通过beginBackgroundTaskWithExpirationHandler申请一段时间的后台时间,你的任务应该在这段时间内执行完成,否则会被系统杀死。

2) Background Task的持续时间并不是一个固定值,在不同性能的设备上差别巨大。在iPhone 10上为30秒,这个是我自己测试的,据说,在高性能的设备上则达到180秒。最长持续时间似乎还和当前的资源占用情况有关。

3)beginBackgroundTask和endBackgroundTask必须成对出现如果使用全局的UIBackgroundTaskIdentifier记录后台任务,需要注意每次执行beginBackgroundTask都会生成新的UIBackgroundTaskIdentifier。旧的UIBackgroundTaskIdentifier会被覆盖,则上一个UIBackgroundTaskIdentifier就没有机会执行endBackgroundTask。此时会出现beginBackgroundTask和endBackgroundTask不配对的情况,可能会被系统杀死。

//进入后台,开始后台任务,启动定时器每隔一秒给角标加一
- (void)applicationDidEnterBackground:(UIApplication *)application {
    
    //方法一
    [self stratBadgeNumberCount];
    [self startBgTask];
}

#pragma mark - 方法一
//开启后台任务
- (void)startBgTask{
    UIApplication *application = [UIApplication sharedApplication];

    if(_bgTask != UIBackgroundTaskInvalid)
    {
        [self endBackgroundTask];
    }

    _bgTask = [application beginBackgroundTaskWithExpirationHandler:^{

        NSLog(@"%f",application.backgroundTimeRemaining);

        //在这个地方重新开启后台任务不启作用
        //[weakSelf startBgTask];
        
        [self endBackgroundTask];
    }];
}

//结束后台任务
- (void) endBackgroundTask
{
    UIApplication *application = [UIApplication sharedApplication];
    [application endBackgroundTask:_bgTask];

    _bgTask = UIBackgroundTaskInvalid;
}

使用UIBackgroundTaskIdentifier后台可以延迟30秒左右就被挂启了。测试结果是角标加到31就不再继续加了。据说以前ios可以延迟180秒。没测过。

三.Background Mode

启用Background Mode后(音频播放、后台定位、VoIP等),是没有后台时间限制的。

//进入前台,结速后台任务
- (void) applicationWillEnterForeground:(UIApplication *)application
{
//    [self endBackgroundTask];
    if(_badgeTimer)
    {
        dispatch_source_cancel(_badgeTimer);
        _badgeTimer = nil;
    }
}

//进入后台,开始后台任务,启动定时器每隔一秒给角标加一
- (void)applicationDidEnterBackground:(UIApplication *)application {
    
    [self stratBadgeNumberCount];

    [self.player play];
    
    //用AVAudioPlayer或CLLocationManager其一就可以
    //方法三 (还没验证)
//    self.appleLocationManager = [[CLLocationManager alloc] init];
//    self.appleLocationManager.allowsBackgroundLocationUpdates = YES;
//    self.appleLocationManager.desiredAccuracy = kCLLocationAccuracyBest;
//    self.appleLocationManager.delegate = self;
//    [self.appleLocationManager requestAlwaysAuthorization];
//    [self.appleLocationManager startUpdatingLocation];

}

- (void)stratBadgeNumberCount{
    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;

    if(_badgeTimer)
    {
        dispatch_source_cancel(_badgeTimer);
        _badgeTimer = nil;
    }
    
    //定时器增加角标
    _badgeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_timer(_badgeTimer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(_badgeTimer, ^{
        
        [UIApplication sharedApplication].applicationIconBadgeNumber++;
    
    });
    dispatch_resume(_badgeTimer);
}

#pragma mark
- (AVAudioPlayer *)player{
    if (!_player){
        NSURL *url=[[NSBundle mainBundle]URLForResource:@"work5.mp3" withExtension:nil];
        _player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
        [_player prepareToPlay];
        //一直循环播放
        _player.numberOfLoops = -1;
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setCategory:AVAudioSessionCategoryPlayback error:nil];

        [session setActive:YES error:nil];
    }
    return _player;
}



#pragma mark
/** 苹果_用户位置更新后,会调用此函数 */
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
    [self.appleLocationManager stopUpdatingLocation];
    self.appleLocationManager.delegate = nil;

    [UIApplication sharedApplication].applicationIconBadgeNumber++;
    NSLog(@"success");
}

/** 苹果_定位失败后,会调用此函数 */
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
    [self.appleLocationManager stopUpdatingLocation];
    self.appleLocationManager.delegate = nil;
    NSLog(@"error");
}

同时要加上后台运行的能力

iOS 后台运行_第2张图片

参考:iOS 关于后台持续运行 - 简书

你可能感兴趣的:(iOS,知识点总结,-,ios,后台运行)