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审核肯定是过不了的。如下图
二.尝试使用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<CLLocation *> *)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 关于后台持续运行 - 简书