如何永远在后台运行iOS核心位置

时间:2013-09-17 18:06:10

标签: ios

我正在为我们的办公室创建一个自定义应用程序。我希望这个应用程序每5分钟(或左右)获取用户的位置,并通过json将其发送到我们的服务器。我有它工作,但它不会在后台运行超过10分钟(我可以告诉)。

我在所需的后台模式中添加了“应用寄存器以进行位置更新”。

我的代码在AppDelegate中,如下所示:

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

NSLog(@"Became active");

// Start location services
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = 100.0f;
locationManager.delegate = self;

[locationManager stopMonitoringSignificantLocationChanges];
[locationManager startUpdatingLocation];

}


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


BOOL isInBackground = NO;
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
{
    isInBackground = YES;

}
NSLog(@"Location Manager isInBackground: %hhd", isInBackground);

if (isInBackground)
{
    [self sendBackgroundLocationToServer:newLocation];
}
else
{
    [self sendDataToServer:newLocation];
}

}


-(void) sendBackgroundLocationToServer:(CLLocation *)location
{

bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
    [[UIApplication sharedApplication] endBackgroundTask:bgTask];
}];

// Send the data
[self sendDataToServer:location];

if (bgTask != UIBackgroundTaskInvalid)
{
    [[UIApplication sharedApplication] endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}
}

-(void) sendDataToServer:(CLLocation *)newLocation
{
NSLog(@"Sending Data to Server");
// Get battery level
[[UIDevice currentDevice] setBatteryMonitoringEnabled:YES];
float batteryLevel = [[UIDevice currentDevice] batteryLevel];

float lat = newLocation.coordinate.latitude;
float lng = newLocation.coordinate.longitude;
NSLog(@"Accuracy: %f", newLocation.horizontalAccuracy);
NSString *userId = [[NSUserDefaults standardUserDefaults] stringForKey:@"userId"];
NSString *post = [[NSString alloc] initWithFormat:@"login_id=%@&latitude=%f&longitude=%f&speed=%f&course=%f&battery_level=%f&horizontal_accuracy=%f&vertical_accuracy=%f",
                  userId,
                  lat,
                  lng,
                  [newLocation speed],
                  [newLocation course],
                  batteryLevel,
                  newLocation.horizontalAccuracy,
                  newLocation.verticalAccuracy];

NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
NSString *urlstring = [NSString stringWithFormat:@"%@webservice/post_logins_location.php", kBaseURL];
[request setURL:[NSURL URLWithString:urlstring]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];

NSError *error;
NSURLResponse *response;
NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
jsonResults = [NSJSONSerialization JSONObjectWithData:urlData options:kNilOptions error:&error];
NSLog(@"GPS Send results: %@", jsonResults);

_lastSentUpdateAt = [NSDate date];
}

我也尝试过startMonitoringSignificantLocationChanges并完全删除_lastSentUpdateAt。但是我仍然得到相同的结果。我现在的问题是,json可以在10分钟后从后台发送数据吗?现在我的手机已经运行了一个多小时,我的应用程序的位置服务图标仍处于活动状态。但是,我没有看到任何数据在我的服务器上发生更新。一旦我真正打开我的应用程序,它确实收到更新,这让我相信在后台发送数据时出现问题。或者还有其他事情发生了吗?

1 个答案:

答案 0 :(得分:2)

阅读文档并观看与“注册重要位置更新”相关的WWDC演示文稿。他们对官方推荐的做法进行了改进和改变,同时对功耗进行了谨慎处理。

具体而言,无法以指定的时间间隔获取背景位置。重要的位置更新由操作系统自行决定,并受到应用程序无法控制的许多因素的影响。

如果您要做的就是让应用程序不在后台终止,您需要在应用程序的plist中声明这种背景模式。它位于Xcode的“Info”下,我想是“应用寄存器进行位置更新”。