如果在swift手机重启后如何在后台获取位置?

时间:2014-12-08 15:45:26

标签: ios swift cllocationmanager

我正在开发一个应用程序,该应用程序在用户选择的时间间隔内跟踪电话的位置。我使用计时器启动startUpdatingLocation,当它获得位置停止更新时,将位置发送到服务器并再次启动计时器。一切都在后台完成。 我需要在手机重启后以后台模式(在iOS 8中)获取位置数据并将数据发送到服务器。我尝试了数百种方法,没有人适合我。那么......我现在得到的是: 在info.plist中:

  • 所需的背景模式 - 位置和提取
  • NSLocationAlwaysUsageDescription - 此应用程序需要位置才能正常工作

在AppDelegate中:

    var locationController: LocationController = LocationController() as LocationController;

func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {

    UIApplication.sharedApplication().setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum);

    var bgTask = UIBackgroundTaskIdentifier()
    bgTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { () -> Void in
        UIApplication.sharedApplication().endBackgroundTask(bgTask)
    }

    if(self.locationController.profileForTracking != nil && self.locationController.profileForTracking != "Disabled" && self.locationController.intervalForTracking != nil && self.locationController.trackingAllowed == true){
        self.locationController.initLocationManager();

        if(self.locationController.timer != nil){
            self.locationController.timer = self.locationController.timer;
        } else {
            self.locationController.startTimerForLocationUpdate();
        }

        println("Location can now start ....");

    }


    return true
}

func application(application: UIApplication!, performFetchWithCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)!) {

    var bgTask = UIBackgroundTaskIdentifier()
    bgTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { () -> Void in
        UIApplication.sharedApplication().endBackgroundTask(bgTask)
    }

    if(self.locationController.profileForTracking != nil && self.locationController.profileForTracking != "Disabled" && self.locationController.intervalForTracking != nil && self.locationController.trackingAllowed == true){
        self.locationController.initLocationManager();

        if(self.locationController.timer != nil){
            self.locationController.timer = self.locationController.timer;
        } else {
            self.locationController.startTimerForLocationUpdate();
        }

        println("Location can now start ....");

    }
}

除非重新启动手机或用户终止应用程序,否则一切似乎都有效(当应用程序处于前台或后台/非活动状态时)。我认为我做错了什么,iOS不会唤醒应用程序。我怎么能这样做,如果我能以某种方式做到这一点,那么就可以获得用户选择的时间段(30分钟,1小时......)。提前谢谢!

2 个答案:

答案 0 :(得分:2)

在移至后台或应用终止时调用此方法

startMonitoringSignificantLocationChanges();

因此,如果您重新启动设备或应用程序被杀,只要您的位置发生重大位置更改,操作系统就会在后台启动您的应用。

根据苹果文件

  

如果您启动此服务并且您的应用随后被终止,则   如果是新的,系统会自动将应用重新启动到后台   事件到了。在这种情况下,选项字典传递给了   应用程序:willFinishLaunchingWithOptions:和   application:didFinishLaunchingWithOptions:你的应用程序的方法   delegate包含密钥UIApplicationLaunchOptionsLocationKey   表示您的应用因位置事件而启动。上   重新启动,您仍然必须配置位置管理器对象并调用   此方法继续接收位置事件。当你重新启动   位置服务,当前事件将传递给您的代理人   立即。此外,您所在位置的位置属性   管理器对象甚至填充了最新的位置对象   在开始定位服务之前。

答案 1 :(得分:1)

你想要的是不再可能的。从iOS7开始,如果应用程序由用户启动到前台而不是由系统启动(例如通过重要的位置更改事件),则应用程序将仅在后台保持活动状态以接收位置。在WWDC '13的一次谈话中简要提到了这一变化,可能是题为“核心位置有什么新内容”的谈话。

我有一个具有此功能的应用程序,它在iOS7中崩溃了。我采访了Apple开发者支持,他们确认了这一变化。我正在进行的项目是一项旨在进行学术研究的始发地 - 目的地调查;我们的解决方案最终是保留一组本地通知,并在我们运行时定期更新他们的火灾时间;如果我们停止运行,用户会收到重新启动应用程序的通知。

同时请注意,如果您告诉核心位置停止更新您的位置,则在用户再次启动到前台之前,您将无法重新打开它。我们在这里使用的解决方案是延迟位置更新和提高“所需精度”方式的组合,以便在没有必要时手机不会启动GPS或wifi天线。显然,这并不理想,但我们的电池性能比我预期的更合理。