SignificantLocationChanges doesn't work since iOS 8 - ios

I have a problem with the SignificantLocationChanges since the release of iOS 8. The method
[locationManager startMonitoringSignificantLocationChanges];
is called correctly after checking for availability, the delegates also work nice (I check it with the didChangeAuthorizationStatus method, which is part of the same delegate and object) and compiler has no doubts, but there comes absolutely no updates and no errors from the didFailWithError method. The log says the authorizationStatus is 4, which is ok I think.
Before iOS 8 this all works fine.
The first test-device (iPad 2 with 3G) runs iOS 7.1.2 the second (iPhone 5) 8.0.2, when I use the normal startUpdatingLocation method I get updates immediately. But SignificantLocationChanges would be much better for my work. Has anyone an idea where the error could be?

In iOS 8 You must request authorization with type "Always" to allow your app to use significant locations.
Add a new row in your -Info.plist file with key NSLocationAlwaysUsageDescription
Then request authorization if its not requested yet.
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
if (status == kCLAuthorizationStatusNotDetermined && [manager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[manager requestAlwaysAuthorization];
}
}

I'm having problems with startMonitoringSignificantLocationChanges too..
I added the [self.locationManager requestWhenInUseAuthorization]; and added the NSLocationWhenInUseUsageDescription string to the plist file.
When i run my app everything works, the didChangeAuthorizationStatus delegate method called, but no activity to the didUpdateLocation or didFailWithError delegate methods..
But when i switch to startUpdatingLocation, magically it works! But i need startMonitoringSignificantLocationChanges to work because i dont want my app to consume battery for an event that i dont need!
UPDATE!! Problem Solved!
Oh i see why it does not working now!. The new SDK reference here in this link says;
"You must call this method or the requestAlwaysAuthorization method prior to using location services. If the user grants “when-in-use” authorization to your app, your app can start most (but not all) location services while it is in the foreground. (Apps cannot use any services that automatically relaunch the app, such as region monitoring or the significant location change service.)"
So it is not possible to use startMonitoringSignificantLocationChanges with the [self.locationManager requestWhenInUseAuthorization]; method. You have to use requestAlwaysAuthorization instead!

Have you remembered to call method
-requestAlwaysAuthorization
(or -requestWhenInUseAuthorization)
on your CLLocationManager? This is a new method in iOS 8, and it's required to call it before starting location updates.
Also, double check if you're allocating and calling -startUpdatingLocation on the main thread. I'm not sure about that one, but I think calling it on a different thread could cause problems.

Related

CLLocationManager not receiving updates in background after a while

I have an app where the user can gps-track his activities.
Everything works as expected with background GPS updates, but there are very rare cases (1 out of 1000), where I am just not receiving update calls from CLLocationManager when my app is in background. Not immediately, but after some time.
My app starts receiving updates and then all of a sudden (can be a couple of minutes or hours of tracking) it just won't get any more locations updates. It continues reporting location as soon as the app get's active again. But of course those missing locations are bad!
I didn't figure out when and why it happens, that's why I wanted to ask if somebody else already experienced the same issue? I can say that it's not a phone call or something like that that is interrupting. I also don't get callbacks in the didFail delegate method. I just don't get anything any more....
And the big problem is that I have NO IDEA on how to debug that, as I can't reproduce it on purpose.
Any help is very much appreciated.
EDIT:
Here's how I setup my location Manager
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = kMinimumDistanceFilter;
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
self.locationManager.pausesLocationUpdatesAutomatically = NO;
self.locationManager.activityType = CLActivityTypeFitness;
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
if ([self.locationManager respondsToSelector:#selector(setAllowsBackgroundLocationUpdates:)])
{
self.locationManager.allowsBackgroundLocationUpdates = YES;
}
and then later when the Start-Recording-Button is hit
[self.locationManager startUpdatingLocation];
EDIT 2:
If you start this service and your app is suspended, the system stops
the delivery of events until your app starts running again (either in
the foreground or background). If your app is terminated, the delivery
of new location events stops altogether. Therefore, if your app needs
to receive location events while in the background, it must include
the UIBackgroundModes key (with the location value) in its Info.plist
file.
I don't even startUpdatingLocation in the background... But it seems as if that's what happening to my app. How would I be even able to start tracking if the app is suspended? That's impossible, isn't it? Cause suspended would mean it's not executing code?!?
Do you have allowsBackgroundLocationUpdates set to YES in your Info.plist?
From documentation:
By default, this is NO for applications linked against iOS 9.0 or
later, regardless of minimum deployment target.
With UIBackgroundModes set to include "location" in Info.plist, you
must also set this property to YES at runtime whenever calling
-startUpdatingLocation with the intent to continue in the background.
Setting this property to YES when UIBackgroundModes does not include
"location" is a fatal error.
Resetting this property to NO is equivalent to omitting "location"
from the UIBackgroundModes value. Access to location is still
permitted whenever the application is running (ie not suspended), and
has sufficient authorization (ie it has WhenInUse authorization and is
in use, or it has Always authorization). However, the app will still
be subject to the usual task suspension rules.
See -requestWhenInUseAuthorization and -requestAlwaysAuthorization for
more details on possible authorization values.

iOS 9 Defer location update not working

Hi recently with the iOS 9 GM seed version out,I have seen location update(allowDeferredLocationUpdatesUntilTraveled:timeout:) not getting deferred. I am getting error kCLErrorDeferredFailed - The location manager did not enter deferred mode for an unknown reason.
Its because of this error its not entering the defer mode at all and location updates are firing continuously .
The same code used to work in iOS 8.4 and below versions.Its draining my device's battery by a huge percentage.
Is there anything we need to explicitly set or mention for iOS 9.Didn't find anything from Apple documentation?
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
if (!self.deferringUpdates) {
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:30];
self.deferringUpdates = YES;
}
}
-(void)locationManager:(CLLocationManager *)manager
didFinishDeferredUpdatesWithError:(NSError *)error {
// Stop deferring updates
self.deferringUpdates = NO;
}
I also set the allowsBackgroundLocationUpdates property but even that didn't help.
self.locationManager.allowsBackgroundLocationUpdates=YES;
In iOS 9 and later, regardless of deployment target, you must also set the allowsBackgroundLocationUpdatesproperty of the location manager object to YES in order to receive background location updates. By default, this property is NO, and it should remain this way until a time when your app actively requires background location updates.
Reduce Location Accuracy and Duration
Please let me know what additional I need to make
Thanks
Please read the discussion on the API reference page.
A few things to try, as mentioned here
Kill all apps from multitasking bar
Verify that no other app is using location services
Unplug the device from debugger and MacBook (Verify it is still getting call by logging didUpdateLocations to a file)
Make sure that the device supports deferred updates
Make sure that the distanceFilter is None, the desiredAccuracy is Best

