0

I'd like to capture an iOS user's location every time my app receives a push notification, even when the screen is off or the app is running in the background. It's important that the location be high-accuracy and captured immediately on delivery of the notification. (I'd then like to post the location back to a server, with the app still in the background.)

Is this possible to do in iOS? I'm new to the platform and have seen a lot of confusing information that indicates that at least parts of this are possible, but I'm not sure whether the entire thing is. I also found some resources (e.g. this question iOS App Background Location (Push Notifications)) but it's from four years ago and I know a lot has changed with recent iOS releases.

Community
  • 1
  • 1
sfdev941
  • 1
  • 3
  • A solution could be to keep fetching location data in background and use it notification arrives. To keep fetching location in background: http://stackoverflow.com/a/24666487/548403 – Varun Singh Sep 25 '16 at 06:00

1 Answers1

0

Yes, this is possible: in your AppDelegate didFinishLaunchingWithOptions, check if launched from notification (received APN while in background) and then start location services. When you receive a location, send that to the backend and then shut down location services. Bear in mind that in general there will be some delay before the system returns a location but this should be doable in the amount of time that you have before the app sleeps again. There are some ways to get additional background processing time if need be.

// untested code, ignores all of the boilerplate Location Services Authorization code and request user permission to Location services
var locationManager: CLLocationManager?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Check if launched from notification (received APN while in background)
    if let notification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [String: AnyObject] {
        let aps = notification["aps"] as! [String: AnyObject]
        print("received background apn, aps: \(aps)")

        locationManager = CLLocationManager()
        locationManager!.delegate = self
        locationManager!.startUpdatingLocation()    // this is what starts the location services query
    }

    ...

    return true
}


func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let location = locations[0]

    // here is where you would send location to your backend

    // shut down location services:
    locationManager?.stopUpdatingLocation()
    locationManager?.delegate = nil
    locationManager = nil
}
hungri-yeti
  • 584
  • 1
  • 5
  • 6
  • It looks like in iOS 10, a notification service extension can be used to run custom code every time a notification arrives. Would this be preferred to the above method? Which method is more likely to work reliably across device reboots, app force-quits, etc? – sfdev941 Dec 07 '16 at 18:36
  • Are you talking about `UNLocalNotificationTrigger`? I don't have any experience with that yet. – hungri-yeti Dec 16 '16 at 15:00