如果你的应用需要在点击home键之后,整个程序里还需要有部分功能需要一直执行,那么就需要用到GCD,后台执行的话,一般来讲,苹果做了限制,如果不做任何配置的话,你的应用最多只能运行5s,5s之后就会被挂起,长时间的话就会被杀掉进程;还有一种情况:你设置了后台运行,但是一般来讲:9.9Min之后,程序同样也会被挂起;
问题来了:怎么进行设置,如果设置成一个一直在后台执行的,不受时间段的控制;
很多的应用:qq,高德地图导航,都是需要保持一个长连接;
下面说一下实现思路:
首先
继续保持Application does not run in background字段的值为NO,同时在UIBackgroundModes字段中添加audio,location,voip,或者选择App processes Newsstand Kit downloads,App communicates with an accessory,App communicates using CoreBluetooth,App shares data using CoreBluetooth,总共7个,都可以开始后台执行,大概在594秒(即9.9分钟)的时候停止,与加不加相应的调用代码无关,空工程即可。
- (void)applicationDidEnterBackground:(UIApplication *)application{ UIApplication* app = [UIApplication sharedApplication]; __block UIBackgroundTaskIdentifier bgTask; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ dispatch_async(dispatch_get_main_queue(), ^{ if (bgTask != UIBackgroundTaskInvalid) { bgTask = UIBackgroundTaskInvalid; } }); }]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_main_queue(), ^{ if (bgTask != UIBackgroundTaskInvalid) { bgTask = UIBackgroundTaskInvalid; } }); }); }
然后,在定义一个定时器,定时的执行进行检测,后台线程运行的时间剩余数;如果小于1分钟就再次申请一个新的任务;
- (void)tik{ if ([[UIApplication sharedApplication] backgroundTimeRemaining] < 61.0) { [[CKAudioTool sharedInstance] playSound]; [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil]; } } [[CKAudioTool sharedInstance] playSound];//这段代码是去播放了一个无声的音乐,很关键的一点是 [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error]
这样后台播放就不会影响到别的程序播放音乐了。
我这个计时器每分钟运行一次tik函数,如果发现后台运行时间小于一分钟了,就再去申请一个backgroundTask。
神奇的地方在于:backgroundTask不能在程序已经进入后台的时候申请,可以用一个播放音乐的假前台状态去申请,所以可以做到不断申请到权限,也就完成了长时间后台执行。