应用程序在后台时向服务器发送纬度和经度

Sending Latitude and Longitude to Server when app is in background

我已经浏览了很多链接,即使在那之后我也没有找到合适的解决方案来获取经纬度。

Periodic iOS background location updates

iOS long-running background timer with "location" background mode

我尝试了一些链接和论坛,但它只工作了 3 分钟,然后应用程序根本没有更新用户位置。

- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.


//create new uiBackgroundTask
__block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

//and create new timer with async call:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

    [locationManager startUpdatingLocation];

    NSTimer* t = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(startTrackingBg) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:t forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
});

}
 -(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//  store data
CLLocation *newLocation = [locations lastObject];


//tell the centralManager that you want to deferred this updatedLocation
if (_isBackgroundMode && !_deferringUpdates)
{
    _deferringUpdates = YES;
    [locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
}
}

好的。

经过 3 天的努力,即使在 3 分钟后,当应用程序处于后台时,它也可以为我发送纬度和经度。

我检查了我的应用程序,在后台持续发送经纬度超过一个小时。

至少可以帮助一些人。

首先请在您的 pList 中添加以下两个键。

 1.NSLocationAlwaysUsageDescription
 2.NSLocationWhenInUseUsageDescription

两者都是字符串,你可以给任何值。

然后请打开后台获取并检查项目部分功能下的位置更新。

然后导入 Corelocation 框架并添加下面的代码。

locationManager 是一个全局变量。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
 //create CLLocationManager variable
locationManager = [[CLLocationManager alloc] init];
//set delegate
locationManager.delegate = self;

app = [UIApplication sharedApplication];
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.

if ([locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) {
    [locationManager setAllowsBackgroundLocationUpdates:YES];
}
locationManager.desiredAccuracy = 45;
locationManager.distanceFilter = 100;
// Once configured, the location manager must be "started".
[locationManager startUpdatingLocation];
}

 - (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.

[locationManager stopUpdatingLocation];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
locationManager.pausesLocationUpdatesAutomatically = NO;
locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[locationManager startUpdatingLocation];
 }

 - (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.


[locationManager stopUpdatingLocation];

__block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    bgTask = UIBackgroundTaskInvalid;
}];

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:10.0
                                              target:self
                                            selector:@selector(startTrackingBg)
                                            userInfo:nil
                                             repeats:YES];


 }

-(void)startTrackingBg {

[locationManager startUpdatingLocation];
 NSLog(@"App is running in background");
}
 //starts automatically with locationManager
  -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
latitude=newLocation.coordinate.latitude;
longitude=newLocation.coordinate.longitude;
NSLog(@"Location: %f, %f",newLocation.coordinate.longitude, newLocation.coordinate.latitude);
 }

你需要参考这个苹果文档handling location events in the background

您需要在后台模式中启用位置更新[=] 34=] 项目。

标准定位服务无法在后台模式下工作因此您必须使用重大变化定位服务或访问服务 .

使用此代码

locationManager.delegate = self
locationManager.startMonitoringSignificantLocationChanges()

启用重大更改位置服务。

基于 Santos 的回答,其中包含使后台定位工作的大部分重要步骤,我澄清并更正了一些细节。

项目设置

您应该将这些密钥添加到您的 Xcode 目标 信息 属性 列表中。确保为每一个添加有效的描述,否则您的应用可能无法获得批准。

  • NSLocationAlwaysUsageDescription
  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysAndWhenInUseUsageDescription

接下来,在目标 功能 中,打开后台模式并检查 位置更新后台获取.位置更新将在后台启用位置,后台获取将允许您在后台使用网络。

开始监控

首先创建 CLLocationManager 的实例,配置它并打开 后台更新,然后启动它。尽管下面的代码使用最常见的函数 startUpdatingLocation 来获取位置,但还有其他几个服务可供使用。 重要 选择最合适的服务,因为这会极大地影响电池使用 并且 应用程序是否会重新启动 iOS。有关详细信息,请参阅下文。

// Declare as properties in your class
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) CLLocation *lastLocation;

// Call to start
- (void)initializeAndStartLocationService {
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;

    // Must be set for background operation
    self.locationManager.allowsBackgroundLocationUpdates = YES;

    // Optional configuration
    self.locationManager.distanceFilter = kCLDistanceFilterNone;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    self.locationManager.pausesLocationUpdatesAutomatically = YES;
    self.locationManager.showsBackgroundLocationIndicator = YES;

    // Authorize - the lazy way
    [self.locationManager requestAlwaysAuthorization];

    // Start the standard location service, there are others
    [self.locationManager startUpdatingLocation];
}

// Delegate method that will receive location updates
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    // Keep the last received location
    self.lastLocation = [locations lastObject];

    NSLog(@"New position %f, %f", self.lastLocation.coordinate.latitude, self.lastLocation.coordinate.longitude);

    // Do something with the location or retrieve the location later
    //       :
}

停止监控

不要忘记停止监控以节省电量。您可以在 CLLocationManager.

的单个实例上多次启动和停止
- (void)dealloc {
    [self.locationManager stopUpdatingLocation];
}

自动重新启动应用程序注意事项

当您的应用 运行 在后台时,它可以(实际上经常会在一段时间后)被 iOS 终止。根据您使用的位置更新类型,iOS 会或不会自动为您重新启动您的应用。如果 iOS 不重新启动,用户必须再次启动您的应用才能继续后台处理。

this page 上阅读更多内容。

阅读更多

CLLocationManager - Core Location | Apple Documentation
Handling Location Events in the Background | Apple Documentation