iOS后台位置不发送http请求

我的应用需要在后台跟踪用户位置,但无法发送“获取”请求。 当应用程序到达前台时,http请求会立即发送。 我正在使用RestKit来处理所有网络请求,我按照本教程设置了我的后台位置服务。 在我的applicationDidEnterBackground中

-(void)applicationDidEnterBackground:(UIApplication *)application { self.bgLocationManager = [[CLLocationManager alloc] init]; self.bgLocationManager.delegate = self; [self.bgLocationManager startMonitoringSignificantLocationChanges]; NSLog(@"Entered Background"); } 

我在我的applicationDidBecomeActive委托中停止监视SignignantLocationChange

这是我的locationManager委托,我接受新的更新位置并发送到我的服务器

 -(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { NSLog(@"I am in the background"); bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{ [[UIApplication sharedApplication] endBackgroundTask:bgTask]; }]; // ANY CODE WE PUT HERE IS OUR BACKGROUND TASK NSString *currentLatitude = [[NSString alloc] initWithFormat:@"%g", newLocation.coordinate.latitude]; NSString *currentLongitude = [[NSString alloc] initWithFormat:@"%g", newLocation.coordinate.longitude]; NSString *webToken = [[NSUserDefaults standardUserDefaults] stringForKey:@"userWebToken"]; NSLog(@"I am in the bgTask, my lat %@", currentLatitude); NSDictionary *queryParams; queryParams = [NSDictionary dictionaryWithObjectsAndKeys:webToken, @"auth_token", currentLongitude, @"lng", currentLatitude, @"lat", nil]; RKRequest* request = [[RKClient sharedClient] post:@"/api/locations/background_update" params:queryParams delegate:self]; //default is RKRequestBackgroundPolicyNone request.backgroundPolicy = RKRequestBackgroundPolicyContinue; // AFTER ALL THE UPDATES, close the task if (bgTask != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; } } 

网络请求按计划运行,但不会在后台调用。 我还需要其他步骤吗? 在我的info.plist中,我有必需的背景模式键和位置服务作为值。

编辑

我也提到了过去的答案 。 我通过在didUpdateToLocation调用中放置日志来运行一些测试,并且它们都被调用但是没有发送’get’请求。 相反,当我最终将应用程序启动到前台时,它会发送所有构建的网络请求(超过10个)。

编辑(2)我在我的请求中添加了RKRequestBackgroundPolicyContinue,但它没有改变我的结果。 (正如您在restkit的后台上传/下载中所见)。 我看到Restkit初始化主机但未能发送请求,直到应用程序变为活动状态。

回答

RestKit必须做一些在后台禁止的事情。 使用NSURLRequest非常有效。

 NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.example.com/api/locations/background_update"]]; [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [urlRequest setHTTPMethod:@"POST"]; [urlRequest setHTTPBody:jsonData]; NSHTTPURLResponse *response = nil; [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error]; 

可以使用同步请求,因为没有UI可以中断后台任务

重新创建原始建议作为答案

您是否尝试使用库存同步NSURLConnection替换您的restKit调用? – dklt 9月20日

我使用与你完全相同的代码,它在RestKit中适用于我。 我可以使它工作的唯一方法是创建一个同步请求(无论如何在这个上下文中异步执行它没有多大意义!)。 请检查此代码,并告知我们是否有效:

 // REMEMBER. We are running in the background if this is being executed. // We can't assume normal network access. // bgTask is defined as an instance variable of type UIBackgroundTaskIdentifier // Note that the expiration handler block simply ends the task. It is important that we always // end tasks that we have started. _bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{ [[UIApplication sharedApplication] endBackgroundTask:_bgTask]; }]; // ANY CODE WE PUT HERE IS OUR BACKGROUND TASK // For example, I can do a series of SYNCHRONOUS network methods (we're in the background, there is // no UI to block so synchronous is the correct approach here). NSNumber *latNumber = [NSNumber numberWithDouble:location.coordinate.latitude]; NSNumber *lngNumber = [NSNumber numberWithDouble:location.coordinate.longitude]; NSNumber *accuracyNumber = [NSNumber numberWithDouble:location.horizontalAccuracy]; NSDictionary *params = [NSDictionary dictionaryWithKeysAndObjects:@"lat",latNumber,@"lng",lngNumber,@"accuracy",accuracyNumber, nil]; RKURL *URL = [RKURL URLWithBaseURL:[NSURL URLWithString:SERVER_URL] resourcePath:@"/user/location/update" queryParameters:params]; RKRequest *request = [RKRequest requestWithURL:URL]; request.method = RKRequestMethodGET; NSLog(@"Sending location to the server"); RKResponse *response = [request sendSynchronously]; if (response.isFailure) NSLog(@"Unable to send background location, failure: %@", response.failureErrorDescription); else { NSError *error = nil; NSDictionary *parsedBody = [response parsedBody:&error]; if (YES == [[parsedBody objectForKey:@"result"] boolValue]){ NSLog(@"Background location sent to server"); } else { //Something went bad NSLog(@"Failed to send background location"); } } // AFTER ALL THE UPDATES, close the task if (_bgTask != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:_bgTask]; _bgTask = UIBackgroundTaskInvalid; } 

我几乎可以肯定,为你的RKClient请求生成的新线程会在调用后自动终止。

当您的应用程序在后台运行时,您可以完成在进入后台之前启动的HTTP请求,但无法发起请求。 您只能在后台启动某些网络操作 (voip,报亭)。