当应用程序转到后台时,我需要不断获取用户的位置更新,正如我在Apple的文档中所发现的那样,这是允许实施的长期运行后台任务之一。我还需要进行一些处理和网络调用,以便在通知位置更新时向服务器发送一些信息。我粗略地试图做的是这样的事情:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Background task
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Background time remaining: %f seconds (%d mins)",
[[UIApplication sharedApplication] backgroundTimeRemaining],
(int)([[UIApplication sharedApplication] backgroundTimeRemaining] / 60));
// Need to get data from database here
// Finished
if (bgTask != UIBackgroundTaskInvalid) {
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
// Start location manager
locationManager = [[CLLocationManager alloc] init];
if ([CLLocationManager locationServicesEnabled]) {
locationManager.delegate = self;
locationManager.distanceFilter = 20;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Want to perform some data processing here, including concurrent tasks
// and several network calls to get and send data to server
[self locationProcessingCompleted];
});
}
- (void)locationProcessingCompleted
{
// Check results. If needed, some more data processing and several network
// calls to send data to server
// Close background task
if (bgTask != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
}
我找不到有关位置服务的长期运行后台任务的任何代码示例,我有几个问题:
a)是否有必要在dispatch_async
队列中执行所有后台代码?换句话说,applicationDidEnterBackground:
中的所有代码是否异步执行,包括位置管理器设置?
b)[[UIApplication sharedApplication] backgroundTimeRemaining]
返回一个非常长的值。这个时间不应该是10分钟左右?
c)我想这样做:执行初始有限长度任务,开始位置更新,然后每次触发didUpdateToLocation:
时执行一些其他有限长度任务。我在location
中设置了UIBackgroundModes
的{{1}}值。我的方法是否正确?我是否会无限期地更新位置,然后我可以在收到每次更新时执行长度不超过10分钟的有限长度任务吗?
拜托,我需要帮助解决这个问题。提前致谢
答案 0 :(得分:2)
您只需在“所需背景模式”下添加“应用寄存器以进行位置更新”,您可以在文本编辑器中编辑plist文件并添加以下代码,也可以使用xcode添加所需的背景模式。
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
将调用didUpdateToLocation方法(即使您的应用程序处于后台)。您可以在此方法调用的基础上执行任何操作...
Xcode快照
答案 1 :(得分:0)
根据您提供的代码,您在applicationDidEnterBackground上分配LocationManager,我建议您在didFinishLaunchingWithOptions方法中分配LocationManager,然后在applicationDidEnterBackground方法中调用startUpdatingLocation方法。
您可能还需要在applicationWillEnterForeground方法中调用stopUpdatingLocation(如果app在前台时您不需要接收位置更新)。
提示:长时间不要以最高精度启用GPS,因为它会很快耗尽电池(根据我的经验,在3到4小时内)。
答案 2 :(得分:0)
免责声明:我为Cintric工作
我们还希望能够在后台准确跟踪用户位置(即使应用程序被杀死后也是如此)。我们花了很长时间解决这个问题,特别是关注电池耗尽。
我们发布了一篇关于我们如何解决它的博文。 http://www.blog.cintric.com/?p=121并且还免费提供拖放SDK解决方案。使用一行代码,您可以在后台持续跟踪位置,并且只使用1%的电池。此外,您可以将一个类设置为它的委托,这样您就可以将信息发送到您的服务器(包括在后台,而无需使用后台任务API)。
您可以下载.framework文件,将其拖入项目并使用一行代码进行初始化:
[CintricFind initWithApiKey:@"YOUR_API_KEY_HERE" andSecret:@"YOUR_SECRET_HERE"];
您可以免费获得API密钥。这里有文档解释每一个:https://www.cintric.com/docs/ios