我创建了一个位置跟踪ios应用程序(使用CocoaLumberjack库编写日志文件),启用了.So后台位置更新,并为我的测试工作(我几乎在后台运行了8个小时)。当应用程序进入现场商店时。在我们的应用程序中出现了很多问题。当应用程序转到后台时,位置跟踪不能正常工作。在一段时间内,它不会将用户位置发送到服务器。因此,我从客户端获得日志文件,并检查日志文件中存在时间间隔。我经常得到用户的位置(每一秒)。所以,我以为在日志文件中出现间隙时,应用程序进入了暂停状态?为什么应用程序进入暂停状态,即使我经常在后台定位?有什么理由让应用程序暂停运行吗?找不到任何有效的细节?
func startTimer()
{
if bgTimer == nil
{
bgTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.startLocationChanges), userInfo: nil, repeats: true)
}
}
func stopTimer()
{
if bgTimer != nil
{
bgTimer?.invalidate()
bgTimer = nil
}
}
@objc func startLocationChanges() {
locationManager.delegate = self
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//let lastLocation = locations.last!
// Do something with the location.
/*print(lastLocation)
let logInfo = "BGLocationManager didUpdateLocations : " + "\(lastLocation)"
AppDelegate.appDelegate().writeLoggerStatement(strInfo: logInfo)*/
locationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
if let error = error as? CLError, error.code == .denied {
// Location updates are not authorized.
manager.stopMonitoringSignificantLocationChanges()
return
}
// Notify the user of any errors.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationDidEnterBackground: when the user quits.
self.writeLoggerStatement(strInfo: "applicationDidEnterBackground")
appstate = "Background"
if CoreDataUtils.isUserLoggedIn(entityName: "UserInfo") == true {
let user = CoreDataUtils.fetchCurrentUser(entityName: "UserInfo")
if user!.isGPSActive == "1"
{
if backgroundTaskIdentifier != nil
{
application.endBackgroundTask(backgroundTaskIdentifier!)
backgroundTaskIdentifier = UIBackgroundTaskInvalid
}
backgroundTaskIdentifier = application.beginBackgroundTask(expirationHandler: {
//UIApplication.shared.endBackgroundTask(self.backgroundTaskIdentifier!)
})
BGLocationManager.shared.startTimer()
let logInfo = String(format:"applicationDidEnterBackground backgroundTimeRemaining : %f",(Double)(application.backgroundTimeRemaining / 60))
self.writeLoggerStatement(strInfo: logInfo)
}
}
}发布于 2019-10-13 16:30:26
几点意见:
beginBackgroundTask只给你买30秒,而不是8小时。(在13之前的iOS版本中,这是3分钟,而不是30秒,但问题仍然存在。)底线,这是为了让你完成一些短的,有限的长度任务,而不是让应用程序无限期地运行。更糟糕的是,如果您没有在其完成处理程序中调用endBackgroundTask,则当分配的时间过期时,应用程序将被随意终止。- If the app is a navigation app, then you can keep the app running in the background. But keeping standard location services running in the background will kill the user’s battery in a matter of a few hours. So Apple will only authorize this if your app absolutely requires it (e.g. your app is an actual navigation app, not just an app that happens to want to keep track of locations for some other reason).
- The other pattern is [significant change service](https://developer.apple.com/documentation/corelocation/getting_the_user_s_location/using_the_significant-change_location_service). With this service, your app will be suspended, but the OS will wake it to deliver location updates, and then let it be suspended again. See [Handling Location Events in the Background](https://developer.apple.com/documentation/corelocation/getting_the_user_s_location/handling_location_events_in_the_background). This isn’t as precise as the standard location services, but because the app isn’t constantly running and because it doesn’t have to spin up GPS hardware, it consumes far less power.
Timer相关的代码。https://stackoverflow.com/questions/58360650
复制相似问题