如何在应用未运行(终止/终止)时保持Core Location和Core Bluetooth运行?

时间:2017-07-26 04:43:19

标签: ios bluetooth-lowenergy core-location ibeacon core-bluetooth

如果我终止应用程序,我试图保持我的功能运行时遇到困难。

当app未运行时,是否可以保持核心位置(地理围栏/地理定位)和核心蓝牙运行?如果可能的话如何解决我的问题?我已经检查了后台模式,并实现了核心定位方法。 这是我的代码:

    class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {

        var viewController = ViewController()
        var window: UIWindow?

        var locationManager = CLLocationManager()

        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

            locationManager = CLLocationManager()
            locationManager.requestAlwaysAuthorization()

            locationManager.delegate = self
            locationManager.distanceFilter = kCLDistanceFilterNone
            locationManager.desiredAccuracy = kCLLocationAccuracyBest

            locationManager.pausesLocationUpdatesAutomatically = false

            if #available(iOS 9.0, *) {
                locationManager.allowsBackgroundLocationUpdates = true
            }

            beaconRegion.notifyEntryStateOnDisplay = true
            beaconRegion.notifyOnEntry = true
            beaconRegion.notifyOnExit = true

            locationManager.startMonitoring(for: beaconRegion)
            locationManager.stopRangingBeacons(in: beaconRegion)
            locationManager.startRangingBeacons(in: beaconRegion)
            locationManager.startUpdatingLocation()

            return true
        }

        func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
            if (region.identifier == beaconRegionIdentifier) {
                manager.requestState(for: region)
                goBackground()
            }
        }

        func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
            print("you exited region")
        }

        func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
            if (region.identifier == beaconRegionIdentifier) {
                manager.stopUpdatingLocation()

                switch state {
                case .inside:
                    manager.startRangingBeacons(in: region as! CLBeaconRegion)
                    manager.startUpdatingLocation()
                case .outside:
                    let delay = DispatchTime.now() + .seconds(3)
                    DispatchQueue.main.asyncAfter(deadline: delay) {
                        manager.requestState(for: region)
                    }
                case .unknown:
                    let delay = DispatchTime.now() + .seconds(3)
                    DispatchQueue.main.asyncAfter(deadline: delay) {
                        manager.requestState(for: region)
                    }
                }
            }
        }

        func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {

            let state = UIApplication.shared.applicationState
            switch(state){
            case.active,
                .inactive,
                .background:

                let mainView = UserDefaults.standard.bool(forKey: "toMainView")

                var isWakeUpRunning = UserDefaults.standard.bool(forKey: "isWakeUpRunning")

                if isWakeUpRunning {
                    if mainView {
                        for aBeacon in beacons{
                            if aBeacon.rssi > WAKE_UP_THRESHOLD   && aBeacon.rssi != 0{
                                UserDefaults.standard.set(false, forKey: "isWakeUpRunning")
                                self.viewController.startFunction()
                                manager.stopRangingBeacons(in: region)
                            }else if aBeacon.rssi != 0 && aBeacon.rssi < WAKE_UP_THRESHOLD {
                                manager.stopRangingBeacons(in: region)
                                manager.requestState(for: region)
                            }
                        }
                    }
                }else{
                    manager.stopRangingBeacons(in: region)
                    manager.requestState(for: region)
                }
            }
        }  

 func goBackground() {
        let app = UIApplication.shared
        var bgTask: UIBackgroundTaskIdentifier = 0
        bgTask = app.beginBackgroundTask(expirationHandler: {
            NSLog("Expired: %lu", bgTask)
            app.endBackgroundTask(bgTask)
        })
        NSLog("Background: %lu", bgTask)
}

    }

从我的代码中,它可以在前台和后台运行。但是当我从任务切换器向上滑动应用程序时,它无法正常工作。而我也无法从xcode中看到日志。有什么想法可以帮到我吗?

1 个答案:

答案 0 :(得分:2)

从应用程序切换器向上轻扫应用程序后,您的应用程序将被终止,但CoreLocation仍将在操作系统级别为您工作,寻找与您所在地区相匹配的信标:

locationManager.startMonitoring(for: beaconRegion)

一旦该区域(didEnter或didExit)发生变化,您的应用将重新启动到后台。此时将按顺序调用以下方法:

  1. application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?)

  2. locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion)

  3. 那时您的应用将继续在后台运行。由于您的应用启动后台任务,因此会在暂停前持续180秒。

    但是,您的应用不会在从屏幕上滑落到下一个区域转换的时间之间运行。这是您可以做的最佳选择。