Request location updates permissions iOS - ios

I currently have my app setup to request location services always, using [locationManager requestAlwaysAuthorization]; and NSLocationAlwaysUsageDescription
This works fine, however I would like to give the option of using location services only while using the app like in the screenshot below.
I have tried adding NSLocationWhenInUseUsageDescription however this overides he always request and only gives the alert for while in use, any ideas on who to give both options in settings?

First ask the user using your own dialog with two options - always / when using the app. Then call appropriate permission request according to the user's choice.
Either:
[locationManager requestAlwaysAuthorization];
or:
[locationManager requestWhenInUseAuthorization];
having both in plist is valid so that's not a problem. Depends on when you actually request it in the code.
It will be slightly tricky to maintain though, so a good code structure is crucial.

The built in iOS alert will only allows for one level of permission and it will only ask the user once. The assumption is that most apps will only need one or the other. In any case, if you want to have both options show up in the Settings, you must ask for Always permission.
More importantly though:
The Always setting is really only to be used by apps that require background location updates. So unless your app requires it, you shouldn't be asking for it. Also, using background location mode will cause your app to be more heavily scrutinized during the app review process.

Related

beacon detection in background even though app is closed

Hi i am developing an application with beacons i need to scan for beacons continuously even though app is closed. is there any cordova plugin which is able to run in background, please suggest me sample applications tutorials
Background modes are only a partial answer. You need to have one of or both entries in Info.plist:
Then in some place in your code you need to ask for requestWhenInUseAuthorization or in your case requestAlwaysAuthorization. Then you need to handle this in location manager delegate. I'm doing it like so:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self startMonitoringAllRegions];
[self.locationManager startUpdatingLocation];
}
else if (status == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestWhenInUseAuthorization];
}
}
So somewhere i'm asking to start monitoring for a beacon region then in this method I'm checking if I have permission from the user to do that if not I'm requesting if (the string from the plist will be displayed) if I have I'm starting updating user location.
Hope that will get you going :D
This is possible with native iOS code, but not with Cordova. When you say "scan" beacons, this usually means using the CLLocation ranging APIs, which provid updates of all visible beacons every second. In order to do this continuously in the background, you need to:
Add location as a background mode in your app's .plist filke in XCode as #hasan83 suggests.
Start a background thread to keep your app running in the background.
Request requestAlwaysAuthorization as #sloik suggests.
I wrote a tutorial and reference app of how to do this. The tutorial mentions this working only for 3 minutes, but with the background mode of location, the 3 minute restriction goes away. Be aware that adding this background mode may make it more difficult to get your app approved for the AppStore. Apple must approve of the reasons for this background use of location services.
The reason you can't do this with Cordova is because JavaScript must run to collect the beacon data returned by the ranging APIs. This works in the foreground, but not in the background, because Cordova relies on a WebView being in the foreground to execute JavaScript code. In the background, your custom code just cannot run.
Allow UIBackgroundModes for location updates in the project plist
file.
Select the project at the left pane, then select Capabilities and expand the Background Modes list and select the Location updates option:
Try this plugin for using iBeacons. There seem to be a few plugins for keeping apps running in the background, e.g. this one. I doubt you'll find both functions in the same plugin.

Apple Binary Rejected (2.16)

My app requires users current location to show him direction to a particular location in google map
Below is the code to show location on web view-
[self.getDirectionsWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://maps.google.com/maps?saddr=%f,%f&daddr=%f,%f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude,self.projectLatitude,self.projectLongitude]]]];
The app declares support for location in .plist by using NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation];
Apple rejected the app with following reason
2.16 Details
Your app declares support for location in the UIBackgroundModes key in
your Info.plist file but still does not declare any features that
require persistent location. Apps that declare support for location in
the UIBackgroundModes key in your Info.plist file must have features
that require persistent location.
Specifically, we noticed that the Directions feature does not require
persistent location information, since it does not include
turn-by-turn navigation.
Any help will be appreciated, Thanks in Advance.
You just remove the location support from UIBackgroundModes key in info.plist
As you must only use UIBackgroundModes for location when you want to fetch location when your app is in background.
In your app declaration of NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription is enough.
Based on:
My app requires users current location to show him direction to a particular location in google map.
NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription
we noticed that the Directions feature does not require persistent location information, since it does not include turn-by-turn navigation
It looks like they're stating you shouldn't need location information unless the app is actually active. Since the location information is used to show the user the direction they need to head in, you should be able to simply adjust (with a little latency of course) when your app comes to the fore.
From Apple's documentation:
UIBackgroundModes (Array - iOS) specifies that the app provides specific background services and must be allowed to continue running while in the background.
These keys should be used sparingly and only by apps providing the indicated services. Where alternatives for running in the background exist, those alternatives should be used instead.
For example, apps can use the significant location change interface to receive location events instead of registering as a background location app.
That'd be my analysis though it's equally likely that the reviewer just had an argument with their significant other that morning, and is just being capricious :-) Nah, just joking, but it does sometimes seem to outsiders that the decisions they make are, shall we say, less than perfectly consistent.
It's is not necessary to request the background mode to request the user's current location.
I would recommend to use NSLocationWhenInUseUsageDescription if you don't need to use the user's location in background. Users are more inclined to deny the user location authorization when they see NSLocationAlwaysUsageDescription because they think that reduce the device's battery

iOS - Turn on Location Services with Settings and Cancel buttons -How do I Capture Cancel button click

When the user launches the app for the first time and attempts to login, they are prompted with the iOS dialog - "Turn On Location Services".
I need to capture when the user clicks "cancel". Is there a Notification sent? If so, what is its name? I've been unable to locate it.
The CLAUthorizationStatus is kCLAuthorizationDenied when Location Services are Disabled OR the user clicked "Don't allow". When the user clicks "Cancel", it does not fire the authorizationChange event. When user clicks "Cancel", the app just hangs.
Short answer: You can't catch that notification. You can infer about the user choice and act consequently by using CLLocationManager methods (the longer answer below).
Longer answer:
Firstly, welcome on Stack Overflow. Before kindly posing your question, and trying to be collaborative with people that are here to help, it's a good idea to search if somebody else previously posed the same question.
A brief search gave (just to mention some of them):
How to handle “Cancel” button on Alert pop up for Location services
How to get location services to reprompt the user for location permission if they accidentally refused it?
locationManager:didFailWithError: not called if user Location Services are off
How to prompt user to turn on Location Services…again
How can I prompt the user to turn on location services after user has denied their use
How to ask permission from user for second time to allow to access the current location?
Now, let's try to summarize them all, starting from iOS docs:
If your app relies on location services to function properly, you should include the UIRequiredDeviceCapabilities key in the app’s Info.plist file. You use this key to specify the location services that must be present in order for your app to run. The App Store uses the information in this key from preventing users from downloading apps to devices that do not contain the listed features.
Important: If your app uses location services but is able to operate successfully without them, do not include the corresponding strings in the UIRequiredDeviceCapabilities key.
So, if your app really needs to access the user's position you should add location-services and eventually gps to UIRequiredDeviceCapabilities.
Then, somewhere in your code - when needed, you have to check if the location services are enabled.
[CLLocationManager locationServicesEnabled]
they may be disallowed for three reasons:
The user can disable location services in the Settings app.
The user can deny location services for a specific app.
The device might be in Airplane mode and unable to power up the necessary hardware.
You are interested in the second case: the user refused to allow your app to use the location services.
Again, from the docs:
Important: 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.
[CLLocationManager authorizationStatus]
That may return:
kCLAuthorizationStatusNotDetermined if the user has not yet made a choice regarding whether this application can use location services.
kCLAuthorizationStatusRestricted this application is not authorized to use location services. The user cannot change this application’s status, possibly due to active restrictions such as parental controls being in place.
kCLAuthorizationStatusDenied The user explicitly denied the use of location services for this application or location services are currently disabled in Settings.
kCLAuthorizationStatusAuthorized This application is authorized to use location services.
If[CLLocationManager locationServicesEnabled] returns NO and you attempt to start location services anyway (i.e. calling [locationManager startUpdatingLocation]), the system prompts the user to confirm whether location services should be re-enabled. Given that location services are very likely to be disabled on purpose, the user might not welcome this prompt.
I suppose you know, and did all the previous steps (I'm only sure you checked the authorizationStatus). You refused to show us the significant code of your app so I can only suppose the overall logic behind. Now you said your app hangs. This should be because you didn't catch the error properly? Catching the error is the way to re-prompt the user, if you wish.
After calling [locationManager startUpdatingLocation], if not authorized, your delegate should define a locationManager:didFailWithError: in order to catch the kCLErrorDenied.
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
You may show, at this point, a UIAlert to insist asking the user to give you access to its position, or trigger a change in the UI or whatever you like.
Final notes
I hope you understand why I was asking for the code: the reason was to offer you an alternative solution instead of reply "You can't catch the 'Cancel' notification".
If this answer does not satisfy your question please elaborate why you need to catch the pushing of the "Cancel"/"Do not allow" button, so we can provide alternatives.
Clearly my advice is to not annoy people to death by continuously ask them for enabling location services if they don't want.
Post scriptum: Maybe that the answer looks pedantic and obvious in certain parts if not all to you, but we are here to provide answers also for future readers.

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.

How to get IOS to ask users whether they want to allow application to use their location everytime?

If we try to access the user's location, iOS will tell the user that our application wants to use their location.
If I do this
[locationManager startUpdatingLocation];
An alert will show.
However, that only happens once.
It looks like some variable or default must have been set up once that display pops out.
How do I reset those default so that next time my app wants to use location users will be asked again?
Google map can displays that again and again.
It's Apple that asks them for permission, not you
Translation: You don't have any control over that part of the process. The little popup:
is only shown by Apple when you first ask for it - so the user always feels in control. After they accept for the first time, Apple assumes they are OK with your app getting their location information from their device, and won't show it again*.
*Unless they specifically go into Settings and disable Location Services for you app.
It's only showed on the first time and there's nothing you can do to change that. What you can do is ask your users to allow it on settings.
You can check if your app has permissions by checking:
[CLLocationManager locationServicesEnabled]
From the docs:
The user can enable or disable location services from the Settings application by toggling the Location Services switch in General.
You should check the return value of this method before starting location updates to determine whether the user has location services enabled for the current device. If this method returns NO and you start location updates anyway, the Core Location framework prompts the user to confirm whether location services should be reenabled.

Resources