iOS 在通知服务扩展中获取用户位置
iOS Get user location in Notification Service Extension
是否可以在 UNNotificationServiceExtension
中使用 CoreLocation
框架?
我尝试过的:
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,
[=12=].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)
}
}
我在控制台中得到的是:
看起来 CLLocationManagerDelegate
方法从未在 UNNotificationServiceExtension
中调用过。但是可以从 CLLocationManager
位置 属性:
获取最后接收到的位置
let locationManager = CLLocationManager()
let lastLocation = locationManager.location
您需要实施后台 url 会话。它有助于延迟扩展到期,在这种情况下,直到交付位置更新(以及任何其他写入的 post 进程)。
private lazy var urlSession: URLSession = {
let config = URLSessionConfiguration.background(withIdentifier: "MySession")
config.sessionSendsLaunchEvents = true
return URLSession(configuration: config, delegate: self, delegateQueue: nil)
}()
是否可以在 UNNotificationServiceExtension
中使用 CoreLocation
框架?
我尝试过的:
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,
[=12=].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)
}
}
我在控制台中得到的是:
看起来 CLLocationManagerDelegate
方法从未在 UNNotificationServiceExtension
中调用过。但是可以从 CLLocationManager
位置 属性:
let locationManager = CLLocationManager()
let lastLocation = locationManager.location
您需要实施后台 url 会话。它有助于延迟扩展到期,在这种情况下,直到交付位置更新(以及任何其他写入的 post 进程)。
private lazy var urlSession: URLSession = {
let config = URLSessionConfiguration.background(withIdentifier: "MySession")
config.sessionSendsLaunchEvents = true
return URLSession(configuration: config, delegate: self, delegateQueue: nil)
}()