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

来源:互联网 发布:韵乐x5效果器软件 编辑:程序博客网 时间:2024/06/11 18:20

之前开发一款配送员用的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;

图:


最后,审核的时候,一定要说明清楚,为啥要用这个后台上传位置功能;这个审核被拒概率很大,也没有好的解决方法;

0 0
原创粉丝点击