后台长时间定时定位-Location实践经验
来源:互联网 发布:pg数据库如何导入数据 编辑:程序博客网 时间:2024/05/16 19:14
前言
最近接到这样一个需求,每隔固定时间采集用户的位置,然后再把这些数据上传到服务器。研究了下ios的定位功能,在后台定时遇到了一些困难。当app进入后台状态,定时器就不再运行,导致无法取到用户的位置。
在网上查了一些资料,发现有人已经实现了这个功能,它是一个Github上的第三方库,叫Location,不仅能在后台定时采集位置数据,还优化了定位方式,减少耗电。
接下来我们来看看Location是如何实现的以及它存在的问题。
代码结构
BackgroundTaskManager
负责创建、管理后台任务,提供两个方法,开始和结束后台任务。它实现了后台任务的无限期运行。
@interface BackgroundTaskManager : NSObject
+(instancetype)sharedBackgroundTaskManager;-(UIBackgroundTaskIdentifier)beginNewBackgroundTask;-(void)endAllBackgroundTasks;@end
LocationShareModel
包装了后台任务类,也管理定位定时器。
@interface LocationShareModel : NSObject@property (nonatomic) NSTimer *timer;@property (nonatomic) NSTimer * delay10Seconds;@property (nonatomic) BackgroundTaskManager * bgTask;@property (nonatomic) NSMutableArray *myLocationArray;+(id)sharedModel;@end
LocationTracker
负责管理后台定时定位的主类。
我们先看一下它提供的接口。
+ (CLLocationManager *)sharedLocationManager;//开始追踪定位- (BOOL)startLocationTracking;//停止追踪定位- (void)stopLocationTracking;//向服务器发送已获取的设备位置数据- (void)updateLocationToServer;
LocationTracker类的初始化
+ (CLLocationManager *)sharedLocationManager { static CLLocationManager *_locationManager; @synchronized(self) { if (_locationManager == nil) { _locationManager = [[CLLocationManager alloc] init]; //设备位置精度,这里设置为最高精度 _locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; //是否暂停更新 _locationManager.pausesLocationUpdatesAutomatically = NO; //iOS9的新特性,打开后台位置更新,还要在plist中配置 if (IOS9ORLATER) { _locationManager.allowsBackgroundLocationUpdates = YES; } } } return _locationManager;}
当应用进入后台,借助BackgroundTaskManager无限延长后台任务的存活时间,进行后台采集位置信息。
- (id)init { if (self==[super init]) { //Get the share model and also initialize myLocationArray self.shareModel = [LocationShareModel sharedModel]; self.shareModel.myLocationArray = [[NSMutableArray alloc]init]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; } return self;}-(void)applicationEnterBackground{ CLLocationManager *locationManager = [LocationTracker sharedLocationManager]; locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; locationManager.distanceFilter = kCLDistanceFilterNone; if(IOS8ORLATER) { [locationManager requestAlwaysAuthorization]; } [locationManager startUpdatingLocation]; //Use the BackgroundTaskManager to manage all the background Task self.shareModel.bgTask = [BackgroundTaskManager sharedBackgroundTaskManager]; [self.shareModel.bgTask beginNewBackgroundTask];}
持续获取设备的位置,是个特别耗电的任务。为了减少耗电,定时关闭位置服务。在接收到位置信息10秒后,关闭位置服务,一分钟后再重新打开位置服务,这样就达到减少耗电的目的。我们看代码的实现
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ ...... self.shareModel.bgTask = [BackgroundTaskManager sharedBackgroundTaskManager]; [self.shareModel.bgTask beginNewBackgroundTask]; //Restart the locationMaanger after 1 minute self.shareModel.timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(restartLocationUpdates) userInfo:nil repeats:NO]; //Will only stop the locationManager after 10 seconds, so that we can get some accurate locations //The location manager will only operate for 10 seconds to save battery if (self.shareModel.delay10Seconds) { [self.shareModel.delay10Seconds invalidate]; self.shareModel.delay10Seconds = nil; } self.shareModel.delay10Seconds = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(stopLocationDelayBy10Seconds) userInfo:nil repeats:NO];}
重启位置服务
- (void) restartLocationUpdates{ if (self.shareModel.timer) { [self.shareModel.timer invalidate]; self.shareModel.timer = nil; } CLLocationManager *locationManager = [LocationTracker sharedLocationManager]; locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; locationManager.distanceFilter = kCLDistanceFilterNone; if(IOS8ORLATER) { [locationManager requestAlwaysAuthorization]; } [locationManager startUpdatingLocation];}
按照Location库的设计,在updateLocationToServer方法中,处理向服务器发送信息。
- (void)updateLocationToServer { ......... //TODO: 在这里插入你的代码,处理向服务器发送位置信息 ........}
实践
这个类库解决了后台定时定位的问题,使用也很简单,而且还处理了定位耗电的问题,使耗电量降低到每小时5%左右。但在实践的过程中发现它存在一些问题。
- 发送数据到服务器方法的定时器,最大支持3分钟;
- 发送数据到服务器方法的定时器,在运行2小时后就停止了;
- 发送数据到服务器方法的定时器,不准确;
经过一些尝试,废弃了updateLocationToServer方法,将发送数据的代码移到locationManager中,才解决了这几个问题。具体解决方法如下:
首先为LocationTracker类添加一个私有的属性,记录上次执行发送数据的时间。
@interface LocationTracker ()@property (nonatomic, strong) NSDate *lastSendDate;@end
在locationManager回调方法中添加自己的代码。
....... //Select only valid location and also location with good accuracy if(newLocation!=nil&&theAccuracy>0 &&theAccuracy<2000 &&(!(theLocation.latitude==0.0&&theLocation.longitude==0.0))){ self.myLastLocation = theLocation; self.myLastLocationAccuracy= theAccuracy; NSMutableDictionary * dict = [[NSMutableDictionary alloc]init]; [dict setObject:[NSNumber numberWithFloat:theLocation.latitude] forKey:@"latitude"]; [dict setObject:[NSNumber numberWithFloat:theLocation.longitude] forKey:@"longitude"]; [dict setObject:[NSNumber numberWithFloat:theAccuracy] forKey:@"theAccuracy"]; //Add the vallid location with good accuracy into an array //Every 1 minute, I will select the best location based on accuracy and send to server [self.shareModel.myLocationArray addObject:dict]; //这里插入代码,处理发送位置数据到服务器 if (!self.lastSendDate || [[self.lastSendDate dateByAddingHours:1] compare:[NSDate date]] <= 0) { self.lastSendDate = [NSDate date]; } }
作者:潇潇潇潇潇潇潇
链接:http://www.jianshu.com/p/295a3ae5f8a6
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
转载自:http://www.jianshu.com/p/7ccc0860bdbd
- 后台长时间定时定位-Location实践经验
- 后台地图的定时定位
- android 后台长时间执行周期性定时任务 解决方案收集
- android 后台长时间执行周期性定时任务 解决方案收集
- android 后台长时间执行周期性定时任务 解决方案收集
- android 后台长时间执行周期性定时任务 解决方案收集
- iOS后台持续定位并定时上传
- iOS后台持续定位并定时上传
- location 定位
- 后台长时间运行
- ios 长时间后台
- iOS后台长时间执行
- ios后台长时间运行
- ios实现长时间后台运行
- ios实现长时间后台运行
- ios实现长时间后台运行
- ios实现长时间后台运行
- ios实现长时间后台运行
- 设计模式学习—代理模式(Proxy Design Pattern)
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
- linux中脚本执行方式详解
- android实现复制粘贴一项文本功能
- 如何接入极光推送
- 后台长时间定时定位-Location实践经验
- Jsonp的使用
- HDU 4089 Activation【概率DP】
- 剑指Offer面试题7[用两个栈实现队列]
- OVN Northbound DB简介及其相关命令示例
- 广度优先搜索
- linux /hadoop 运行java 程序
- dumpsys介绍
- Ubuntu 16.04 CUDA8.0 Caffe搭建