前情提要
公司一个项目需要用到在登录后,锁屏后台的状态下也能持续性获取定位信息,并且每间隔
20S
提交到服务端。
第一步:
在info.plist
文件中添加如下内容
或者 在
TARGET
--- Signing&&Capabilities
--- Background Mode
中勾选Location Updates
,如下图截屏2020-08-04 16.41.41.png
第二步:
由于我用的高德地图来获取位置信息的,那就需要在定位前&&获取定位权限后将AMapLocationManager
的pausesLocationUpdatesAutomatically
属性设置为NO
,allowsBackgroundLocationUpdates
属性设置为YES
。如下
- (AMapLocationManager *)locationManager {
if (!_locationManager) {
_locationManager = [[AMapLocationManager alloc] init];
_locationManager.delegate = self;
[_locationManager setPausesLocationUpdatesAutomatically:NO];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
_locationManager.allowsBackgroundLocationUpdates = YES;
}
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
_locationManager.locationTimeout = 2;
_locationManager.reGeocodeTimeout = 2;
}
return _locationManager;
}
第三部:
为了方便获取位置信息和提交,我单独写了一个GCD-Timer
的管理类,如下
#import "JTTimerManager.h"
#import "LocationManager.h"
static JTTimerManager *jtm = nil;
@interface JTTimerManager ()
@property (nonatomic, strong) dispatch_source_t reportTimer;
@end
@implementation JTTimerManager
/*
创建单利,单利的唯一性
*/
+ (instancetype)share{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
jtm = [[self alloc]init];
});
return jtm;
}
/*
覆盖该方法主要确保 alloc init方法创建对象的唯一性
*/
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
jtm = [super allocWithZone:zone];
});
return jtm;
}
/*
确保通过copy产生对象的唯一性
*/
- (id)copy{
return self;
}
/*
确保通过mutableCopy产生对象的唯一性
*/
- (id)mutableCopy{
return self;
}
#pragma mark - GCD-Timer
- (dispatch_source_t )timerWithTimeInterval:(NSTimeInterval)timeInterval
delay:(NSTimeInterval)delay
block:(void (^)(void))block{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC));
uint64_t interval = (uint64_t)(timeInterval * NSEC_PER_SEC);
dispatch_source_set_timer(timer, start, interval, 0);
dispatch_source_set_event_handler(timer, ^{
if(block){
block();
}
});
return timer;
}
#pragma mark - 启动定时器
- (void)startWithTimer:(dispatch_source_t)timer{
if(timer){
dispatch_resume(timer);
}
}
#pragma mark - 取消定时器
- (void)cancelWithTimer:(dispatch_source_t)timer{
if(timer){
dispatch_cancel(timer);
}
}
#pragma mark - 计时操作
- (void)commitLocationInfo{
NSLog(@"** 提交定位信息 **");
[[LocationManager shared] getLocationInfoWithHandler:^(CLLocation * _Nonnull location, AMapLocationReGeocode * _Nonnull regeocode, NSError * _Nonnull error) {
}];
}
#pragma mark - 开始定位并提交位置信息
+ (void)startReport{
JTTimerManager *jtm = [JTTimerManager share];
@WeakObj(jtm);
jtm.reportTimer = [jtm timerWithTimeInterval:20 delay:0 block:^(void) {
[Weakjtm commitLocationInfo];
}];
[jtm startWithTimer:jtm.reportTimer];
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication]endBackgroundTask:UIBackgroundTaskInvalid];
}];
}
#pragma mark - 停止提交
+ (void)stopReport{
JTTimerManager *jtm = [JTTimerManager share];
[jtm cancelWithTimer:jtm.reportTimer];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
还有一句全局最重要的话,有了它才能保证后台运行。
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication]endBackgroundTask:UIBackgroundTaskInvalid];
}];
网友评论