Iphone iOS后台位置未发送http请求
我的应用程序需要在后台跟踪用户位置,但无法发送“获取”请求。当应用程序到达前台时,会立即发送http请求。我正在使用RestKit处理我的所有网络请求,并按照它设置了我的后台位置服务。 在我的应用程序标识符背景中Iphone iOS后台位置未发送http请求,iphone,ios,ios5,nsurlconnection,restkit,Iphone,Ios,Ios5,Nsurlconnection,Restkit,我的应用程序需要在后台跟踪用户位置,但无法发送“获取”请求。当应用程序到达前台时,会立即发送http请求。我正在使用RestKit处理我的所有网络请求,并按照它设置了我的后台位置服务。 在我的应用程序标识符背景中 -(void)applicationDidEnterBackground:(UIApplication *)application { self.bgLocationManager = [[CLLocationManager alloc] init]; self.bgL
-(void)applicationDidEnterBackground:(UIApplication *)application
{
self.bgLocationManager = [[CLLocationManager alloc] init];
self.bgLocationManager.delegate = self;
[self.bgLocationManager startMonitoringSignificantLocationChanges];
NSLog(@"Entered Background");
}
我停止监视ApplicationIDBecomeActive委托中的重要位置更改
这是我的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可以中断后台任务当应用程序在后台运行时,您可以完成在进入后台之前启动的HTTP请求,但无法启动新请求。您只能在后台启动(voip、报摊)。重新创建原始建议作为答案
您是否尝试将restKit调用替换为库存同步NSURLConnectiondklt 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请求生成的新线程在调用后会自动终止。感谢您的回答,我仍然看到有关此主题的冲突信息。看看这个过去的答案,@KyleC他说的是,如果你发现你的HTTP请求(你在前台启动的)在你的应用程序终止之前没有完成,那么你应该使用beginBackgroundTaskWithExpirationHandler:方法请求额外的时间来完成请求。此方法允许您在首次进入后台时有额外的时间来完成您已启动并希望完成的任何任务,但在此状态下无法启动新的HTTP请求,我发现这段时间从5秒到10分钟不等。我理解这一部分,并且我知道beginBackgroundTaskWithExpirationHandler:方法用于在应用程序进入后台时完成更长时间的运行任务。然而,他的回答表明,你的应用程序在后台状态下被显著的位置更改唤醒,可以使用beginBackgroundTaskWithExpirationHandler:在后台完成http请求。哦,酷!我从那个事件中没有意识到这是可能的。您是否尝试过用共享同步NSURLConnection替换restKit调用?我同意dklt的问题,因为调用
[[RKClient sharedClient]post:params:delegate:]
正在导致一些可能在后台GCD队列中发生的事件,这些事件不在您的backgroundTask括号中…并且获取数据的同步调用可能有助于在后台任务中发送请求。是的,RKRequestBackgroundPolicyContinue可能要处理这个问题,但实际上直到调用post:params:delegate:,您才开始设置它,到那时,可能已经太晚了。@dklt我能够让它与NSURLConnection请求一起工作,感谢您的建议。如果你给我答复,我就接受。