iOS开发 程序后台上传位置CLLocationManager
2016-08-02 14:31
316 查看
之前开发一款配送员用的APP时,用到了在程序在后台时,可以不断上传位置的功能,今天略微整理了一下,
主要用到系统的CoreLocation
代码:
.m
在AppDelegate的- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法里
直接调用即可:[[XSDLocationTools shareInstance] startLocationService];
还有,是必须在如图所示,勾选location updates;
图:
![](http://img.blog.csdn.net/20160802142747658?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
最后,审核的时候,一定要说明清楚,为啥要用这个后台上传位置功能;这个审核被拒概率很大,也没有好的解决方法;
主要用到系统的CoreLocation
代码:
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface XSDLocationTools : NSObject + (XSDLocationTools *)shareInstance; // 开启定位 - (void)startLocationService; @end
.m
// // XGLocationTool.m // XGPayDemo // // Created by 小广 on 16/4/25. // Copyright © 2016年 小广. All rights reserved. // #import "XSDLocationTools.h" #import <CoreLocation/CoreLocation.h> //#import "WGS84ToGCJ02.h" #import "BaiduMapDefine.h" #import "XSDBaiduMapTools.h" #define LAST_LONG @"last_longitude" // 上次上传位置的经度 #define LAST_LATI @"last_latitude" // 上次上传位置的纬度 @interface XSDLocationTools ()<CLLocationManagerDelegate> { //dispatch_source_t _timer; CLLocationCoordinate2D _newCoor; } // 1.设置位置管理者属性 @property (nonatomic, strong) CLLocationManager *lcManager; //@property (nonatomic, assign) BOOL isRequest; @property (nonatomic, strong) NSTimer *uploadTimer; @end @implementation XSDLocationTools + (XSDLocationTools *)shareInstance { static XSDLocationTools *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[XSDLocationTools alloc] init]; [instance p_addNSNotificationObserver]; }); return instance; } // 开启定位 - (void)startLocationService { if ([CLLocationManager locationServicesEnabled]) { // 创建位置管理者对象 self.lcManager = [[CLLocationManager alloc] init]; self.lcManager.delegate = self; // 设置代理 // 设置定位距离过滤参数 (当本次定位和上次定位之间的距离大于或等于这个值时,调用代理方法) self.lcManager.distanceFilter = 50; self.lcManager.desiredAccuracy = kCLLocationAccuracyBest; // 设置定位精度(精度越高越耗电) // 2、在Info.plist文件中添加如下配置: //(1)NSLocationAlwaysUsageDescription 授权使应用在前台后台都能使用定位服务 //(2)NSLocationWhenInUseUsageDescription 授权使应用只能在前台使用定位服务 // 两者也可以都写 if ([[UIDevice currentDevice].systemVersion floatValue] >=8.0 ) { // iOS0.0:如果当前的授权状态是使用是授权,那么App退到后台后,将不能获取用户位置,即使勾选后台模式:location [self.lcManager requestAlwaysAuthorization]; [self.lcManager requestWhenInUseAuthorization]; } // iOS9.0+ 要想继续获取位置,需要使用以下属性进行设置(注意勾选后台模式:location)但会出现蓝条 if ([self.lcManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) { // self.lcManager.allowsBackgroundLocationUpdates = YES; } [self.lcManager startUpdatingLocation]; // 开始更新位置 [self.uploadTimer setFireDate:[NSDate distantPast]]; // 开启定时器 } } /** 获取到新的位置信息时调用*/ -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *tempLocation = locations[0]; // 将坐标转化为百度坐标 方法来源于百度sdk NSDictionary *temp = BMKConvertBaiduCoorFrom(tempLocation.coordinate, BMK_COORDTYPE_GPS); CLLocationCoordinate2D nowLocation = BMKCoorDictionaryDecode(temp); //if (self.isRequest) return; //self.isRequest = YES; //[self uploadUserLocationHandle:nowLocation]; //[self uploadLocationTimer:nowLocation]; _newCoor = nowLocation; } /** 不能获取位置信息时调用*/ -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@"获取定位失败"); } /** 定位服务状态改变时调用*/ - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { switch (status) { case kCLAuthorizationStatusNotDetermined: { NSLog(@"用户还未决定授权"); break; } case kCLAuthorizationStatusRestricted: { NSLog(@"访问受限"); break; } case kCLAuthorizationStatusDenied: { // 类方法,判断是否开启定位服务 if ([CLLocationManager locationServicesEnabled]) { NSLog(@"定位服务开启,被拒绝"); } else { NSLog(@"定位服务关闭,不可用"); } break; } case kCLAuthorizationStatusAuthorizedAlways: { NSLog(@"获得前后台授权"); break; } case kCLAuthorizationStatusAuthorizedWhenInUse: { NSLog(@"获得前台授权"); break; } default: break; } } // 直接上传用户位置 static NSInteger uploadCount = 1; - (void)uploadUserLocationHandle:(CLLocationCoordinate2D)coor { NSDictionary *dic = @{@"longitude":@(coor.longitude), @"latitude":@(coor.latitude)}; __weak typeof(self)weakSelf = self; [[UserManager shareInstance] uploadUserLocation:dic block:^(BOOL success) { if (!success) { if (uploadCount > 3) return ; uploadCount ++; [weakSelf uploadUserLocationHandle:coor]; XSDLog(@"上传位置不ok"); return; } // if (uploadCount != 1) uploadCount = 1; XSDLog(@"上传位置ok"); }]; } // 定时上传位置 - (void)uploadLocationTimer { BOOL canUpload = [self isCanUpload:_newCoor]; if (canUpload) { NSDictionary *dic = @{@"longitude":@(_newCoor.longitude), @"latitude":@(_newCoor.latitude)}; __weak typeof(self)weakSelf = self; // 和后台服务器进行交互 上传位置 [[UserManager shareInstance] uploadUserLocation:dic block:^(BOOL success) { if (success) { XSDLog(@"上传位置ok"); return ; } XSDLog(@"上传位置不ok"); [weakSelf uploadUserLocationHandle:_newCoor]; }]; } } // 监听用户登录的通知 - (void)p_addNSNotificationObserver { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(p_loginNotification) name:kLoginNotification object:nil]; } - (void)p_loginNotification { // 用户登录, 就开始上传位置 NSString *latitude = [XSDTools objectForKey:TCPFLocationlatitude]; NSString *longitude = [XSDTools objectForKey:TCPFLocationlongitude]; if (!latitude || !longitude) return; // 读取本地的经纬度 CLLocationCoordinate2D location = CLLocationCoordinate2DMake(latitude.doubleValue, longitude.doubleValue); [self uploadUserLocationHandle:location]; } // 是否达到条件(判断距离 大于一定距离)上传位置 - (BOOL)isCanUpload:(CLLocationCoordinate2D)coor { // 下面代码相当于 NSUserDefaults 存取数据 NSString *latitude = [XSDTools objectForKey:LAST_LATI]; NSString *longitude = [XSDTools objectForKey:LAST_LONG]; if (!latitude || !longitude) { // 下面代码相当于 NSUserDefaults 存取数据 [XSDTools setValue:[NSString stringWithFormat:@"%f",coor.latitude] forKey:LAST_LATI]; [XSDTools setValue:[NSString stringWithFormat:@"%f",coor.longitude] forKey:LAST_LONG]; return YES; } // 下面代码来源于百度sdk 计算两点间的距离 NSNumber *distence = [XSDBaiduMapTools calculateTwoPointLongWithStart:CLLocationCoordinate2DMake(latitude.doubleValue, longitude.doubleValue) end:coor]; if (distence.integerValue >= 100) { // 下面代码相当于 NSUserDefaults 存取数据 [XSDTools setValue:[NSString stringWithFormat:@"%f",coor.latitude] forKey:LAST_LATI]; [XSDTools setValue:[NSString stringWithFormat:@"%f",coor.longitude] forKey:LAST_LONG]; return YES; } return NO; } // 懒加载 - (NSTimer *)uploadTimer { if (!_uploadTimer) { _uploadTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(uploadLocationTimer) userInfo:nil repeats:YES]; } return _uploadTimer; } @end里面用到了一些自定义的类,不过不影响,各位可以根据需求修改,挺简单的;
在AppDelegate的- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法里
直接调用即可:[[XSDLocationTools shareInstance] startLocationService];
还有,是必须在如图所示,勾选location updates;
图:
最后,审核的时候,一定要说明清楚,为啥要用这个后台上传位置功能;这个审核被拒概率很大,也没有好的解决方法;
相关文章推荐
- iOS开发-APP在waiting for review状态时如何重新上传程序
- iOS开发:保持程序在后台长时间运行
- iOS开发小技巧--iOS程序进入后台运行的实现
- ios开发中iphone模拟器中程序文件和数据库的存放位置
- iOS开发>学无止境 - 后台定位上传的代码实践
- 精通iOS开发--第15章 Grand Central Dispatch和后台处理之程序生命周期 NSNotificationCenter和线程
- iOS开发:保持程序在后台长时间运行
- 学习IOS开发项目篇--如何让程序在后台保持挂起状态
- IOS开发模块总结(二)后台运行程序(2)Task completion-UIBackgroundTaskIdentifier
- ios开发-程序压后台后,悄悄的抓取数据~~
- ios开发——日常之iOS程序进入后台后仍可运行定时器
- ios开发中iphone模拟器中程序文件和数据库的存放位置
- iOS后台与服务器交互(支持锁屏)eg:后台定时上传当前位置
- IOS开发模块总结(二)后台运行程序(1) 后台运行程序详解(一)
- IOS开发模块总结(二)后台运行程序(1) 后台运行程序详解(二)