简体   繁体   中英

How to update location in background online in an iOS app?

I'm trying to build an iPhone app that requires me to keep track of the user's location at all times using Core Location. I am using startMonitoringSignificantLocationChanges so that it updates in the background and because the accuracy is not as important as it being updated whenever there is a significant change.

Currently I make an HTTP request to a web service to update the location. This works perfectly when I am running the app - my location gets updated in the MySQL database I'm storing location data in. But when the app enters into the background - I can see the location services icon in the top right corner of the phone still running, but when I go back and look at the database, it didn't update my location at all. I tested this by taking a drive across town, one way with the app running, and one way with the app in the background.

From Apple's documentation:

If you leave this service running and your application is subsequently suspended or terminated, the service automatically wakes up your application when new location data arrives. At wake-up time, your application is put into the background and given a small amount of time to process the location data. Because your application is in the background, it should do minimal work and avoid any tasks (such as querying the network) that might prevent it from returning before the allocated time expires. If it does not, your application may be terminated.

How long exactly is this "small amount of time to process location data"? And is it just not recommended to query the network, or is it not possible to query the network in that time? Is there a better way to keep track of the location of several different users even when the app is in the background?

You should have look at background tasks.

When Apple says small amount of time to process location data , you shouldn't really rely on getting any processing time after the locationManager:didUpdateToLocation:fromLocation: method has returned. Assuming that you're running the HTTP request asynchronously in a separate thread, you are likely not given enough time to finish it before your app is suspended.

UIBackgroundTasks let you ask the operating system for extra processing time while in background. Making a HTTP request could be such a task. The time limit is 10 minutes although you are not guaranteed to get this much time.

In your location callback, you should define a new background task for your request. The expiration handler block is triggered at any time if the operating system decides that it can not give you any more processing time.

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    // Start your request here
    UIBackgroundTaskIdentifier backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        backgroundTask = UIBackgroundTaskInvalid;
        // Cancel your request here
    }];
}

And when the request has finished you should tell the application that the task is done:

- (void)requestFinished:(id)request {
    [[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
    backgroundTask = UIBackgroundTaskInvalid;
}

In this example, I've not taken into account that you may receive multiple location callbacks before the request has finished. If that happens, you need to cancel that request and current background task before starting a new one, or create a separate background task for each request.

Another way of doing it would be to run the HTTP request synchronously on the main thread in the location callback method, but that will be a bad thing to do for multiple reasons, like locking up the interface if the user opens the app while a request is running.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM