应用程序进入后台后每n分钟获取用户位置

scu*_*oni 27 iphone background objective-c locationmanager ios

我正在尝试实施这篇文章中给出的建议.

不幸的是,我不清楚这些步骤.我尝试实现这些建议,但是即使在我启动和停止locationServices之后,backgroundTimeRemaining仍然继续减少.这就是我开发它的方式:

- (void)applicationDidEnterBackground:(UIApplication *)application {

    UIApplication*    app = [UIApplication sharedApplication];

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

    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task.
        self.timer = nil;
        [self initTimer];

    });
}
Run Code Online (Sandbox Code Playgroud)

initTimer:

- (void)initTimer {

    // Create the location manager if this object does not
    // already have one.
    if (nil == self.locationManager)
        self.locationManager = [[CLLocationManager alloc] init];

    self.locationManager.delegate = self;
    [self.locationManager startMonitoringSignificantLocationChanges];

    if (self.timer == nil) {
        self.timer = [NSTimer scheduledTimerWithTimeInterval:0.3
                                              target:self
                                            selector:@selector(checkUpdates:)
                                            userInfo:nil
                                             repeats:YES];
    }
}
Run Code Online (Sandbox Code Playgroud)

checkUpdates:

- (void)checkUpdates:(NSTimer *)timer{
    UIApplication*    app = [UIApplication sharedApplication];
    double remaining = app.backgroundTimeRemaining;
    if(remaining < 580.0) {
        [self.locationManager startUpdatingLocation]; 
        [self.locationManager stopUpdatingLocation]; 
        [self.locationManager startMonitoringSignificantLocationChanges];
    }
    DbgLog(@"Reminaing %f", app.backgroundTimeRemaining);
}
Run Code Online (Sandbox Code Playgroud)

有没有人对我的代码中的错误有什么建议?正在调用initTimer和checkUpdates,但仅限于后台执行时间(+ - 10分钟).我希望应用程序每隔n分钟"永远"更新位置.

我的应用程序的UIBackgroundModes设置为位置.

更新:

我现在正在重置didUpdateToLocation和didFailWithError上的计时器.但是backgroundTimeRemaining仍在不断减少:

- (void)locationManager:(CLLocationManager *)manager 
didUpdateToLocation:(CLLocation *)newLocation 
       fromLocation:(CLLocation *)oldLocation {

NSLog(@"Did Update Location = %f / %f", [newLocation coordinate].latitude, [newLocation coordinate].longitude);

UIApplication*    app = [UIApplication sharedApplication];

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

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task.

    [self initTimer];

});
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {

[self.locationManager stopUpdatingLocation]; 
UIApplication*    app = [UIApplication sharedApplication];

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

// Start the long-running task and return immediately.
[self initTimer];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task.

});

}
Run Code Online (Sandbox Code Playgroud)

我也使计时器无效:

- (void)checkUpdates:(NSTimer *)timer{
UIApplication*    app = [UIApplication sharedApplication];
double remaining = app.backgroundTimeRemaining;
if(remaining < 580.0 && remaining > 570.0) {
    [self.timer invalidate];
    self.timer = nil;
    [self.locationManager startUpdatingLocation]; 
    [self.locationManager stopUpdatingLocation]; 
}
DbgLog(@"*************************Checking for updates!!!!!!!!!!! Reminaing %f", app.backgroundTimeRemaining);
}
Run Code Online (Sandbox Code Playgroud)

Hel*_*miB 10

对于其他任何有过一次噩梦的人试图解决这个问题,我有一个简单的解决方案.

  1. 研究raywenderlich.com的例子.示例代码工作正常,但不幸的是在后台位置没有计时器.这将无限期地运行.
  2. 使用此代码段添加计时器:

    -(void)applicationDidEnterBackground {
      [self.locationManager stopUpdatingLocation];
    
      UIApplication* app = [UIApplication sharedApplication];
    
      bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
      }];
    
      self.timer = [NSTimer scheduledTimerWithTimeInterval:intervalBackgroundUpdate
                                                    target:self.locationManager
                                                  selector:@selector(startUpdatingLocation)
                                                  userInfo:nil
                                                   repeats:YES];
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 只是不要忘记在info.plist中添加"应用寄存器以进行位置更新".

  • `bgTask`来自哪里? (3认同)
  • property(nonatomic)UIBackgroundTaskIdentifier bgTask; 在标题类中 (2认同)
  • @HelmiB:它不适用于**iOS 7**,你能推荐别的吗,我需要在后台启动locationmanger. (2认同)

scu*_*oni 9

经过几天尝试所有可能的解决方案,我终于能够使它工作.这是我的解决方案中的错误:

  • 我需要设置2个 UIBackgroundTaskIdentifiers,一个用于计时器,另一个用于locationManager

在我的解决方案上,只需添加:

UIApplication *app = [UIApplication sharedApplication];

bgTask2 = [app beginBackgroundTaskWithExpirationHandler:^{ 
[app endBackgroundTask:bgTask2]; 
bgTask2 = UIBackgroundTaskInvalid; }];

self.locationManager.delegate = self; 
[self.locationManager startUpdatingLocation]; 
Run Code Online (Sandbox Code Playgroud)

  • 你在哪种方法中添加这些行? (29认同)