iOS7 and iOS 8 location services - ios

I have an app and I want to add some location based features to it. It supports both iOS 7 and 8, but I'm having some issues.
I want to request the permission for location only when the user taps a certain button on a certain viewController. The issue is that the permission request appears as soon as the app launches. To be more precise, between ViewWillAppear and ViewDidAppear functions of the first viewController.
What I have tried previously:
having the NSLocationWhenInUseUsageDescription key in the plist (for iOS8).
In terms of code:
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
Removing the plist key -> this caused the pop up in iOS8 not to appear anymore, but it still does in iOS7
At the moment every single bit of code related to CoreLocation is commented out and I still do get the dialog asking me for permissions (iOS7 only)
I don't know what else I could possibly try, so any bit of help is much appreciated

That's just how iOS 7 (and before) works. You're not in charge of the authorization dialog: the system is. You can't make it appear; the system, seeing that you are using Core Location, presents it on your behalf. That is exactly the sort of thing that iOS 8 changes. All you can do in iOS 7 is look to see whether location services are turned on and whether your app is authorized.

Ok, I discovered the issue.
It turns out that a third party app is requesting permissions as soon as the app opens.
Thank you for all the answers.

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 GPS tracking app that runs all the time

I am trying to make an app to track the user GPS all the time, this app is a kind of car GPS tracker to get the location of driver all the time and send it to server.
I have tried to add "location updates" to the "background modes" but the app will automatically suspends after 10 mins when going into background.
Is there a way to make this app run all the time and get the GPS location?
You have two options here:
1) Regular location tracking. This type of tracking works with kCLAuthorizationStatusAuthorizedWhenInUse and kCLAuthorizationStatusAuthorizedAlways authorizations. When CLLocationManager started tracking location once it will receive location updates in delegate method locationManager:didUpdateLocations:. App can go to suspended state, but when location manager receive new location app goes to background state and handles new location in delegate method. How to setup location manager:
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
// Setup location tracker accuracy
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
// Distance filter
self.locationManager.distanceFilter = 50.f;
// Assign location tracker delegate
self.locationManager.delegate = self;
// This setup pauses location manager if location wasn't changed
[self.locationManager setPausesLocationUpdatesAutomatically:YES];
// For iOS9 we have to call this method if we want to receive location updates in background mode
if([self.locationManager respondsToSelector:#selector(allowsBackgroundLocationUpdates)]){
[self.locationManager setAllowsBackgroundLocationUpdates:YES];
}
[self.locationManager startUpdatingLocation];
}
2) Signification location changes tracking. This type of tracking works only with kCLAuthorizationStatusAuthorizedAlways authorization. It receives new location only each 500 meters, so distance filter and desiredAccuracy don't work here. App can go to suspended state, and even can be terminated by system, but when location updates app goes to background state and receives location in delegate method locationManager:didUpdateLocations:.If app was terminated by system, it will be relaunched in background with UIApplicationLaunchOptionsLocationKey key in launch options in didFinishLaunchingWithOptions app delegate method. How to setup this type on tracking:
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
// Assign location tracker delegate
self.locationManager.delegate = self;
// For iOS9 we have to call this method if we want to receive location updates in background mode
if([self.locationManager respondsToSelector:#selector(allowsBackgroundLocationUpdates)]){
[self.locationManager setAllowsBackgroundLocationUpdates:YES];
}
[self.locationManager startMonitoringSignificantLocationChanges];
}
You should notice that both of these methods does not guarantee that your application does not go to suspended state.
Also, if app was terminated by user (for example from app switcher by swipe) location tracking in background will not work.
UPDATE (corresponding to comments)
Here is my code examples that work for me:
For Regular tracking. Run the example, provide access to user location, tap Start button to start location updates. To test locations in simulator choose in simulator menu Debug > Location > Freeway Drive. Now you can push app to background by home button (Command+Shift+H). Leave simulator for more than 10 minutes, and all this time app will receive locations. When you return to app you will see red pins on the map.
For Significant changes. Run the app and test by the same way as for previous example.
Monitoring Significant changes can be started only by method [self.locationManager startMonitoringSignificantLocationChanges];
UPDATE (iOS 11)
Changes to location tracking in iOS 11
iOS 11 also makes some major changes to existing APIs. One of the affected areas is location tracking. If your app only uses location while the app is in the foreground, as most apps do, you might not have to change anything at all; however, if it’s one of those apps that continuously track user’s location throughout the day, you should probably book some time this summer for making some changes in how you do the tracking and testing possible usage scenarios.
follow this link: https://mackuba.eu/2017/07/13/changes-to-location-tracking-in-ios-11/
I am sure it is useful for the author because the question was asked in Feb 2016 and I am giving an answer in June 2019. This answer maybe is useful for other users.
Recently, I was working with the same requirement. After 2-3 week hard work, I did it. For other users, I create a helper class for it. Which is available in GitHub.
Please use HSLocationManager for your requirement. I have achieved the same requirements in one of my project
Location manager that allows getting background location updates every
n seconds with desired location accuracy.
Advantage:
OS will never kill our app if the location manager is currently
running.
Give periodically location update when it required(range is between 2 -
170 seconds (limited by max allowed background task time))
Customizable location accuracy and time period.
Low memory consumption(Singleton class)
In reply to comment 1 in the solution (I can't comment anywhere yet): you didn't seem to solve the problem as your app gets suspended and doesn't update the location any more after 10 minutes.
I had the same issue: I had set setAllowsBackgroundLocationUpdates to YES, and I had the NSLocationAlwaysUsageDescription key in my Info.plist, but my App also used to stop tracking location after 10 minutes.
I solved it by adding both NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription to the Info.plist file so it looks like this:
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs to use your location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs to use your location</string>
set it.it take power of battery but your application run in Background.OS does not Suspend your App
[self.locationManager setPausesLocationUpdatesAutomatically:NO];

iOS Google Maps SDK - Using location in background

I am utilizing the Google Maps iOS SDK in my app and am utilizing a GMSMapView with myLocationEnabled = TRUE. The user has authorized for location usage in app.
The problem is that when a user opens the screen with the map, then closes the app with that screen visible, the map continues to use the user's location, even if the user only allowed location usage "While Using the App". This is a huge problem as it is a big drain on battery, and have no clue how to fix it.
I am using the latest version of the SDK (1.11.1).
Any ideas?
It might help to stop the location updates:
[[[CLLocationManager alloc] init] stopUpdatingLocation];
You can restart requesting for updates using this
[[[CLLocationManager alloc] init] startUpdatingLocation];
Please replace the location manager with your instance if you have already instantiated them.

Access the user's location on Today Extension

Is it possible to access the user's location on a widget?
I used the new iOS 8 API
[locationManager requestWhenInUseAuthorization];
and I added to the info.plist file the key
NSLocationWhenInUseDescription
however, when I request the location access, an alert should appear, but it doesn't happen.
Are there some not declared limitations on iOS today extensions?
As I found out, didUpdateLocations: delegate method doesn't work in today extension. So, to get location use locationManager.location.
Along with requesting authorization, you must also explicitly ask your location manager to start updating locations.
[locationManager requestWhenInUseAuthorization];
[locationManager startUpdatingLocation];
The key NSLocationWhenInUseDescription is wrong, therefore the Alert doesn't come up.
Change it to NSLocationWhenInUseUsageDescription and it should work.
For all keys you can refer to this:
https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html
The authorization dialog does not pop up in extensions. Your app, which should be in the same App Group (in capabilities)

didUpdateToLocation alert called only twice

Suppose in the starting the location services are off in the default settings page. I have a button in the app to turn on the location services if first time I click on that it shows the default alert to change the settings to turn on
locationmanager = [[CLLocationManager alloc]init];
[locationmanager setDelegate:self];
[locationmanager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationmanager startUpdatingLocation];
It is working fine two times. but if it got third time location services are in off condition and click on on button it doesn't show any alert. I am unable to know the CLLocation behavior. May b its not a good question to ask but still I want to clear this concept. if anyone has some idea then please help me out.
Thank You.
Here's what Apple documentation says:
In addition to hardware not being available, the user has the option of denying an application’s access to location service data. During its initial uses by an application, the Core Location framework prompts the user to confirm that using the location service is acceptable. If the user denies the request, the CLLocationManager object reports an appropriate error to its delegate during future requests. You can also check the application’s explicit authorization status using the authorizationStatus method.
So the alert could or could not appear, based on authorizationStatus.

Resources