在后台更新位置
Update location in Background
我想获取用户位置,即使用户不使用 app.now 我可以在按下主页按钮和应用程序进入后台状态后获取位置,但几秒钟后位置更新停止。当我停止应用程序位置更新时。这是我在应用程序委托中的代码。
let locationManager = CLLocationManager()
var LatitudeGPS = String()
var LongitudeGPS = String()
var speedGPS = String()
var Course = String()
var Altitude = String()
var bgtimer = Timer()
func applicationDidEnterBackground(_ application: UIApplication) {
self.doBackgroundTask()
}
func beginBackgroundUpdateTask() {
backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
self.endBackgroundUpdateTask()
})
}
func endBackgroundUpdateTask() {
UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
self.backgroundUpdateTask = UIBackgroundTaskInvalid
}
func doBackgroundTask() {
DispatchQueue.global(qos: .background).async {
self.beginBackgroundUpdateTask()
self.StartupdateLocation()
self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)
RunLoop.current.add(self.bgtimer, forMode: RunLoopMode.defaultRunLoopMode)
RunLoop.current.run()
self.endBackgroundUpdateTask()
}
}
func bgtimer(timer:Timer!){
print("Fired from Background ************************************")
updateLocation()
}
func StartupdateLocation() {
locationManager.delegate = self
locationManager.startUpdatingLocation()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.requestAlwaysAuthorization()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
}
func updateLocation() {
locationManager.startUpdatingLocation()
locationManager.stopUpdatingLocation()
print("Latitude: \(LatitudeGPS)")
print("Longitude: \(LongitudeGPS)")
print("Speed: \(speedGPS)")
print("Heading: \(Course)")
print("Altitude BG: \(Altitude)")
DispatchQueue.main.async {
print(UIApplication.shared.backgroundTimeRemaining)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
LatitudeGPS = String(format: "%.10f", manager.location!.coordinate.latitude)
LongitudeGPS = String(format: "%.10f", manager.location!.coordinate.longitude)
speedGPS = String(format: "%.3f", manager.location!.speed)
Altitude = String(format: "%.3f", manager.location!.altitude)
Course = String(format: "%.3f", manager.location!.course)
}
}
我想几秒钟后我的应用程序终止了,位置更新也停止了。
我想在 20 分钟后该应用程序终止(os 或用户)停止更新位置以保持电池电量。
我的位置更新问题在哪里。
有几处需要更改。
第 1 步:
确保您已在项目的功能部分启用位置更新后台模式,如下所示
第 2 步:
And when I'm killing the app location update against stoped.
引用苹果文档
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 location 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.
在上面的声明中需要注意的重要一点是
Upon relaunch, you must still, configure a location manager object and
call this method to continue receiving location events.
意思是,您当前的位置管理器不会有多大用处,您应该创建一个新的并配置新的实例,然后再次调用 startMonitorSignificantLocationChanges
。
所以 iOS 只会在您使用 startMonitoringSignificantLocationChanges
时向终止的应用程序发送位置更新。
仅当您的应用被终止并且 iOS 在收到位置更新时重新启动它时,所有这些才适用。但是如果你的应用程序只是在后台运行,你不需要做任何事情来使用 startMonitorSignificantLocationChanges
另一方面,startUpdatingLocation
仅当应用程序处于 background/foreground 模式时才有效。 iOS 如果您的应用被挂起或终止,将停止更新位置。
If you start this service and your app is suspended, the system stops
the delivery of events until your app starts running again (either in
the foreground or background). If your app is terminated, the delivery
of new location events stops altogether. Therefore, if your app needs
to receive location events while in the background, it must include
the UIBackgroundModes key (with the location value) in its Info.plist
file.
所以修改你的代码
locationManager.startMonitoringSignificantLocationChange()
好的,这就是 startMonitoringSignificantLocationChanges
和 startupdatinglocation
的正确用法。现在为您的代码中的错误计时。
错误一:
self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)
使用计时器及时获取位置更新。那不是它的工作原理!你不能永远 运行 定时器。一旦您的应用程序暂停或终止,计时器就会停止。位置管理器会在位置更改时通知应用程序,您应该只依赖它。您不能 运行 计时器来及时检查位置更新。它不会 运行 处于挂起或终止状态。
错误二:
func updateLocation() {
locationManager.startUpdatingLocation()
locationManager.stopUpdatingLocation()
为什么在后续语句中启动和停止更新位置?这没有多大意义。
错误三:
func StartupdateLocation() {
locationManager.delegate = self
locationManager.startUpdatingLocation()
您的 StartupdateLocation
被多次调用,每次您调用此方法时,您都会在同一位置管理器实例上重复调用 startUpdatingLocation
。你不需要那样做!您只能调用 startUpdatingLocation
或 startMonitoringSignificantLocationChange
一次。
我想获取用户位置,即使用户不使用 app.now 我可以在按下主页按钮和应用程序进入后台状态后获取位置,但几秒钟后位置更新停止。当我停止应用程序位置更新时。这是我在应用程序委托中的代码。
let locationManager = CLLocationManager()
var LatitudeGPS = String()
var LongitudeGPS = String()
var speedGPS = String()
var Course = String()
var Altitude = String()
var bgtimer = Timer()
func applicationDidEnterBackground(_ application: UIApplication) {
self.doBackgroundTask()
}
func beginBackgroundUpdateTask() {
backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
self.endBackgroundUpdateTask()
})
}
func endBackgroundUpdateTask() {
UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
self.backgroundUpdateTask = UIBackgroundTaskInvalid
}
func doBackgroundTask() {
DispatchQueue.global(qos: .background).async {
self.beginBackgroundUpdateTask()
self.StartupdateLocation()
self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)
RunLoop.current.add(self.bgtimer, forMode: RunLoopMode.defaultRunLoopMode)
RunLoop.current.run()
self.endBackgroundUpdateTask()
}
}
func bgtimer(timer:Timer!){
print("Fired from Background ************************************")
updateLocation()
}
func StartupdateLocation() {
locationManager.delegate = self
locationManager.startUpdatingLocation()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.requestAlwaysAuthorization()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
}
func updateLocation() {
locationManager.startUpdatingLocation()
locationManager.stopUpdatingLocation()
print("Latitude: \(LatitudeGPS)")
print("Longitude: \(LongitudeGPS)")
print("Speed: \(speedGPS)")
print("Heading: \(Course)")
print("Altitude BG: \(Altitude)")
DispatchQueue.main.async {
print(UIApplication.shared.backgroundTimeRemaining)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
LatitudeGPS = String(format: "%.10f", manager.location!.coordinate.latitude)
LongitudeGPS = String(format: "%.10f", manager.location!.coordinate.longitude)
speedGPS = String(format: "%.3f", manager.location!.speed)
Altitude = String(format: "%.3f", manager.location!.altitude)
Course = String(format: "%.3f", manager.location!.course)
}
}
我想几秒钟后我的应用程序终止了,位置更新也停止了。 我想在 20 分钟后该应用程序终止(os 或用户)停止更新位置以保持电池电量。 我的位置更新问题在哪里。
有几处需要更改。
第 1 步:
确保您已在项目的功能部分启用位置更新后台模式,如下所示
第 2 步:
And when I'm killing the app location update against stoped.
引用苹果文档
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 location 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.
在上面的声明中需要注意的重要一点是
Upon relaunch, you must still, configure a location manager object and call this method to continue receiving location events.
意思是,您当前的位置管理器不会有多大用处,您应该创建一个新的并配置新的实例,然后再次调用 startMonitorSignificantLocationChanges
。
所以 iOS 只会在您使用 startMonitoringSignificantLocationChanges
时向终止的应用程序发送位置更新。
仅当您的应用被终止并且 iOS 在收到位置更新时重新启动它时,所有这些才适用。但是如果你的应用程序只是在后台运行,你不需要做任何事情来使用 startMonitorSignificantLocationChanges
另一方面,startUpdatingLocation
仅当应用程序处于 background/foreground 模式时才有效。 iOS 如果您的应用被挂起或终止,将停止更新位置。
If you start this service and your app is suspended, the system stops the delivery of events until your app starts running again (either in the foreground or background). If your app is terminated, the delivery of new location events stops altogether. Therefore, if your app needs to receive location events while in the background, it must include the UIBackgroundModes key (with the location value) in its Info.plist file.
所以修改你的代码
locationManager.startMonitoringSignificantLocationChange()
好的,这就是 startMonitoringSignificantLocationChanges
和 startupdatinglocation
的正确用法。现在为您的代码中的错误计时。
错误一:
self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)
使用计时器及时获取位置更新。那不是它的工作原理!你不能永远 运行 定时器。一旦您的应用程序暂停或终止,计时器就会停止。位置管理器会在位置更改时通知应用程序,您应该只依赖它。您不能 运行 计时器来及时检查位置更新。它不会 运行 处于挂起或终止状态。
错误二:
func updateLocation() {
locationManager.startUpdatingLocation()
locationManager.stopUpdatingLocation()
为什么在后续语句中启动和停止更新位置?这没有多大意义。
错误三:
func StartupdateLocation() {
locationManager.delegate = self
locationManager.startUpdatingLocation()
您的 StartupdateLocation
被多次调用,每次您调用此方法时,您都会在同一位置管理器实例上重复调用 startUpdatingLocation
。你不需要那样做!您只能调用 startUpdatingLocation
或 startMonitoringSignificantLocationChange
一次。