1

Is it possible to use CoreLocation framework in UNNotificationServiceExtension? What I've tried:

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?
    private let locationManager = CLLocationManager()

    override func didReceive(_ request: UNNotificationRequest,
                             withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        os_log("%{public}@",
        log: OSLog(subsystem: "bundleIdentifier", category: "WakeUpExtension"),
        type: OSLogType.debug,
        "Push received")
        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()

        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    }

    override func serviceExtensionTimeWillExpire() {
        os_log("%{public}@",
        log: OSLog(subsystem: "bundleIdentifier", category: "WakeUpExtension"),
        type: OSLogType.debug,
        "Task expired")
        locationManager.stopUpdatingLocation()
        locationManager.delegate = nil

        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }

}
extension NotificationService: CLLocationManagerDelegate {

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        locations.forEach {
            os_log("%{public}@",
            log: OSLog(subsystem: "bundleIdentifier", category: "WakeUpExtension"),
            type: OSLogType.debug,
            $0.horizontalAccuracy)
        }

        for location in locations {
            let locationAge = -location.timestamp.timeIntervalSinceNow
            if locationAge < 5 {
                os_log("%{public}@",
                log: OSLog(subsystem: "bundleIdentifier", category: "WakeUpExtension"),
                type: OSLogType.debug,
                "Send")
                locationManager.stopUpdatingLocation()
                locationManager.delegate = nil
                contentHandler?(UNNotificationContent())
            }
        }
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        os_log("%{public}@",
        log: OSLog(subsystem: "bundleIdentifier", category: "WakeUpExtension"),
        type: OSLogType.debug,
        error.localizedDescription)
    }
}

All I've got in Console is: enter image description here

BadCodeDeveloper
  • 455
  • 5
  • 24
  • I don't think you will be able to access the user's location in an extension context. However, you can use `requestLocation` for a one shot location rather than trying to start & stop location updates. – Paulw11 May 14 '20 at 11:52
  • @Paulw11 Do you mean use `requestLocation` inside main app or push extension? I've tried to use this method in extension with the same result – BadCodeDeveloper May 14 '20 at 12:07
  • Yeah, I suspect that you can’t use location in an extension – Paulw11 May 14 '20 at 12:19

2 Answers2

0

Looks like CLLocationManagerDelegate methods never gets called in UNNotificationServiceExtension. But it is possible to get last received location from the CLLocationManager location property:

 let locationManager = CLLocationManager()
 let lastLocation = locationManager.location
BadCodeDeveloper
  • 455
  • 5
  • 24
0

You need to implement a background url session. It helps delay the extension expiry, in this case till the location update is delivered (and any other post process that is written).

private lazy var urlSession: URLSession = {
    let config = URLSessionConfiguration.background(withIdentifier: "MySession")
    config.sessionSendsLaunchEvents = true
    return URLSession(configuration: config, delegate: self, delegateQueue: nil)
}()

Reference: https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_in_the_background

Preema
  • 1
  • 1