即使在暂停时也能获取 iOS 应用的位置更新

Posted

技术标签:

【中文标题】即使在暂停时也能获取 iOS 应用的位置更新【英文标题】:Get Location Updates for iOS App Even when Suspended 【发布时间】:2015-01-02 13:01:18 【问题描述】:

2014 年初,Apple 已将 ios 7.0 更新至 7.1,以便即使应用程序在前台和后台未处于活动状态时也能进行位置更新。我们如何做到这一点?

我读过一些类似Apple's iOS 7.1 will fix a geolocation bug 的文章。但苹果没有提供与此相关的太多沟通,也没有提供任何关于如何获取位置更新的示例代码,即使应用程序被终止/终止/暂停也是如此。

我已阅读Release Notes for iOS 7.1。我也找不到与此相关的任何内容。

那么,即使应用程序暂停,我们如何实际获取 iOS 7 和 8 的位置更新?

【问题讨论】:

【参考方案1】:

通过试验 Core Location 框架经过数月的试验和错误,我找到了即使在应用程序被终止/暂停时也能获取位置更新的解决方案。它适用于 iOS 7 和 8。

这是解决方案:-

如果您的应用是基于位置的移动应用,需要在设备发生重大变化时监控设备的位置,则当设备从最后一个已知位置移动超过 500 米时,iOS 会返回一些位置坐标。是的,即使应用程序被用户或 iOS 本身杀死/暂停,您仍然可以获得位置更新。

所以为了让locationManager即使在应用程序被杀死/暂停时也能获得位置更新,你必须使用startMonitoringSignificantLocationChanges方法,你不能使用startUpdatingLocation

当 iOS 想要将位置更新返回给应用程序时,它会帮助您重新启动应用程序并将密钥 UIApplicationLaunchOptionsLocationKey 返回到应用程序委托方法 didFinishLaunchingWithOptions

密钥UIApplicationLaunchOptionsLocationKey非常重要,你必须知道如何处理它。您必须在收到密钥时创建一个新的 locationManager 实例,您将在 locationManager 委托方法didUpdateLocations 上获得位置更新。

这里是示例代码:-

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    self.shareModel = [LocationShareModel sharedModel];

    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey])  
      self.shareModel.anotherLocationManager = [[CLLocationManager alloc]init];
      self.shareModel.anotherLocationManager.delegate = self;
      self.shareModel.anotherLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
      self.shareModel.anotherLocationManager.activityType = CLActivityTypeOtherNavigation;

      if(IS_OS_8_OR_LATER) 
        [self.shareModel.anotherLocationManager requestAlwaysAuthorization];
      

     [self.shareModel.anotherLocationManager startMonitoringSignificantLocationChanges];   

        
        return YES;
 

除了didFinishLaunchingWithOptions 方法之外,我还在应用程序处于活动状态时创建了locationManager 实例。以下是一些代码示例:

- (void)applicationDidEnterBackground:(UIApplication *)application

    [self.shareModel.anotherLocationManager stopMonitoringSignificantLocationChanges];

    if(IS_OS_8_OR_LATER) 
        [self.shareModel.anotherLocationManager requestAlwaysAuthorization];
    

    [self.shareModel.anotherLocationManager startMonitoringSignificantLocationChanges];


- (void)applicationDidBecomeActive:(UIApplication *)application

    if(self.shareModel.anotherLocationManager)
        [self.shareModel.anotherLocationManager stopMonitoringSignificantLocationChanges];

    self.shareModel.anotherLocationManager = [[CLLocationManager alloc]init];
    self.shareModel.anotherLocationManager.delegate = self;
    self.shareModel.anotherLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
    self.shareModel.anotherLocationManager.activityType = CLActivityTypeOtherNavigation;

    if(IS_OS_8_OR_LATER) 
        [self.shareModel.anotherLocationManager requestAlwaysAuthorization];
    

    [self.shareModel.anotherLocationManager startMonitoringSignificantLocationChanges];

我写了一篇文章,详细解释了如何在 iOS 7 和 8 中获取位置更新,即使应用程序被终止/挂起。我还在 GitHub 上上传了完整的源代码,其中包含有关如何测试此解决方案的步骤。

请访问以下网址了解更多信息:-

    Getting Location Updates for iOS 7 and 8 when the App is Killed/Terminated/Suspended Source Code on GitHub - Get the Location Updates Even when the iOS mobile apps is Suspended/Terminated/Killed

【讨论】:

“您必须在收到密钥时创建一个新的 locationManager 实例” - 听起来有点混乱,您的意思是“新的 locationManager 实例”吗?我的项目中有一个 locationManager 的共享实例 - 我可以重复使用它吗? 好问题。当应用程序被挂起时,您之前创建的共享 locationManager 也会从内存中清除。如何重用内存中不存在的实例?因此,创建一个新实例是唯一的方法。 嗨瑞奇,很好的答案。只有一个问题:可以将相同的方法应用于标准位置管理器,而不仅仅是重大变更位置管理器吗? 是否可以在应用终止时或仅在 .plist 文件中保存位置和日志以及核心数据? @Ricky,感谢您的解释。这部分的文档记录很差。但是,我不明白为什么当应用程序进入后台时您会停止并重新开始重大的位置更改,以及为什么在应用程序再次激活时重新创建它。它是强制性的,只是双重预防吗?【参考方案2】:
locationManager = [[CLLocationManager alloc] init];
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)


if(IS_OS_8_OR_LATER)

    [locationManager requestWhenInUseAuthorization];


locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; //whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;

[locationManager startUpdatingLocation];

该代码用户位置更新仅适用于后台应用程序运行而不是后台运行

[locationManager requestWhenInUseAuthorization];

【讨论】:

以上是关于即使在暂停时也能获取 iOS 应用的位置更新的主要内容,如果未能解决你的问题,请参考以下文章

当应用程序被终止/终止/暂停时,cordova 获取 iOS 7 和 8 的位置更新

即使应用程序处于终止状态或被杀死,如何在 iOS 中获取位置更新? [复制]

即使应用程序被杀死/终止,位置更新

即使应用程序被杀死/终止,位置更新

在后台模式和终止模式下获取位置更新 IOS

即使在终止应用程序后,我们还能获取位置信息吗? [关闭]