您的位置:首页 > 移动开发 > IOS开发

iOS开发 程序后台上传位置CLLocationManager

2016-08-02 14:31 316 查看
之前开发一款配送员用的APP时,用到了在程序在后台时,可以不断上传位置的功能,今天略微整理了一下,

主要用到系统的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;

图:


最后,审核的时候,一定要说明清楚,为啥要用这个后台上传位置功能;这个审核被拒概率很大,也没有好的解决方法;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: