了解用户在iOS中的位置跟踪

时间:2013-02-24 16:31:42

标签: ios background core-location cllocationmanager

当应用程序转到后台时,我需要不断获取用户的位置更新,正如我在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分钟的有限长度任务吗?

拜托,我需要帮助解决这个问题。提前致谢

3 个答案:

答案 0 :(得分:2)

您只需在“所需背景模式”下添加“应用寄存器以进行位置更新”,您可以在文本编辑器中编辑plist文件并添加以下代码,也可以使用xcode添加所需的背景模式。

<key>UIBackgroundModes</key>
<array>
    <string>location</string>
</array>

将调用didUpdateToLocation方法(即使您的应用程序处于后台)。您可以在此方法调用的基础上执行任何操作...

Xcode快照

Snapshot of 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