先介绍一篇关于后台运行的文章:http://www.jianshu.com/p/174fd2673897
此篇文章的博主已经非常详细的介绍了IOS后台运行的一些方法,其中播放无声音乐、后台通知,这些我基本都有试过。当时做的项目是一个计步类的项目,因为系统计步器不能实时显示步数变化,用户体验有点差,后来选用加速计计步,这样就需要长久的后台运行来保证数据完整性。
后来跟博主一样选择了定位来保持后台运行,博主已经将方法讲的差不多了;我在使用过程中发现了一些可以保证APP后台稳定运行的细节,为博主补充下,也方便大家借鉴,有写的不对的还请大家指正。
关于定位服务:
1.info.plist里边需要加入后台运行的种类:Required background modes(Array类型) --> App registers for location updates(string类型),这个大家基本都知道。或者直接在Capabilities里边将Background Modes 打开并勾选Location updates即可。IOS8以上好像需要加入Privacy - Location Always Usage Description 类型String,是弹出定位提示的文字,如果没有这个好像是不弹提示的,具体忘了,大家可以尝试下。
2.AppDelegate.m 导入 #import <CoreLocation/CoreLocation.h> //GPS
在方法 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 中创建gps:
locationMannager = [[CLLocationManager alloc] init];
locationMannager.delegate = self;
locationMannager.activityType = CLActivityTypeFitness;
locationMannager.distanceFilter = kCLLocationAccuracyThreeKilometers;
locationMannager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locationMannager.allowsBackgroundLocationUpdates = YES; //允许后台刷新
locationMannager.pausesLocationUpdatesAutomatically = NO;//允许自动暂停定位服务
//该模式是抵抗ios在后台杀死程序设置,iOS会根据当前手机使用状况会自动关闭某些应用程序的后台刷新,该语句申明不能够被暂停,但是不一定iOS系统在性能不佳的情况下强制结束应用刷新
if (IS_IOS_8) {
[locationMannager requestAlwaysAuthorization];
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[locationMannager startUpdatingLocation];
[NSThread sleepForTimeInterval:5];
[locationMannager stopUpdatingLocation];
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) {
//第一次打开时系统还没允许使用定位,直接关闭会导致后台驻留失败,所以定位还未打开时不主动关闭,并不会增加太多耗电量。
[locationMannager stopUpdatingLocation];
}
});
3.AppDelegate.m 在进入后台的代理方法中实现后台运行的方法:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
inBackground = YES;
UIBackgroundTaskIdentifier __block bgTask;
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY
_DEFAULT, 0), ^{
int i = 0;
int j = 0;
while (inBackground) {
i = 0;
[locationMannager startUpdatingLocation];
while (i < 150 && inBackground) {
NSLog(@"时间:%d 总时间:%d
%.2f",i,j,application.backgroundTimeRemaining);
i++;
j++;
[NSThread sleepForTimeInterval:1];
}
}
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
这一部分粗体文字非常重要,这个是后台定位稳定运行的必要设定。
[NSThread sleepForTimeInterval:5];虽然没明白为什么必须加,但是加了这个之后会解决引用文博主出现的有时不能持续运行的问题。经过我多次测试出现引用文博主那种情况一般是这样的:如果APP打开后定位图标还亮着,home键进入后台,后台可运行时间backgroundTimeRemaining会被刷新,可达到稳定允许的效果;如果是在APP打开后大约30秒之后定位图标消失了,再进入后台,backgroundTimeRemaining将不会被刷新,后台运行中断。
但是如果加了[NSThread sleepForTimeInterval:5];将不会出现这种情况,不管图标有没有消失都能刷新backgroundTimeRemaining,backgroundTimeRemaining将变为无限大。可以看到,后台运行的时候会在每150秒的时候激活一次定位,即便一开始background Time Remaining是180秒,150秒的时候激活定位,background Time Remaining会被刷新,变为无限大。
因为定位设置的精度是千米级,150秒激活一次,虽然是处于持续定位,但是耗电量不是很大,后边有测试截图。
我给项目加了widget,可以实时观察后台运行情况,附上我测试的图。
闲来无事把代码重新码了一遍,发现还好使,有需要的自取吧。
链接: https://pan.baidu.com/s/1CMlzbNjwg7f2whvzvNTvSQ 密码: wdrw