CLLocationManager Disable use of the location by the application - ios

I have a switch for the user to disable / enable the use of the location by the application. I am having two problems.
1 - When the native ios popup appears to ask if he wants to allow the use of location, and he says no, the promixa time I request permission popup is no longer displayed, and the only way to enable the user permission It is in the iPhone settings.
2 - If the user has allowed the use of the location, but then at some point you want to disable the switch is present in the application, it can not.
below is the code I am using.
-(IBAction)avancar:(id)sender{
if (locationManager == nil) {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
}
if (switchPermissao.isOn) {
[locationManager startUpdatingLocation];
if(IS_OS_8_OR_LATER) {
[locationManager requestWhenInUseAuthorization];
[locationManager requestAlwaysAuthorization];
}
}else{
[locationManager stopUpdatingLocation];
[self performSegueWithIdentifier:#"tela2" sender:self];
}
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusDenied) {
[switchPermissao setOn:NO animated:YES];
}
else if (status == kCLAuthorizationStatusAuthorizedAlways
|| status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[switchPermissao setOn:YES animated:YES];
}
[self performSegueWithIdentifier:#"tela2" sender:self];
}

RE: 1) The OS will only show the permission dialog once. After the user makes their selection, the OS will not show the permission dialog again even if your code asks for permission again. So, you must handle this with your code to present the user with a custom dialog/alert. To do this, use the CLLocationManager authorizationStatus to get the current status. Only when this status is kCLAuthorizationStatusNotDetermined will the OS show the system permission dialog. In all other cases you need to handle the permission with a custom dialog.
RE: 2) Your app cannot change the status of location services, this can only be changed by the user under the system Setting. To handle this you can present a custom dialog that will open the system Settings for your app so the user can change the status. You can use UIApplicationOpenSettingsURLString, in iOS 8, to open the system Settings for your app.

Related

Location Services Permission reset upon app upgrade on iOS