iOS 8.2 MonitoringForRegion delegate Method was working perfectly and now not getting called

Since yesterday, I have a problem with monitoring region working with CLLocationManager
PS: my project was working perfectly I'm testing it everyday, but today this delegate method was called after 1 minute of entering a region
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{}
and now it's no more getting called I have made another project only with CLLocationManager for testing the delegate method and the same thing is happening.
Can you just tell me what the hell this could be?
[UPDATE]
i found this helpful link about iOS Region Monitoring after iPhone Restart
Just check that below service is on or off.
[CLLocationManager regionMonitoringAvailable] returns YES
CLLocationManager.monitoredRegions contains valid regions
Apple document specified that events make take between 3-5 minutes to fire.
Hope this help you.
Does locationManager:didDetermineState:forRegion: get called?
Do you call requestStateForRegion: after startMonitoringForRegion:?
Is this in background or foreground?

How to enable "When app in use" in CLLocationManager in iOS 8

I just became aware of a new privacy option for Location Service in iOS 8 which allows the user to select "When app in use" as privacy option.
My application needs to go back to iOS 7, and I can't figure out how to make this option available for my application. Currently it just says "Always/Never"
I am not doing anything special in the code. Location Services are started using
startUpdatingLocation
when in the foreground, and
startMonitoringSignificantLocationChanges
when in the background.
I also tried implementing
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
to no avail.
Any ideas?
With iOS 8 you must add a new value to your plist, either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription. If you want a specific message to show when the alert is displayed to the user, you can set the string as the value to the location key.
Also you must add this code to actually ask the user the permission, switch out the function with whichever key you used in your plist.
#pragma message ("iOS 8 Support for location updating")
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]){
[self.locationManager requestWhenInUseAuthorization];
}
More information https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/

How to stop using the Location Services within my iOS app?

I have an iOS app that uses the CLLocationManager to monitor regions and to get GPS updates. Most of the time, I want my app to continue tracking the cellphone when it goes in background or even when it gets killed, and it works well (I can still see the small arrow in the status bar after my app gets killed). The problem is that I am not able to stop monitoring the regions and GPS updates after my app has been restarted by the Location Services.
When my app gets restarted by the Location Services, I instanciate the CLLocationManager and then call its methods stopRangingBeaconsInRegion and stopUpdatingLocation before setting its delegate to nil and itself to nil.
Thanks to NSLogger, I can see that my callbacks are no longer called, but the small arrow in the status bar stays there (and my app is the only one that I allowed to use the Location Services from the settings menu).
What did I miss? Is there a way to know what still uses the Location Services in my app?
When you call stopRangingBeaconsInRegion, where are you getting the list of regions? The proper way to do this is like below:
for (CLRegion *monitored in [self.locationManager monitoredRegions]) {
NSLog(#"Stopping monitoring on: %#", monitored.identifier);
[self.monitoringLocationManager stopMonitoringForRegion:monitored];
}
for (CLBeaconRegion *region in [self.locationManager rangedRegions]) {
NSLog(#"Stopping ranging on: %# ", region.identifier);
[self.rangingLocationManager stopRangingBeaconsInRegion:region];
}
I finally found that I missed to remove some of my numerous regions. The easy way to avoid this mistake is to retrieve the list of regions monitored with the property monitoredRegions and call stopRangingBeaconsInRegion for each of them. I also forgot to call stopMonitoringSignificantLocationChanges (I didn't know that my app was using it, since I am modifying the app of a former colleague).
How do you know that it is your app that is using the location services?
The small arrow appears if the iOS itself is using the location services in the background.
if you did call stopRangingBeaconsInRegion and stopUpdatingLocation before setting the delegate to nil and you are not getting any callbacks then your app is not using the location services.

Resources