我的应用程序进入暂停状态的原因?

时间:2019-10-13 04:41:07

标签: ios swift background core-location cllocationmanager

我创建了一个位置跟踪ios应用程序(使用CocoaLumberjack库编写日志文件)。因此启用了后台位置更新并可以进行我的测试(我在后台运行了将近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)
        }
    }
}

1 个答案:

答案 0 :(得分:2)

一些观察结果:

  1. beginBackgroundTask流程仅能为您带来3分钟而不是8个小时的收益。它旨在让您完成一些有限的简短任务,而不会无限期地运行应用程序。更糟糕的是,如果您未在其完成处理程序中调用endBackgroundTask,则该应用将在3分钟结束时毫不客气地终止,而不是被正常暂停。

  2. 后台位置更新有两种基本模式。

    • 如果该应用是导航应用,则可以使该应用在后台运行。但是让标准位置服务在后台运行将在几小时内耗尽用户的电池。因此,Apple仅在您的应用绝对需要时才批准此操作(例如,您的应用是实际的导航应用,而不仅仅是一个因其他原因而想跟踪位置的应用)。

    • 另一个模式是significant change service。使用此服务,您的应用将被挂起,但是操作系统将唤醒它以提供位置更新,然后再次将其挂起。参见Handling Location Events in the Background。这不像标准位置服务那样精确,但是由于该应用程序不能一直运行,并且不必旋转GPS硬件,因此它消耗的电量要少得多。

  3. 在测试这些类型的后台交互时,您不想附加到Xcode调试器。通过调试器运行它实际上会更改应用程序生命周期,从而防止其挂起。

  4. 由于通常不会无限期地使应用程序在后台运行,这意味着您将需要删除与Timer相关的代码。