应用程序终止时获取用户位置

4

我目前正在开发一个应用程序,遇到了一个问题。我的应用程序的目的是查看某人何时下班。为了让它始终有效,该应用程序应该能够在应用程序打开、在后台运行或被终止(关闭)时获取用户的位置。我的理解是您必须使用“significant location change”功能来实现这一点。但是,它并没有按预期工作。

AppDelegate:

    //handle location changes when app is terminated and waken up by the OS
    if launchOptions?[UIApplicationLaunchOptionsKey.location] != nil {
        print("Restarted app due to a location update")
        request = Locator.subscribeSignificantLocations(onUpdate: { newLoc in
            let db: FirebaseDB = FirebaseDB.shared
            db.postCoordinates(coordinates: CLLocation(latitude: 9.99, longitude: 9.99))
            print("new loc found -> \(newLoc)")
        }, onFail: {(err, lastLoc) in
            print("failed to get loc, -> \(err)")
        })
        //send new post to DB
    }

    //subscribeSignificantLocations -> power efficient
        request = Locator.subscribeSignificantLocations(onUpdate: { newLoc in
            print("new loc found -> \(newLoc)")
        }, onFail: {(err, lastLoc) in
            print("failed to get new loc, -> \(err)")
        })

除了在应用程序终止时获取位置之外,一切正常......

提前致谢!


尝试使用此链接:https://dev59.com/F1oU5IYBdhLWcg3wc2tW - Ashish
尝试使用此链接:http://mobileoop.com/getting-location-updates-for-ios-7-and-8-when-the-app-is-killedterminatedsuspended - Balaji Kondalrayal
@MathiasSchrooten,你可以参考我的stackoverflow答案,它可能会有所帮助 https://stackoverflow.com/questions/47539720/ios11-location-update-after-getting-killed-by-user/47546956#47546956 - Ashish
@Ashish,感谢您的答复,不过我已经解决了这个问题:( - Mathias Schrooten
@MathiasSchrooten 我注意到我构建的一个类似Uber的应用程序中存在这种行为,即在应用程序终止时仍跟踪用户位置。我发现,在iOS 9和iOS 10上测试时,约70%的时间会在用户移动显着距离后触发位置回调,电池、当前打开的应用程序和网络等因素对回调起了作用。请尝试充满电并关闭所有其他应用程序,并报告结果。 - B K
显示剩余3条评论
1个回答

7

经过数小时的搜索和阅读,我找到了适合我的解决方案。(注意:我正在进行地理围栏,需要在用户离开特定区域时通知/调用API

第一步也是最重要的一步是,用户必须授权"始终"访问位置。

其次,我们需要使用startMonitoringSignificantLocationChanges()来更新位置,即使应用程序已经终止。

        locationManager.requestAlwaysAuthorization()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.startUpdatingLocation()
        locationManager.startMonitoringSignificantLocationChanges() //THIS IS WHERE THE MAGIC HAPPENS

以下是获取位置更新本地通知的代码。
import UIKit


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {

    var window: UIWindow?
    let locationManager = CLLocationManager()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.


        locationManager.requestAlwaysAuthorization()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.startUpdatingLocation()
        locationManager.startMonitoringSignificantLocationChanges()

        application.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil))
        UIApplication.shared.cancelAllLocalNotifications()

        return true
    }

    func alertUserOnLeaving(region:CLRegion){
        if UIApplication.shared.applicationState == .active {
            let alert = UIAlertController(title: "Alert Title", message: "Alert Message", style = .Alert
            window?.rootViewController?.present(alert, animated: true, completion: nil)
        }
        else{
            let notification = UILocalNotification()
            notification.alertBody = "You forgot to checkout"
            notification.soundName = "Default"
            UIApplication.shared.presentLocalNotificationNow(notification)
        }
    }

    func alertUserOnArrival(region:CLRegion){
        if UIApplication.shared.applicationState == .active {
            let alert = UIAlertController(title: "Alert Title", message: "Alert Message", style = .Alert
            window?.rootViewController?.present(alert, animated: true, completion: nil)
        }
        else{
            let notification = UILocalNotification()
            notification.alertBody = "Welcome Please checkin"
            notification.soundName = "Default"
            UIApplication.shared.presentLocalNotificationNow(notification)
        }
    }

    func setUpGeofenceForJob() {
        let geofenceRegionCenter = CLLocationCoordinate2DMake(-33.7513580322265, 151.242416381836)
        let geofenceRegion = CLCircularRegion(center: geofenceRegionCenter, radius: 100, identifier: "GeoFence")
        geofenceRegion.notifyOnExit = true
        geofenceRegion.notifyOnEntry = true
        self.locationManager.startMonitoring(for: geofenceRegion)
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if (status == CLAuthorizationStatus.authorizedAlways) {
            self.setUpGeofenceForJob()
        }
    }

    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        alertUserOnArrival(region: region)
    }
    func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
        alertUserOnLeaving(region: region)
    }

希望这有所帮助。

2
当应用程序被杀死/终止/挂起状态时,我希望位置每15分钟更新一次。这种情况是否可能实现? - Rashesh Bosamiya
当应用程序被杀死/终止/挂起时,我希望每15分钟更新一次位置。这是否可能实现?请给予建议。 - Piyush

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接