Summary:
Is it possible for iOS/App Store to reset an app's Location Service permission on app upgrade?
Detailed:
In our recent app upgrade, we believe quite a few of users that had previously granted our app "Always" Location Services permission as a result of enabling certain features were prompted with a While in Use Location Services prompt on first launch of the new version of our app. Since there is no context around this permission prompt, many of our users likely selected Don't Allow at this time.
AFAIK, it is not possible for our app to reset the user's permission settings via code. Is anyone aware of a certain version of iOS and/or device combination that would lead to this behaviour upon app upgrade?
The only time when our app would prompt users for Location Services permissions is if the authorizationStatus is set to kCLAuthorizationStatusNotDetermined. Otherwise we would start to request for location updates.
Here's a snippet of our app's launch code:
CLLocationManager *lmFollowMe = [[CLLocationManager alloc] init];
[lmFollowMe setDesiredAccuracy:kCLLocationAccuracyKilometer];
[lmFollowMe setDistanceFilter:1000];
[lmFollowMe setDelegate:self];
if ([lmFollowMe respondsToSelector:#selector(setAllowsBackgroundLocationUpdates:)]) {
[lmFollowMe setAllowsBackgroundLocationUpdates:NO];
}
[self setFollowMeLocationManager:lmFollowMe];
...
if ([CLLocationManager locationServicesEnabled] == YES) {
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusDenied) {
...
} else if (status == kCLAuthorizationStatusRestricted) {
...
} else if (status == kCLAuthorizationStatusNotDetermined) {
if ([self followMeStarted] == NO) {
[self setFollowMeStarted:YES];
[[self followMeLocationManager] requestWhenInUseAuthorization];
}
} else {
[[self followMeLocationManager] startUpdatingLocation];
}
...
Thanks!
You can not change location permission through code, but if user denied location permission then you can show alert for ask location permission with 'Setting' & 'Cancel' buttons.
If user click on 'Setting' then you can redirect user to application's setting page to update location permission by following code.
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
Thanks.

Why Location Permission Popup not coming after Reinstallation of iOS App?

I am facing one strange issue while using CLLocationManager for fetching the current Location. When I request for current location first time I am getting the permission popup having Allow and Don't Allow options. I have choose Don't Allow and then I went to App Settings and Turn On Location by choosing While Using the App and come back to the app and Uninstall the app. When I Reinstall the same ipa file I am not getting permission popup again.
Observation: When I was debugging the app I came to know that When App was installed first time and requested for Location Update I was receiving AuthorizationStatus = kCLAuthorizationStatusNotDetermined and from there I was calling requestWhenInUseAuthorization but when I was reinstalling the app instead of kCLAuthorizationStatusNotDetermined AuthorizationStatus i am directly getting requestWhenInUseAuthorization. I have observed this issue in iPhone 7 Plus with iOS 10. I have added permission keys into my info.plist file.
Please find the code snippet which i have used in the app.
- (Void)getCurrentLocation {
// Check if location services enabled in settings..
if ([CLLocationManager locationServicesEnabled]) {
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
locationManager.delegate = self;
}
else{
NSLog(#"Location Services Turn Off");
}
}
[1]: https://i.stack.imgur.com/vo4An.png
#pragma mark- CoreLocation Delegate Methods
// This will be called when app level location permissions are changed.
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
NSLog(#"didChangeStatus called.. status: %d", status);
switch (status) {
case kCLAuthorizationStatusNotDetermined:{
NSLog(#"kCLAuthorizationStatusNotDetermined");
[locationManager requestWhenInUseAuthorization];
}
break;
case kCLAuthorizationStatusRestricted:{
NSLog(#"kCLAuthorizationStatusRestricted");
}
break;
case kCLAuthorizationStatusDenied:
{
NSLog(#"kCLAuthorizationStatusDenied");
}
break;
default:{
[locationManager startUpdatingLocation];
}
break;
}
}
// This delegate method will be called in case of iOS 6 or later when location data is fetched successfully.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations{
CLLocation* receivedLocation = [locations lastObject];
[self formatLocationData:receivedLocation];
}
Please check and Let me know what should I do to get the Location Permission Popup while Re-installation of same ipa file.

CLLocationManager permissions

I'm working on permissions for location, problem is next:
User turned off location services from privacy and installed the app. I have line of code that is asking to enable location services: if (![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)... and this is working pretty fine. Problem is that app don't ask for allowing app to use location, then it asks the second time. Code for asking for permission:
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
NOTE: Everything works fine if locations services enabled, it asks for approval first time.
EDIT: Full code for permissions:
-(void)setupPermissions
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if (![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
}
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
Your code makes no sense. You have this:
if (something) {
}
if (somethingelse) {
[self.locationManager requestWhenInUseAuthorization];
}
So you have one if that is empty, and another if that always runs regardless of what the first if does. Perhaps you meant to use else if for the second condition?
(And keep in mind that, as you've already been told, calling requestWhenInUseAuthorization is pointless unless the status is NotDetermined.)
The only time you can get iOS to request user permissions is when the authorization status is NotDetermined.
If a user has denied your app, the only way you can get them to be prompted again is to uninstall the app, or reset privacy on the device.
The easiest approach would be to provide an alert controller with a link to settings so that they can turn it on themselves.
Here is a link that shows the process for doing that.

Start to monitor location updates with locationManager from Apple Watch while the iPhone app is in background

I'm working on a very simple GPS-based app where users can monitor their driving. Typically, this is what a user-driver does :
go in his/her car
launch the app
press a button that says "I'm driving"
drive
press a "I'm arrived" button when arrived to his/her destination
I want the Apple Watch companion app where I would find these two buttons. So there are two scenarios :
A/ When the app is in foreground, there are no problems.
B/ When the app is in background or not started though, I don't get any gps updates. Nothing happens. Nada.
Here's some code.
When user pressed the "I'm driving" button on the watch and the app is not started in the simulator :
// Regular location manager
self.standardLocationManager = [[CLLocationManager alloc] init];
self.standardLocationManager.delegate = self;
self.standardLocationManager.desiredAccuracy = self.accuracy;
self.standardLocationManager.activityType = CLActivityTypeAutomotiveNavigation;
self.standardLocationManager.distanceFilter = self.distanceFilter;
[self.standardLocationManager requestWhenInUseAuthorization];
// Significant Location Change location manager
self.significantLocationChangeLocationManager = [[CLLocationManager alloc] init];
self.significantLocationChangeLocationManager.delegate = self;
self.significantLocationChangeLocationManager.activityType = CLActivityTypeAutomotiveNavigation;
[self.significantLocationChangeLocationManager requestWhenInUseAuthorization];
// Start the managers
[self.standardLocationManager startUpdatingLocation];
[self.significantLocationChangeLocationManager startMonitoringSignificantLocationChanges];
I'm using MWormhole to "debug" what is happening.
The only called delegate method is :
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways){
if (manager == self.significantLocationChangeLocationManager) {
[[WatchController sharedController]notify:#"starting slc loc manager"]; // call MWWormHole to debug
[self.significantLocationChangeLocationManager startMonitoringSignificantLocationChanges];
} else if (manager == self.standardLocationManager) {
[[WatchController sharedController]notify:#"starting standard loc manager"]; // call MWWormHole to debug
[self.standardLocationManager startUpdatingLocation];
}
}
}
In this delegate method, status is Authorized because I have both debug message in my watch app.
My questions :
Is what I want to do even possible in the Apple world ?
What am I doing wrong ? Am I missing something ?
Is this post clear enough ?

How to calculate current location in WatchKit extension

How to calculate the current user location in Watch Kit extension as we can't use CoreLocation in watch kit.
Thanks in advance
You can use CoreLocation in your watch app extension very similarly to how you use it in your iPhone app. The key difference is that a user can't authorize your extension to have access to Core Location. They will need to do that from your iPhone app. So you will need to check if the user has authorized location services for your app and if they haven't, you will need to instruct them how to do it.
Here is the code I use in my watch kit extension for tracking the current location. (GPWatchAlertView is a custom controller I made to show alert messages.)
#pragma mark - CLLocation Manager
-(void)startTrackingCurrentLocation:(BOOL)forTrip
{
if (self.locationManager == nil)
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.activityType = CLActivityTypeFitness;
self.locationManager.distanceFilter = 5; //Require 15 meters of movement before we show an update
}
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse)
{
NSLog(#"%# Start tracking current location", self);
self.trackingCurrentLocation = YES;
self.gpsTrackingForTrip = forTrip;
//We wait until we have a GPS point before we start showing it
self.showCurrentLocation = NO;
[self.locationManager startUpdatingLocation];
}
else
{
[self presentControllerWithName:#"GPWatchAlertView" context:#"Unauthorized GPS Access. Please open Topo Maps+ on your iPhone and tap on current location."];
}
}
-(void)stopTrackingCurrentLocation:(id)sender
{
NSLog(#"%# Stop tracking current location", self);
self.trackingCurrentLocation = NO;
[self.locationManager stopUpdatingLocation];
self.showCurrentLocation = NO;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation* loc = [locations lastObject];
...
}
The answer by Stephan should work (haven't tested it), with just one exception.
WatchKit requires "Always" permission for the location manages. This is because your phone is really running the watch extension, in background mode. So if you only ask for "When in Use" permission, you will never get locations returned to your watch extension.
Try changing the line:
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse)
with:
if (status == kCLAuthorizationStatusAuthorizedAlways)
you should get user location on iphone app not in extension. Please check apple documentation.

Resources