I'm using Location service in my app.
But [CLLocationManager authorizationStatus] is kCLAuthorizationStatusNotDetermined both before [self.locationManager startUpdatingLocation];
code of project:
Implementation
#import <CoreLocation/CoreLocation.h>
#interface NewRunViewController () <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
- (void)viewDidLoad
{
[super viewDidLoad];
[self startLocationUpdates];
}
- (void)startLocationUpdates
{
// Create the location manager if this object does not
// already have one.
if (self.locationManager == nil) {
self.locationManager = [[CLLocationManager alloc] init];
}
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = 10;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
I also add NSLocationWhenInUseUsageDescription key into info.plist file.
And app also does not ask for user permission to use core location service.
Can anyone help me??
You must include a string value for the key NSLocationAlwaysUsageDescription for your target.
Look on the Info page of your target in Xcode. The string will be the text for the alert when the system asks the user for permission to use location services in your app.
This is my own code for handling same. It is requesting Always Authorization but you could replace with When in Use.
CLAuthorizationStatus auth = [CLLocationManager authorizationStatus];
if (auth == kCLAuthorizationStatusNotDetermined && [self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager performSelector:#selector(requestAlwaysAuthorization) withObject:NULL];
} else {
if (auth == kCLAuthorizationStatusAuthorizedAlways) {
[self notificationsSetup];
} else {
NSLog(#"Device is not authorized for proper use of the location Services, no logging will be performed");
}
}
You might find my github repository helpful- TTLocationHandler on Githup
you have to move
[self.locationManager startUpdatingLocation];
to the delegate method
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined:
{
NSLog(#"User still thinking");
}
break;
case kCLAuthorizationStatusDenied:
{
NSLog(#"User denied location request");
}
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
case kCLAuthorizationStatusAuthorizedAlways:
{
[self.locationManager startUpdatingLocation];
}
break;
default:
break;
}
}
Update : Make the log easier to be understood
Thank you guys for your answers. I found solution of problem. I checked the version of system like:
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
in startLocationUpdates method:
if(IS_OS_8_OR_LATER) {
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
}
Now it's working properly.
Related
Requirement:
To Trigger Location update Callback after every second when the app is in background.
Problem:
Location Callbacks are not triggered after every second. Instead we get them inconsistently sometimes after 1 second, sometimes after 4 second and even with gap of 40-50 seconds.
Current Implementation:
setActivityType = CLActivityTypeOther
setAllowsBackgroundLocationUpdates = YES
setDesiredAccuracy = kCLLocationAccuracyBestForNavigation
setDistanceFilter = kCLDistanceFilterNone
setPausesLocationUpdatesAutomatically = false
plist configuration also done for background location updates.
Please suggest what more can be done to achieve solution for this problem?
Try out below code for background location updation when a significant location change is occured:
#pragma mark - CLLocationManager
- (void)startContinuosLocationUpdate
{
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusDenied)
{
NSLog(#"Location services are disabled in settings.");
}
else
{
// for iOS 8
if ([self.anotherLocationManager respondsToSelector:#selector(requestAlwaysAuthorization)])
{
[self.anotherLocationManager requestAlwaysAuthorization];
}
// for iOS 9
if ([self.anotherLocationManager respondsToSelector:#selector(setAllowsBackgroundLocationUpdates:)])
{
[self.anotherLocationManager setAllowsBackgroundLocationUpdates:YES];
}
[self.anotherLocationManager startUpdatingLocation];
}
}
- (void)stopContinuosLocationUpdate
{
[self.anotherLocationManager stopUpdatingLocation];
}
- (void)startMonitoringLocation
{
if (_anotherLocationManager)
[_anotherLocationManager stopMonitoringSignificantLocationChanges];
self.anotherLocationManager = [[CLLocationManager alloc]init];
_anotherLocationManager.delegate = self;
_anotherLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
_anotherLocationManager.activityType = CLActivityTypeOtherNavigation;
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"9.0")) {
[_anotherLocationManager setAllowsBackgroundLocationUpdates:YES];
}
else if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
[_anotherLocationManager requestAlwaysAuthorization];
}
[_anotherLocationManager startMonitoringSignificantLocationChanges];
}
- (void)restartMonitoringLocation
{
[_anotherLocationManager stopMonitoringSignificantLocationChanges];
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"9.0")) {
[_anotherLocationManager setAllowsBackgroundLocationUpdates:YES];
}
else if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
[_anotherLocationManager requestAlwaysAuthorization];
}
[_anotherLocationManager startMonitoringSignificantLocationChanges];
}
Location services stopped working after I uninstalled my iOS10 app. I have the description set up in the Info.plist so it confuses me why location services would stop working. The app does not show up in Settings->Privacy->Location Services
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs to use your location so that it may send it to your selected contacts.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs to use your location so that it may send it to your selected contacts.</string>
Checking for status using the following code reveals that the status is Not Determined.
if ([CLLocationManager locationServicesEnabled]) {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted) {
NSLog(#"RESTRICTED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
NSLog(#"DENIED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
NSLog(#"NOT DETERMINED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) {
NSLog(#"ALWAYS");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) {
NSLog(#"WHEN IN USE");
}
}
EDIT:
The viewController viewDidLoad method contains the following code:
- (void)viewDidLoad {
[self.locationManager requestAlwaysAuthorization];
[self.locationManager requestWhenInUseAuthorization];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;
if ([CLLocationManager locationServicesEnabled]) {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted) {
NSLog(#"RESTRICTED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
NSLog(#"DENIED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
NSLog(#"NOT DETERMINED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) {
NSLog(#"ALWAYS");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) {
NSLog(#"WHEN IN USE");
}
}
}
You need to use [yourLocationManager startUpdatingLocation] which will prompt the alert for Using location.
Until then authorizationStatus will be kCLAuthorizationStatusNotDetermined
Edit
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager requestAlwaysAuthorization];
self.locationManager.delegate = self;
Add this
You need to check authorization status, and if it's xxx, you need to call requestAlwaysAuthorization() or requestWhenInUseAuthorization(). That will trigger an alert to the user.
If you've deleted the app by long-pressing the app icon and tapping the X, that revokes the user's permission to use location services, so the app will be denied access until you call requestAlwaysAuthorization() or requestWhenInUseAuthorization() again.
In iOS 8.3 with xCode 6.3.2, when I'm launching Map, it throws the following error:
Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
I have done everything and follow every step to launch a map in ios8 app, here is my code for this:
//viewcontroller default function set mapview and a function to find user current location.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[self otlMapView] setShowsUserLocation:YES];
self.otlMapView.delegate = self;
[self updateUserCurrentLocation];
}
//this function is used to fine the user current location.
-(void)updateUserCurrentLocation
{
// Create a location manager
self.locationManager = [[CLLocationManager alloc] init];
// Set a delegate to receive location callbacks
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
// Start the location manager
[self.locationManager startUpdatingLocation];
[self.locationManager requestWhenInUseAuthorization];
}
#pragma mark Location Callback Method
// Wait for location callbacks
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"Current Location%#", [locations lastObject]);
}
What am I doing wrong?
You should make sure to call
[self.locationManager requestWhenInUseAuthorization];
before calling
[self.locationManager startUpdatingLocation];
Also, have you set up your Info.plist?
I assume you've correctly set up your Info.plist already. Then try something like this:
- (void)viewDidLoad {
[self updateUserCurrentLocation];
}
- (void)updateUserCurrentLocation {
if (nil == locationManager) {
locationManager = [[CLLocationManager alloc] init];
}
locationManager.delegate = self;
// This part was added due to a location authorization issue on iOS8
// See more at: http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/
if ([self._locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self._locationManager requestWhenInUseAuthorization];
}
self.mapView.showsUserLocation = YES;
[locationManager startUpdatingLocation];
CLLocation *currentLocation = locationManager.location;
if (currentLocation) {
PAWAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.currentLocation = currentLocation;
}
}
Check if you have this key in your info.plist,
"Privacy - Location Usage Description",
if yes remove this and retain the "When in use" key. it should then work.
Please don't mark it as duplicate because I took help from others posted answer in stack overflow. But still I faced some issues. Location manager delegate not get called even in real device also. And also it's not asking for the permission.
Below is my code.
- (IBAction)getUserLocationAction:(id)sender
{
if([CLLocationManager locationServicesEnabled])
{
if(!locationManager)
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if ([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
[locationManager startUpdatingLocation];
//[locationManager startMonitoringSignificantLocationChanges];
}
else
{
NSLog(#"Location service is not enabled");
}
}
#pragma mark - Location Manager Delegate-
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"%#", locations);
userLocation = [locations lastObject];
NSLog(#"User Current Locatiion\nLat: %+.6f\nLong: %+.6f", [userLocation coordinate].latitude, [userLocation coordinate].longitude);
[locationManager stopUpdatingLocation];
//[locationManager stopMonitoringSignificantLocationChanges];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"Error: %#", [error localizedDescription]);
}
I also add the below two key in my .plist file
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app want to use your location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app want to use your location</string>
I have also added the frameworks
I am not sure where I am doing wrong. Please help me.
UPDATE
Firstly I think its an issue with my code but after some research it's working as expected in iOS7. The code is remain same, this issue occur only in iOS8. Please let me know what changes needs to be done for working in iOS8 also.
You need to do some more checking:
- (IBAction)getUserLocationAction:(id)sender
{
if([CLLocationManager locationServicesEnabled]) {
if(!self.locationManager) {
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus];
if (authStatus == kCLAuthorizationStatusNotDetermined) {
// Check for iOS 8 method
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
else {
[self.locationManager startUpdatingLocation];
}
}
else if(authStatus == kCLAuthorizationStatusAuthorizedAlways || authStatus == kCLAuthorizationStatusAuthorizedWhenInUse || authStatus == kCLAuthorizationStatusAuthorized) {
[self.locationManager startUpdatingLocation];
}
else if(authStatus == kCLAuthorizationStatusDenied){
NSLog(#"User did not allow location tracking.");
// present some dialog that you want the location.
}
else {
// kCLAuthorizationStatusRestricted
// restriction on the device do not allow location tracking.
}
}
else {
NSLog(#"Location service is not enabled");
}
}
Also you need to handle the use callback:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status != kCLAuthorizationStatusRestricted && status !=kCLAuthorizationStatusDenied) {
[self.locationManager startUpdatingLocation];
}
}
Check your Location Access settings..so go to Setting-->Privacy-->Location Services-->Your app
I have found the following solution explaining how to utilize location services in iOS 8. Unfortunately I have got only an iPhone 6 simulator and not the real device. I tried to add this code in the viewDidLoad method but the authorization dialog is never shown. Why is this?
I added a breakpoint in the following, it gets executed but does not show the dialouge..:
// Will open an confirm dialog to get user's approval
[locationManager requestAlwaysAuthorization];
And here is the full viewDidLoad method:
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Initialize location manager
locationManager = [CLLocationManager new];
locationManager.delegate = self;
float system = [[[UIDevice currentDevice] systemVersion] floatValue ];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 &&
[CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways
) {
// Will open an confirm dialog to get user's approval
[locationManager requestAlwaysAuthorization];
} else {
[locationManager startUpdatingLocation]; //Will update location immediately
}
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
PS: I also modified the info.plist as following:
PPS:
This is how I implement (in the same ViewController) the rest of the CLLocationManagerDelegate protocol:
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined: {
NSLog(#"User still thinking..");
} break;
case kCLAuthorizationStatusDenied: {
NSLog(#"User dislikes your app");
} break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
case kCLAuthorizationStatusAuthorizedAlways: {
[locationManager startUpdatingLocation];
} break;
default:
break;
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations lastObject];
NSLog(#"lat%f - lon%f", location.coordinate.latitude, location.coordinate.longitude);
}
EDIT 2: I added the following block of code as suggested in an answer. The code is executed but dialogue fails to appear.
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined: {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0){
[locationManager requestAlwaysAuthorization];
}
} break;
case kCLAuthorizationStatusDenied: {
NSLog(#"User dislikes your app");
} break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
case kCLAuthorizationStatusAuthorizedAlways: {
[locationManager startUpdatingLocation];
} break;
default:
break;
}
}
Add this to the didChangeAuthorizationStatus:
case kCLAuthorizationStatusNotDetermined: {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
[locationManager requestAlwaysAuthorization];
}
EDIT
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 &&
[CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways
) {
// Will open an confirm dialog to get user's approval
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation]; //Will update location immediately
I think your code might not have any problem. Here is the code that I am using:-
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
if(IS_OS_8_OR_LATER) {
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation];
You might not understand how the authorization dialog works. For your information, the authorization dialog will only appear once (Either you allow it or disallow it). Afterwards, you can change the authorization from the Settings.
If you want the authorization dialog to re-appear, you should delete the app from you iPhone Simulator (Long press the app and tap the X button). When you relaunch the app from XCode into the iPhone Simulator, then only the authorization dialog will re-appear.