I'm trying to get being called the delegate method locationManager:didEnterRegion in iOS 8 for custom region. Here is the code:
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(20, 20) radius:1000 identifier:#"asda"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
[self.locationManager startMonitoringForRegion:region];
It does call method locationManager:didStartMonitoringForRegion, but it doesn't call "enter" or "exit" region methods.
The one more strange thing is that it DOES work if I use requestAlwaysAuthorization for locationManager. But I need to get it worked with "When In Use".
Note: In iOS7 it works for both WhenInUse and Always Authorization methods.
region monitoring - it's not working with requestWhenInUseAuthorization
check Apple Docs:
".. “when-in-use” ... Apps cannot use any services that automatically relaunch the app, such as region monitoring or the significant location change service"
You must call requestAlwaysAuthorization!!!
https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManager_Class/index.html#//apple_ref/occ/instm/CLLocationManager/requestWhenInUseAuthorization
Related
I have a bluetooth device that triggers location services in my app when a button is pressed. And location services do run, but only for about 8 seconds. I have an NSLog outputting Location Found in the didUpdateToLocation delegate method. It outputs that NSLog for only that 8 seconds.
When I put the app in the foreground, location services continue again. Here is how I initialize the location manager:
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager requestAlwaysAuthorization];
[self.locationManager requestWhenInUseAuthorization];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager setAllowsBackgroundLocationUpdates:YES];
[self.locationManager allowsBackgroundLocationUpdates];
When button is pressed, I run this:
[self.locationManager startUpdatingLocation];
You need enabling the background mode (location), as long as your location-manager is capable to receive location-updates, your app will receive all bluetooth data.
As #Paulw11 mentioned in comments, using significant-location-updates will drastically reduce battery usage.
Here is the link to Apple guide.
Here is the link to a question related to getting location updates in background.
i am trying to get user's location in app's terminated state. i am doing this by startMonitoringSignificantLocationChanges but it's giving location after 3km or after 5 min. so can't create a route properly. please guide me how to do this.
if (_anotherLocationManager)
[_anotherLocationManager stopMonitoringSignificantLocationChanges];
self.anotherLocationManager = [[CLLocationManager alloc]init];
_anotherLocationManager.delegate = self;
_anotherLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
_anotherLocationManager.activityType = CLActivityTypeOtherNavigation;
if(IS_OS_8_OR_LATER) {
[_anotherLocationManager requestAlwaysAuthorization];
}
[_anotherLocationManager startMonitoringSignificantLocationChanges];
I solved my query myself...
Create a locationManager object and alloc it like this
self.locationManager = [[CLLocationManager alloc]init]; // initializing locationManager
_locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; // setting the accuracy
[self.locationManager requestAlwaysAuthorization];
if([self.locationManager respondsToSelector:#selector(allowsBackgroundLocationUpdates)]) {
[self.locationManager setAllowsBackgroundLocationUpdates: YES];
}
self.locationManager.distanceFilter = 20.0;
[self.locationManager startMonitoringSignificantLocationChanges];
self.locationManager.activityType=CLActivityTypeAutomotiveNavigation;
[self.locationManager startUpdatingLocation];
self.locationManager.pausesLocationUpdatesAutomatically = YES;
self.locationManager.delegate = self;
Now set location manager delegate method.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
{
if (newLocation.speed>7){
// here you got location, i settled speed 7 for my convenience.
}
if (newLocation.horizontalAccuracy <= self.locationManager.desiredAccuracy) {
//Desired location Found
[self.locationManager stopUpdatingLocation ];
}
}
You must have to write this stopUpdatingLocation, else your battery consumption will increase so high.
Use the Geofencing to achieve the same.
Create a Geofence of 200mtr radius.
By default, notifyOnExit would be true
Implement the delegate didExitRegion of LocationManager
For termination state, the app would be lunched with UIApplication.LaunchOptionsKey.location in didFinishLaunchingWithOptions.
Create an instance of Location Manager object on location launch key, you obtain the region at which the location exited and keep creating the 200mtr fence on every exit.
You're not going to get 200 meter granularity or continuous tracking with significant location monitoring.
Have you seen these notes in the docs:
The significant-change location service delivers updates only when
there has been a significant change in the device’s location, such as
500 meters or more.
If GPS-level accuracy isn’t critical for your app and you don’t need
continuous tracking, you can use the significant-change location
service.
In my current app i am using
self.locationManager = [[CLLocationManager alloc] init];
if ([_locationManager respondsToSelector:#selector(requestAlwaysAuthorization)])/
[_locationManager requestAlwaysAuthorization];
//self.locationManager.allowsBackgroundLocationUpdates = YES;
self.locationManager.delegate = self;
[self.locationManager startMonitoringForRegion:tempRegio
[self.locationManager startRangingBeaconsInRegion:beaconRegion];
in this case nowhere i need to know user's location still my app asks that it will use you current location even when you're not using this app
Which is annoying for end user plus it constantly display purple arrow on the statubar indicating that the app uses GPS (Which it does not )
My question is
Can we have mechanism where we can scan the beacon without use of CLLocationManager
1 possible solution is to use CBCentralManager but i do not find a proper way where i can use it to detect beacons/ibeacons
Thanks
I've used location services in many apps, but this new app has a problem on iOS 8.0 and up. I am not getting the notification on the app's first load prompting to allow location services. However, on my iOS 7.1 device I get the prompt.
Here is what I have in my appDelegate in didFinishLaunchingWithOptions:
self.locationManager = [CLLocationManager new];
[self.locationManager setDelegate:self];
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
[self initializeRegionMonitoring];
And the initializeRegionMonitoring method is:
-(void) initializeRegionMonitoring {
NSLog(#"initialize region monitoring");
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// radius of region being monitored
CLLocationDistance radius = 25; // 20 metre sensitivity
CLLocationCoordinate2D coordinate;
coordinate.latitude = 25.886099;
coordinate.longitude = -80.165124;
self.someRegion = [[CLCircularRegion alloc] initWithCenter:coordinate radius:radius identifier:#"Qualex"];
self.someRegion.notifyOnEntry = YES;
self.someRegion.notifyOnExit = YES;
[self.locationManager startMonitoringForRegion:self.someRegion];
// notify changes when the device has moved x meters
self.locationManager.distanceFilter = 20; // or set to 20 meters
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[self.locationManager startUpdatingLocation];
[self.locationManager startMonitoringSignificantLocationChanges];
}
I also have set the NSLocationAlwaysUsageDescription in my info.plist, so there must be something I've forgotten, right? Thanks for the help!
Edit:
I'm also registering for remote notifications at the same time, that's never been a problem before but I thought it might be some useful extra information.
Also, when terminated the app then re-run the notification to allow location services pops up, but goes away instantly. Just flashes on the screen. I have no idea why it would dismiss without clicking one of the options on the alert.
Before iOS 8, you could request location permission simply by instantiating a CLLocationManager object and attempting to start location tracking. On iOS 8 and above, this does not present a permission prompt; you must request authorization manually with either the requestAlwaysAuthorization or requestWhenInUseAuthorization methods.
That being said, on iOS 8, if you call either of those methods, then the CLLocationManager instance on which you called it is released, the location permission prompt will dismiss itself. What's happening here is that you are creating a location manager, requesting permission (iOS starts to try to present the permission dialog), calling initializeRegionMonitoring, and setting the self.locationManager property to a new location manager instance. This causes the first one you created to get released by ARC, so the permission prompt is dismissed before it even gets a chance to appear.
Removing the line self.locationManager = [[CLLocationManager alloc] init]; in your initializeRegionMonitoring method should fix the issue.
I have an app that uses background location updates, it needs to constantly track the devices position regardless if the app is in the foreground or background. I have the background tracking setup in the app delegate.
In the front end I have a single UIViewController with a working mapkit view all the CCLocationManager code triggers without error but didUpdateUserLocation is never fired within the custom UIViewController class.
Background location tracking is working with absolutely no problems.
Here is the code i'm using in viewDidLoad
[self.mapView setShowsUserLocation:YES];
[self.mapView setShowsPointsOfInterest:YES];
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager requestWhenInUseAuthorization];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager setDelegate:self];
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
NSString *error;
if (![CLLocationManager locationServicesEnabled]) {error = #"Error message";}
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusRestricted || status == kCLAuthorizationStatusDenied) {error = #"Error message";}
if (error) {NSLog(error);}
else
{
status = [CLLocationManager authorizationStatus];
self.locationManager.pausesLocationUpdatesAutomatically = NO;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[self.locationManager stopMonitoringSignificantLocationChanges];
[self.locationManager startUpdatingLocation];
}
Any help would be appreciated
Thanks
You need to check below details:
Testing this on simulator?? didUpdateLocations must be tested on real device.
Make sure that you specified the NSLocationAlwaysUsageDescription string or else the app won't present the authorization message, and you won't be authorized.
Have you implemented locationManager:didFailWithError:? did you got any error?
Have you implemented locationManager:didChangeAuthorizationStatus:? Are you getting this called with a successful authorization status?
I worked out the problem finally.
Turns out even if you're using the location stuff in Schema and Xcode you still need to set it in the Simulator via Debug > Location
Hopefully this helps someone else.
and now, with iOS 9, the following needs to be included for any update;
if ([ locationManager respondsToSelector:#selector(requestWhenInUseAuthorization )])
{
locationManager.allowsBackgroundLocationUpdates = YES;
}
Else background updates will be impaired.