0
votes

I know this is a very common question. I have read many answer but not found out the appropriate answer for me. That's why I post this question and hope someone will show me how to fix my code.

  1. I have function startUpdate to update location using CLLocationManager. In applicationDidEnterBackground method, I write something like below:

    [self startUpdate]; // position1 NSLog(@"applicationDidEnterBackground"); __block UIBackgroundTaskIdentifier bgTask; bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ [application endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }];

    [self startUpdate]; // position2 // Start the long-running task and return immediately.

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self startUpdate]; // position3 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://google.com"]]; });

    • I tried to put [self startUpdate] at one of three positions (position1, 2, 3) and sometime it works, sometime not, and I do not know why.

    • In case it works, updating just run in 3 minutes event. If I call startUpdate when app is in foreground, then put app to background, updating will last 15 minutes with real device, and more than 1hour with simulator ( I don't know exactly, after 1 hour, i thought it would last forever then I stop testing). So what is different between: startupdate in foreground-> go to background vs startupdate in background; simulator vs real device?

    • right after position3, I called following line to open safari [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://google.com"]]; But it does not work. So what types of task can be executed here, in background?

  2. I need to keep a service running forever. Some search results say that it's impossible. But some familiar apps did that (Facebook,... keeps service to receive notifications). How can they do that?

Thank you so much,

1
I'll note that Facebook does not keep a service running to receive notifications. Apple handles this and then sends a message to the AppDelegate object using application:didReceiveRemoteNotification: - atreat
Do you just want to receive location updates in the background (and possibly log that to a server)? If so then all you need to do is set the location background mode in Info.plist and tell the CLLocationManager to start updating. Your location manager delegate method will be called, even in the background. You don't need to worry about the long-running task stuff. You won't be able to launch a web site from background mode though - you can only do that when you are in the foreground - Paulw11
@Paulw11: I already set the location background mode in Info.plist. what I asked is: when in foreground, I start update location then go to background mode, updating continue working in 15 minutes (with real device, > 1h with simulator); If I start updating location when app is already in background, updating just works 3 minutes. Why are they so different? And how can I keep updating forever? - meaholik
If you have specified the background location mode then location updates will continue in the background indefinitely. You don't need to set up a background task for this. Behaviour of background tasks is different when connected to the debugger (i.e. simulator or device with cable connected) as your app isn't terminated after background time expires. - Paulw11
What does startUpdate do? Does it simply call startUpdatingLocation on the CLLocationManager? What version of iOS are you running? - Paulw11

1 Answers

1
votes

The exact behaviour of location services has been clarified in the latest update to the Core Location documentation. It now states -

  • The standard location service delivers events normally while an app is running in the foreground. When your app is in the background, this service delivers events only when the location-updates background mode is enabled for the app. This service does not relaunch iOS apps that have been terminated.

  • The significant location change service delivers events normally while an app is running in the foreground or background. For a terminated iOS app, this service relaunches the app to deliver events. Use of this service requires “Always” authorization from the user.

So, it seems that for the best chance of continuing to receive location updates in the background you should switch to significant location change monitoring once you move to the background state and restore full location monitoring once you return to the foreground.