Greetings all.
I am attempting to implement significant location change and region support into my app. While the app is active, there is obviously no problem receiving location updates. My question is how to handle updates when the app is not active.
This is my understanding of what happens if a significant location change or region entry/exit is detected:
If the app is in the background or suspended, iOS calls locationManager:didUpdateToLocation:fromLocation: (or locationManager:didEnterRegion:) on my existing location delegate.
If the app is terminated, iOS calls application:didFinishLaunchingWithOptions: with the key UIApplicationLaunchOptionsLocationKey on my application delegate. At this point I need to create a new location manager instance to obtain the new location.
Is this correct? Am I missing anything?
Thanks for help.
Regards,
--John
You are partly right.
If the app is in background, and you are using significant location change:
The app will call locationManager:locationDidUpdateToLocation:fromLocation
If app crashed while it was in background, it will call application:didFinishLaunchingWithOption: with UIApplicationLaunchOptionLocationKey. You then have to init location manager again to get significant location change. This will then come in to locationManager:locationDidUpdateToLocation:fromLocation. This step is important
If the app is in background, and you are using region monitoring
locationManager:locationDidUpdateToLocation:fromLocation will not be called
the app calls locationManager:didEnterRegion:
To get location update when the app is in the background versus when the app is suspended are 2 very different scenario. You will have to handle them differently.
You can only use the key UIApplicationLaunchOptionsLocationKey if your locationManager is using the method startMonitoringSignificantLocationChanges, you can not use startUpdatingLocation.
To get the location update when
A) The app is In the background, please see: Background Location Services not working in iOS 7
B) The app is suspended/terminated, please see: How to Get Location Updates for iOS 7 and 8 Even when the App is Suspended
I have written 2 very long article explaining the different between the 2 scenario. The source codes for the above 2 scenario are also available on the GitHub.
I believe it always calls application: didFinishLaunchingWithOptions if your app is not in the foreground.
Related
I've seen application on iphone called "moves"
the gps is running on background while the application is totaly closed and not working in the background.
how can i get the location of the user and send it to the application while it is closed and not working on background? how could this possible?
what is the function to do that?
thanks
It is possible to get the location while the phone is running in the background (The Google Maps app does this), however running a background thread is a privilege that you must justify to Apple in their review process.
Here is some documentation by Apple for guidelines for running in the background
You register for the significant-change location service.
According to the Apple docs:
If the app starts this service and is then terminated, the system relaunches the app automatically when a new location becomes available.
This is not possible for an App on a non jailbraked iphone. Check again what you really have seen.
Apps can run in the background and get locations. But an app which is closed, can not do anything, since it is not running.
Maybe you have sawn the GPS Arrow in the status bar, staying active. But this disappears after some seconds, as long as no other application uses GPS.
I'am developing an application that keep a WebService informed for device location each 5minute (for exemple) :
So when the application leave the foreground execution and enter background I have to lunch a timer who
1 - Update the device location
2 - Send the location to a web service
How can I perform this action ? Or do you know any code exemple that I can follow to achieve this design ?
Thank you for your help !
Doesn't look like anyone gave you a solid answer, so allow me.
There is no iOS approved way of running a 5 minute (or any minute) timer in the background (unless your app is VOIP or music). What you CAN do is register your app as requiring location services in the background (edit the info.plist and add a key Required Background Modes and then add a value App registers for location updates. What this means is your locationManager:didUpdateToLocation:fromLocation: method and corresponding region monitoring/SLC methods will fire on location change, but Timers will not work at all.
The reason why is that timers require a run loop (a thread executing code) to be running and must piggy-back on that thread, but when the app is in the background even when executing code from the LocationManager, the run loop that executes the code almost always finishes before your timer would go off.
Hope this helps!
you cannot do this (on iOS).
(unless your app requests permissions that are meant for Navigation apps)
Hello #Aladdin Gallas,
I have developed a simple application that supports background location updates for iOS and Android in Xamarin.
The app pushes a new location every 2 seconds (you can change it to 5 minutes if you want to).
There is a feature I haven't been able to add; it is to keep the service up when the user closes the app (for iPhone). Other than that, as long as the app is open, even if the phone is locked, the service keeps running.
You can take a look at the application as a reference if it helps.
GitHub Repo
Is there a way to manually tell the device to dispatch a significant location change notification that will wake up any applications registered for this notification?
This is for testing only, and I realize this private API call would get rejected upon submission to the app store.
So two answers:
A) Hop on a train :-)
B) Use the simulator. In iOS 5.x simulator, there is a debug menu that has a location submenu. Choose freeway drive. This will start the simulator on an imaginary journey down the scenic 280 in Northern California. It gives you everything but the view: your app will get Significant Location Change updates, and will also be launched in the background if it has been suspended.
To verify that you are actually moving, launch safari in the simulator, and go to maps.google.com and click the little track my location button. You should be moving.
Awesome! Now how to debug the lifecycle problem of being launched by the system? Easy! Have xCode wait for your app to be launched to start debugging. From the Scheme menu, choose edit scheme. In the Run Scheme, and the Info tab, for the "Launch" setting choose : "Wait for My.app to launch".
Run your app once in the simulator, so that it starts monitoring for location updates, then force quit it, so that it is suspended. Add a break point in your application did finish launching function, and wait. As soon as your simulator has gone far enough, your application will be woken up, your breakpoint hit, and you are in the money.
But really, the train ride is more fun.
Well, I've found that I can do this by toggling on and off Airplane mode and/or WiFi. Perhaps start the app with the device in airplane mode, then close the app and turn airplane mode off. That will turn the GPS on and force a location update to be dispatched.
I also wanted to test the relaunch of my terminated app which uses significant change monitoring. I wrote a piece of code so that it would display a local notification when it gets launched by a location key in the launch options dictionary.
I ran my app in the simulator. Then killed it from the multitasking bar. Then I set the location of the iOS simulator to a custom location. I quit the simulator and started it again. My app received the significant location update and showed the local notification.
I was struggling with the same issue, how to test 'startMonitoringSignificantLocationChanges' and check if my app is receiving location updates when suspended.
I couldn't manage to catch the execution on a breakpoint but I managed to see the results of my implementation working by sending the new location data to the server.
The whole flow:
- Implemented with 'startMonitoringSignificantLocationChanges' and an API call to my server to update the location latitude and longitude
- Set the location updates background mode capability to true
- Run the app so the location manager is initiated and the app is listening for location changes
- Force closed the app
- Set the debug->location on simulator to freeway drive
- Opened maps to see if the location is changing
- Waited on the server to see for location updates and was getting new results every about 3 minutes
However, I'm still not sure if this is fine enough on a real device.
I'm working on Xcode Version 6.0.1 (6A317); tested on Simulator iPhone 5s (8.0).
Adding to MagicSeth's answer, if you need to test this on a real device instead of a simulator, you can trigger a background launch with UIApplication.LaunchOptionsKey.location key by disabling and re-enabling Location Services in General > Privacy screen in the Settings app.
Depending on your scenario I would suggest two solutions:
Use a Timer or LocalNotification that periodically calls stopMonitoringSignificantLocationChanges followed by startMonitoringSignificantLocationChanges which should trigger a new location to be sent to your code (might be the same Location as before).
Build your own GPS Simulator that you start in debug builds and that will call the same delegate methods like CLLocationManager would do.
One thing I noticed in iOS 7 and Xcode 5.1.1 - If you are expecting SLC events to fire up your app into background mode, it may or may not hit the breakpoints you set. For me, sometimes the NSLog message are not even showing.
If that's the case for you, you can view NSLog outputs from the System Log. You can open the System Log from iOS Simulator's Debug menu.
In iOS 4, you can register for significant location changes. From the Apple docs: With this service, location updates are generated only when the user’s location changes significantly; thus, it is ideal for social applications or applications that provide the user with noncritical, location-relevant information. If the application is suspended when an update occurs, the system wakes it up in the background to handle the update. If the application starts this service and is then terminated, the system relaunches the application automatically when a new location becomes available. This service is available in iOS 4 and later, only on devices that contain a cellular radio.
See the Apple docs here and here.
Here is some example code to register for signification location updates:
- (void)startSignificantChangeUpdates {
// Create the location manager if it doesn't exist
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startMonitoringSignificantLocationChanges];
}
The docs say: 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.
Freeway drive
// MARK: - MKMapViewDelegate
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
guard let location = userLocation.location else { return }
print(location.speed)
}
Well, this is not possible as the application scope is limited to its own space and such kind of notification cannot be generated with Apple Documented APIs list.
Of course.. if any undocumented API is used, application will get rejection from apple due to the use of undocumented/private API.
Basically, I've been learning Objective-C and how to develop for the iPhone over the past few months and have created a few basic applications. Now I've got an idea for an iPhone app that I'm interested in developing and I'm just looking for a bit of advice on wether it is actually possible. I'm looking to create an app that sends the iPhones location to my server every 15 minutes - even when the app hasn't been opened/isn't opened.
Is this possible? If it is, could you point me in the direction of some more info on this subject.
Thanks.
You can declare your application as needing background location services. But this is available only in iOS 4, and user needs to allow location services for your app.
More info about multitasking can be found here
More info about getting users's location can find here
The answer to your question could be a partial YES or a partial NO. Basically ur app can give location updates even when it is not opened ... and u can handle it to be sent to ur server whenever user location updates .. but it is not possible to send the location update on a time basis like every 15 minutes ..
If you want ur app to register for location updates in background mode, u have two options:-
send location update on significant location change (i.e. a location update is sent when user moves significantly such that the cell tower changes for the user ) in this case u have to use startMonitoringSignificantLocationChanges OR
send continous location updates by using startupdatingLocation and in info.plist file declare background mode key for location updates (uses GPS)
and u have to handle didUpdatetoLocation for location updates in both cases and Ur app will be woken up in background as soon as a location update is recieved (beware of battery usage in 2nd case)
For the sake of this question, assume I plan to build a Google Latitude client app for iOS 4.
my app needs to upload the user gps location every two minutes, and also download the user friends locations. - in the background!
my app can't wait to be woken up by the OS on cellular tower switches (because they may only happen after 2 KM, while my app needs constant gps updating), so I understand I can create a thread, similar to the ones GPS navigators use, to run in the background.
I have no knowledge in iPhone programming, I just need to know if my app is feasible.
Will I be able to access the internet from within the background thread (and upload the user gps location), or is it restricted to only sampling the GPS location.
1.
Will Apple approve such an application, or is this type of use forbidden? because my app isn't realy critical such as a gps navigator
Thanks!
As Don said, iOS will send location events to apps that support it. From there, the app can do what it needs to do with the location event.
Background apps can register for one of three options:
Significant changes only: a low-power way to track location that only wakes the app up when there's a "significant" change in location
Standard location services: compatible with all iOS devices that can use location services, allows you specify change in distance, and works in background. However, if the app has been terminated or suspended, iOS won't attempt to relaunch the app.
Continuous location services: allows the program to receive continuous location updates and iOS will not suspend the application when sent to the background.
More info: Executing Code in the Background and Location Awareness Programming Guide
If you take a look at Executing Code in the Background, Apple provides guidelines on what multitasking-aware apps should and shouldn't do.
You will receive the locationManager:didUpdateToLocation:fromLocation: message in your app. In there, you can do whatever you need to, although you should not update the UI or use Open GL if your are in the background.