Notifications for changes to Location Services? - iphone

I've been experimenting with CLLocationManager for an app I'm building. I understand how to check if Location Services are enabled and whether or not a user has allowed my app to use their current location.
If a user allows my app to use their location initially, and then the user either:
turns location services off explicitly
puts the phone in airplane mode
explicitly de-authorizes my app to use their location
Are any notifications posted that I can subscribe to and respond to automatically when they reopen my app?
If not, would the best way to handle this scenario (so I can update views that were displaying GPS coordinates) to manually put this check in my AppDelegate's applicationDidFinishLaunching and applicationWillEnterForeground methods?
The reason I was thinking it should go there is because when you relaunch an app, viewWillAppear is not triggered for the first view, and if that view needs to change from showing GPS coordinates to a friendly message asking them to re-enable location services, the AppDelegates were the best hook I could think of.
Thanks!

On iOS 4.2 and later you will get a delegate call
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status;

Your approach is sound. If you find Core Location is unavailable on re-opening the app or network access has changed, you could then send a notification to those viewControllers that need to updated accordingly. Check out NSNotificationCenter
Even if you adopt the above I would suggest you do these check every time in viewDidAppear anyway as network access could be lost at anytime. Plus in line tests where you do any location checking.

Related

CLLocationManager disable monitoring significant changes in background

I'm using background geolocation to schedule local notifications when the user is in a specific location.
Since theses notifications are link to a commercial operation I've got a date, stored in the userdefaults to manage when I should disable the background geolocation when the operation is other.
I don't want the user to have to launch the application to be able to disable the significant changes monitoring.
So I tried to stopMonitoringSignificantLocationChanges the CLLocationManager directly in the locationManager:didUpdateToLocation:fromLocation: but it doesn't seam to work.
Any advice? What is the best practice for this issue?
Thanks.
Given the rules of the road for backgrounded applications or apps that aren't running, your hands are somewhat tied here.
Here is your one and only option if you want to disable location without any interaction from the user.
Each time your user's location updates from the background, your location manager delegate will receive this update. You don't get a lot of processing power here, so keep it short and sweet or register for a long running background task, check your date and if you are done with location, call the stop monitoring call there, reset any data or flags in your user defaults and you are done.
If you trigger from a local notification, the user will need to click on the open button to perform any actions. You can fire notifications from your background location delegate method for sure. But that is your one and only path to automating anything without user interaction. What you do there is up to you. There is no problem with checking for location udpates and turning that off from the background delegate method.

Register local notification from background

I have a situation where I have to present alert while my app is in background.
So I was thinking that the solution is Local notification.
But the problem is that, I want to show that alert only when user has crossed a particular predefined location point.
So I have to show the notification without any registration for it in Foreground(Or you can say register the local notification in background).
Is it doable ?
Please help.
Yes, you can let your run in the background while you still receive location updates.
You have to the add location to UIBackgroundModes in your apps info.plist;
And any instance of CLLocationManager will keep receiving location updates.
But be aware that this could drain the battery of the iPhone really fast, so it's a good idea to only monitor major location changes.

When does an iphone application receive didChangeAuthorizationStatus: delegate call?

I have a question about CLLocationManagerDelegate. The documentation says if the user changes the settings for your location services (in the iPhone's Settings.app) then your app is supposed to receive an didChangeAuthorizationStatus: message to the delegate. My question is, when would this happen?
If the user changed the setting, it means they are in the settings app, and your app is either backgrounded or not running at all, so in the former case, when would your app's CLLocationManager delegate get the didChangeAuthorizationStatus: call?
I just ran across this method an hour ago, so good timing on the question!
It looks like in my case this method gets called:
When the app becomes active.
On allowing Location Services for the app on the initial startup of the app.
I wrote a quick test app you can find here:
https://github.com/mharper/LocationServices
It simply logs the authorization status whenever the method gets called.
This delegate method will be called when:
The first time you init a CLLocationManager instance
1.1. If that's the first time your App launch on device, you'll receive state kCLAuthorizationStatusNotDetermined before user see the [Allow/Don't Allow] UIAlertView. (At this time, you can find that the UISwitch of your App in Settings - Privacy - Location Service is turn off or not shown.
1.2. When user re-launch your App. Because decision has been made in previous launch, so you can retrieve the state.
The first time after user made decision. This is obvious. After you call the startUpdatingLocation/startUpdatingHeading, then iOS show the UIAlertView.
In your answer's situation, user made changes in Settings, if your App is running in background, you'll receive the new state when your App become active. Otherwise, reference 1.2.
If your app is running in the background or not at all it will be called the moment the user returns to your application.
I encounter the same issue as well.
my solution is put the request gps authorization code in main loop.
I guess it can also works if you put in another run loop.
I ran into this problem of handling location permission changes correctly recently and did a lot of research and debugging.
If the app is not running at all and the user changes location permissions in Settings, then when you start your app, locationManager:didChangeAuthorizationStatus is called when the location manager is initialized as stated in mharper's answer. This behavior is not in Apple's docs.
If the app is in the background/suspended, I tested it in the simulator and it looks like the delegate function is also called.

iPhone: Find out where am I when application is in background

I can get the current location of my iPhone but I was wondering if it is possible to call my methods when application is in background and pop-up message(may be using local notification?) if user has reached at particular location.
Thanks.
Yes, this is possible. A local notification is also an excellent solution.
All you need to do is to set the flags for background position updates in the app plist. Then, in the callback methods for the location manager, perform the distance and/or location tracking logging and fire a local notification.

Location updates while app is in the background or suspended

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.