有人在 iOS 中实现了后台位置更新吗?下面是我的场景,任何帮助都会很棒
问题陈述
到目前为止我尝试过的是
启用后台模式、位置更新、后台获取和后台处理
创建了一个用于位置跟踪的单例,检查下面的代码并调用此类
didFinishLaunchingWithOptions - AppDelegate
现在我也探索了 BakcgroundTasks,但后台任务已注册,但在给定的时间间隔后没有执行,请检查下面的代码
class EmployeeAttendanceTracker: NSObject,CLLocationManagerDelegate {
static let shared = EmployeeAttendanceTracker()
private let locationManager = CLLocationManager()
private var lastLocationDate = Date()
static let LOCATION_INTERVAL = 1
var locationUpdate: (() -> Void)?
private override init() {
super.init()
setupLocationManager()
}
private func setupLocationManager() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.activityType = .other
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.showsBackgroundLocationIndicator = true
if #available(iOS 9.0, *) {
locationManager.requestAlwaysAuthorization()
} else {
locationManager.requestWhenInUseAuthorization()
}
}
//
//
// // MARK: - CLLocationManagerDelegate
//
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
//showLocationPermissionAlert()
Logger.s("Location access restricted.")
case .denied:
//showLocationPermissionAlert()
Logger.s("User denied location access.")
case .notDetermined:
// showLocationPermissionAlert()
Logger.s("Location access not determined.")
case .authorizedAlways:
if #available(iOS 9, *) {
locationManager.requestLocation()
} else {
locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()
}
default:
// showLocationPermissionAlert()
break
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
Logger.s("User latitude: \(location.coordinate.latitude), longitude: \(location.coordinate.longitude)")
locationManager.stopUpdatingLocation()
let now = Date()
if isItTime(now: now as NSDate) {
if shouldSendLocationToServer() {
self.sendLocationToServer(location: location,completion: {
self.locationUpdate?()
})
}else{
self.locationUpdate?()
}
Logger.s(now)
Logger.s(location)
}else{
self.locationUpdate?()
}
}
AppDelegate.swift
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.example.location_update")
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 minutes from now
do {
try BGTaskScheduler.shared.submit(request)
Logger.s("BG TASK REQUEST SUBMITTED")
} catch {
print("Unable to submit task request: \(error)")
}
}
func handleAppRefresh(task: BGAppRefreshTask) {
task.expirationHandler = {
// Handle expiration if needed
Logger.s("BG TASK EXPIRED")
task.setTaskCompleted(success: false)
}
Logger.s("HANDLE BG TASK REQUEST")
EmployeeAttendanceTracker.shared.locationUpdate = {
task.setTaskCompleted(success: true)
}
}
func registerBackGroundTasks() {
// Register for background tasks
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.example.location_update",
using: DispatchQueue.global()
) { task in
// Your task handler logic
//task.setTaskCompleted(success: true)
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
}
你做不到。至少没有后台刷新任务。应用程序刷新任务将在 iOS 选择时执行。
earliestBeginDate
正是如此;任务最早运行的时间。它可能会在该日期后运行几分钟、几小时或几天。
您可以采取以下几种策略:
在“始终”权限下使用
startUpdatingLocation
。这将大约每秒提供一次位置更新。然后,您可以每“n”分钟向服务器报告一次位置。这将对电池产生重大影响,并且如果终止,将不会重新启动您的应用程序。
使用显着位置变化监控。仅当用户移动了约 500m 时,才会提供位置更新。如果用户正在步行或停下来一段时间,则这可能比“n”分钟长,或者如果用户快速移动(例如在汽车或火车中),则可能比“n”分钟更频繁。重要的位置监控使用的电量要少得多,并且允许您的应用程序在终止时重新启动(仅在检测到重大位置更改时)。
使用组合;定期位置进行频繁更新,重要位置更新在终止时重新启动。
您使用哪种方法取决于您的应用程序的用例。
对于 Uber 风格的“司机”应用程序,您希望持续更新,并且可以合理地期望设备连接到外部电源。
对于 Uber 风格的“乘客”应用程序,您希望持续更新,但只需要很短的时间(从预订过程开始到接载),因此电力消耗可能不是问题。
对于其他用例,请考虑仅进行重大位置更改是否就足够了。