【问题标题】:Understanding background tracking of user's location in iOS了解iOS中用户位置的后台跟踪
【发布时间】:2013-02-09 19:44:49
【问题描述】:

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

拜托,我需要有关此问题的帮助。提前致谢

【问题讨论】:

    标签: ios background core-location cllocationmanager


    【解决方案1】:

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

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

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

    Xcode 快照

    【讨论】:

    • 这并没有解决原始发帖人的问题。设置 UIBackgroundModes 可以获得更新,但它不允许您有足够的处理时间来实际建立网络连接并进行实际工作。而且 backgroundTimeRemaining 仍然是一个巨大的数字,表明它没有被设置,即使你在你的位置处理方法中创建了一个后台任务。我的经验是我的后台操作在几秒钟内就被杀死了。
    • 对不起,我不同意,我的一个应用程序在 App Store 上运行,它在后台位置更新的基础上做了很多事情(网络访问、数据操作和发送本地通知等) .我猜(可能是错误的)您的评论是基于假设/知识而不是这种特殊情况的经验,或者如果您在处理类似情况时遇到问题,您可能做错了什么。
    【解决方案2】:

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

    您可能还需要在 applicationWillEnterForeground 方法中调用 stopUpdatingLocation(以防应用在前台时不需要接收位置更新)。

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

    【讨论】:

    • 一个设计问题:如果我想在应用程序在前台时也能够监听位置更新并将它们显示在地图上,那么最好的方法应该是什么?我应该将locationManager 实例保留在AppDelegate 中并在前台模式下向viewControllers 发送通知吗?
    • 在后台更新位置是否需要locationManager 及其在AppDelegate 中的委托方法,或者是否有可能/正确/最佳解决方案让另一个类实例具有自己的@ 987654325@和delegate方法,然后让AppDelegate随便创建?
    【解决方案3】:

    免责声明:我为 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-14
      相关资源
      最近更新 更多