2

当应用程序进入后台时,我需要不断获取用户的位置更新,正如我在 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:触发时执行一些其他有限长度任务。我已经设置了in的location值。我的方法正确吗?我是否会无限期地更新位置,然后我是否可以在每次收到更新时执行少于 10 分钟的有限长度任务?UIBackgroundModesInfo.plist

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

4

3 回答 3

2

您所要做的就是在“所需的后台模式”下添加“用于位置更新的应用程序寄存器”,您可以在文本编辑器中编辑 plist 文件并添加以下代码,也可以使用 xcode 添加所需的后台模式。

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

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

Xcode 的快照

Xcode 的快照

于 2013-03-05T12:37:15.477 回答
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

于 2014-10-27T00:21:11.913 回答
0

根据您提供的代码,您在 applicationDidEnterBackground 上分配 LocationManager,我建议您在 didFinishLaunchingWithOptions 方法中分配 LocationManager,然后在 applicationDidEnterBackground 方法中调用 startUpdatingLocation 方法。

您可能还需要在 applicationWillEnterForeground 方法中调用 stopUpdatingLocation (如果您不需要在应用程序处于前台时接收位置更新)。

提示:不要长时间以最佳精度启用 GPS,因为它会很快耗尽您的电池(根据我的经验,在 3 到 4 小时内)。

于 2013-03-05T12:58:56.753 回答