How to get location in background even after phone restart in swift?

蓝咒 提交于 2019-12-06 11:10:47

问题


I'm developing an application which is tracking the location of the phone on time interval chosen by the user. I made it with timer which starts startUpdatingLocation, when it get the location stops updating sends the location to the server and starts timer again. Everything is done in background. I need to get location data in background mode (in iOS 8) even after phone restarts and send the data to a server. I tried hundreds methods and no one works for me. So ... what i've got at this moment: In info.plist:

  • Required background modes - location and fetch
  • NSLocationAlwaysUsageDescription - Location is required for this application to work properly

In 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 ....");

    }
}

Everything seems to work (when app is in foreground or background/inactive) except when the phone was restarted or user terminate application. I think I'm doing something wrong and iOS does not wake up the application. How can I do it, and if I can do it somehow is there a way so get the location in time period chosen by the user (30 minutes, 1 hour ...). Thanks in advance!


回答1:


While moving to background or when app terminated call this method

startMonitoringSignificantLocationChanges();

So if you reboot your device or app got killed, whenever there is significant location change in your location, OS will launch your app in background.

As per apple document

If you start this service and your app is subsequently terminated, the system automatically relaunches the app into the background if a new event arrives. In such a case, the options dictionary passed to the application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions: methods of your app delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your app was launched because of a location event. Upon relaunch, you must still configure a location manager object and call this method to continue receiving location events. When you restart location services, the current event is delivered to your delegate immediately. In addition, the location property of your location manager object is populated with the most recent location object even before you start location services.




回答2:


What you want is no longer possible. As of iOS7, an application will only be kept alive in the background to receive locations if it was launched into the foreground by the user, not by the system (such as via a significant location change event). This change was mentioned briefly in in one of the talks at WWDC '13, probably the one titled "What's New in Core Location".

I had an app with this functionality, and it broke in iOS7. I spoke with Apple developer support, and they confirmed the change. The project I was working on was a origin-destination survey intended for an academic study; our solution ended up being to keep a set of local notifications, and regularly update their fire times into the future while we are running; if we ever stop running the user gets a notification to relaunch the app.

Be aware, as well, that if you ever tell core location to stop updating your location, you will not be able to turn that back on until you are again launched into the foreground by the user. The solution we used here is a combination of deferred location updates, and of turning the 'desired accuracy' way up, so that the phone isn't powering on the GPS or wifi antennas when it isn't necessary. This isn't ideal, obviously, but our battery performance has managed to be more reasonable then I had expected.



来源:https://stackoverflow.com/questions/27361561/how-to-get-location-in-background-even-after-phone-restart-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!