My app requires location data to run. I makes sure user has to accept location services for my app before logging in. If user declines, it will prevent user log in until user grants the app permission to use location services.
Everything is working well except for 1 test user's device. The device is not getting the location data at all even if the user granted the app location services permission. There is no GPS icon appears. Google map is working fine for the user's device. I'm really not sure what is going on here. It looks like didUpdateToLocation is not called on this user's device at all. What could be causing this issue?
Code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
[self getCurrentLocation];
...
}
- (void)getCurrentLocation {
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
locationManager.distanceFilter = 100; // meters
[locationManager startMonitoringSignificantLocationChanges];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
[self setLatitude:[NSNumber numberWithFloat:currentLocation.coordinate.latitude]];
[self setLongitude:[NSNumber numberWithFloat:currentLocation.coordinate.longitude]];
if (loginController) {
[loginController validateSession];
loginController = nil;
}
}
}
Please Check the below commends. Some times this same issue Happened for me.
Uninstall completely and Re Install and check Application again.
Reset Network Settings in iPhone Settings.
Delete previous installed application and reinstall again.
You are not using
- (void)startUpdatingLocation;
But you use
- (void)startMonitoringSignificantLocationChanges;
Since you set up all the filter you probably want to use the first (startUpdatingLocation).
As to why this didn't work one a single user's device:startMonitoringSignificantLocationChanges does not use GPS to triangulate the position of the user and therefore comparing it with google maps does not help you.
For more information on both methods investigate further in Apple's documentation:
Apple Doku
Related
I have a location app that needs to get accurate location periodically. Currently I am getting constantly getting location in didUpdateLocation but I only ever log the location every 5 seconds. I am interested in a solution that gets accurate location periodically or on signification change. I would like either or both of these scenarios:
(by very accurate, I need 10m of desired accuracy)
Get a very accurate location every 5 seconds
Notify/callback if user moves a threshold ( eg moves 5 - 10 meters)
The app needs to work when backgrounded as well and location must still be logged if user switches to another app.
I was considering turning on/off location every 5 seconds but was not sure if that is the best practice. I also know there is also allowDeferredLocationUpdatesUntilTraveled but I believe that only applied to backgrounded mode. I would appreciate a solution that saves battery when the app is in use and in background mode. Please share your solutions and best practices for my use case.
I did write an app using Location services, app must send location every 10s. And it worked very well.
Just use the "allowDeferredLocationUpdatesUntilTraveled:timeout" method, following Apple's doc.
Steps are as follows:
Required: Register background mode for update Location.
Create LocationManger and startUpdatingLocation, with accuracy and filteredDistance as whatever you want:
-(void) initLocationManager
{
// Create the manager object
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
_locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
_locationManager.desiredAccuracy = 45;
_locationManager.distanceFilter = 100;
// Once configured, the location manager must be "started".
[_locationManager startUpdatingLocation];
}
To keep app run forever using "allowDeferredLocationUpdatesUntilTraveled:timeout" method in background, you must restart updatingLocation with new parameter when app moves to background, like this:
- (void)applicationWillResignActive:(UIApplication *)application {
_isBackgroundMode = YES;
[_locationManager stopUpdatingLocation];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[_locationManager startUpdatingLocation];
}
App gets updatedLocations as normal with "locationManager:didUpdateLocations:" callback:
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// store data
CLLocation *newLocation = [locations lastObject];
self.userLocation = newLocation;
//tell the centralManager that you want to deferred this updatedLocation
if (_isBackgroundMode && !_deferringUpdates)
{
_deferringUpdates = YES;
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
}
}
But you should handle the data in then "locationManager:didFinishDeferredUpdatesWithError:" callback for your purpose
- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
_deferringUpdates = NO;
//do something
}
NOTE: I think we should reset parameters of LocationManager each time app switches between background/forgeround mode.
Hopefully this should help
I'm first using the CoreLocation framework. I have a table and by button click a new location should be added and the distance to all entries in the table should be shown and updated all the time. That is why I have a BOOL saveNewLocation which is set to Yes when the button is clicked. Because the updates need to happen still all the time in the background, but when the button is clicked only a new entry is added.
At the moment I have this in my viewDidLoad:
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
And this is my delegate method:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
self.currentLocation = newLocation;
if(self.saveNewLocation){
[PointOfInterest addPointOfInterest:newLocation withAddress:#"" andNotes:#"" inManagedObjectContext:self.cdh.context];
self.saveNewLocation = NO;
}
[self updateAllDistances];
}
And this my button:
- (IBAction)addLocationClicked:(id)sender {
self.saveNewLocation = YES;
}
But the problem at the moment is that when you click this button, there is sometimes a big lag and nothing happens. Sometimes immediately a new location is added. How can I avoid this lag and instantly add a new location by click?
The time interval between update calls to the location manager delegate is variable, so the behavior you're experiencing is expected.
CLLocationManager has a property called location which returns the last known location of the user (or nil if you've never used the Location Manager in the app).
Instead of waiting for the LocationManager to update, grab the last known location of the user instead:
- (IBAction)addLocationClicked:(id)sender {
CLLocation *location = self.locationManager.location;
if (location && [NSDate timeIntervalSinceReferenceDate] - location.timeStamp.timeIntervalSinceReferenceDate < 60 * 10){
//Do something with the location if the location manager returns a location within the last 10 minutes
} else {
self.saveNewLocation = YES;
}
}
If the app has never asked for it's location, you may get nil, in which case you'll have to wait for the locationManager to update. But otherwise, you can just grab the last known location. You can also check whether the location was update recently by checking the timeStamp on the location object.
You also may want to set a state flag indicating that the app should wait for a location update when the location manager is first used. When you first start up the LocationManager, you can't really know how up-to-date that location is. But once the manager begins updating the delegate, you can be reasonably certain the location manager holds a fairly up-to-date location.
Ive been struggling with a way to retrieve information periodically from a BT device. My bluetooth device is located in a vehicle typically, so my question is if its possible to use say... (if user traveling > 10km/h) to run a task. Or on major location change.
Is is possible to get a really course location that I would be able to use to get a general idea of wether the user is moving? I only need it to trigger once every couple days(while user is driving). The user never interacts with my app after initial setup.
Thanks.
Implementation of cmyr's suggestion:
CLLocationManager *locationManager;
int badge_count = 0;
- (void)startSignificantChangeUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.pausesLocationUpdatesAutomatically = YES;
locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[locationManager requestAlwaysAuthorization];
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
locationManager.distanceFilter = 500; // meters
[locationManager allowDeferredLocationUpdatesUntilTraveled:501 timeout:-1];
[locationManager startMonitoringSignificantLocationChanges];
[locationManager startUpdatingLocation];
}
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
badge_count++;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge_count];
NSLog(#"Location Event WOOT!");
}
Unfortunately I cannot get the event to trigger. I have added Location updated to the apps plist.
The above code is contained inside my app delegate.m file
Core Location has a set of APIs for specifically this use-case, which Apple refers to as Significant Location Change Monitoring.
From the documentation:
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.
This API only updates your location when and if you've traveled the specified distance. It does not provide constant updates. If you need constant updates, you will have to use the standard location service.
Hi I am implementing Location services in my app. First I have to know my Coordinates to get the distance between some places that I have in a list and the device. Then if I go into a place I can make a check in, so, I need to get coordinates again, and the problem is here. Second time I try to get coordinates, the method -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations is not called.. and I can not get new Coordinates.
My manager is located in a NSObject sublcass with this code:
(id)init {
if ( self = [super init] ) {
if ([CLLocationManager locationServicesEnabled])
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
}
return self;
}
-(void) checkLongLatitudeAgain {
[locationManager startUpdatingLocation];
}
#pragma mark Delegates de CLLocationManager
//
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSLog(#"LON%f", manager.location.coordinate.longitude);
NSLog(#"LAT:%f", manager.location.coordinate.latitude);
NSTimeInterval howRecentNewLocation = [newLocationeventDate timeIntervalSinceNow];
if (manager.location.horizontalAccuracy <= 100.0 && howRecentNewLocation < -0.0 && howRecentNewLocation > -20.0){
//Usar coordenada
[self.delegate getLocationForCheckIn:manager.location];
[self stopUpdatingLocation:#"Fins"];
}
}
// ---------------------------------------------------------------------------------------------------------------------
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
//
if ([error code] != kCLErrorLocationUnknown) {
[self stopUpdatingLocation:NSLocalizedString(#"Error", #"Error")];
}
//
}
// ---------------------------------------------------------------------------------------------------------------------
- (void)stopUpdatingLocation:(NSString *)state {
//Detenemos la lectura del GPS
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
NSLog(#"Stop gps");
//
}
I call the class when the list of places is open, and also when inside a place the user press checkIn button. Both times I do it with this code:
WPLocationManager *location = [[WPLocationManager alloc]init];
[location checkLongLatitudeAgain];
You are creating a new manager every time:
WPLocationManager *location = [[WPLocationManager alloc]init];
[location checkLongLatitudeAgain];
That new manager is not assigned to any delegate.
You need to use the previous manager you have created and assigned to your delegate, something like:
[locationManager checkLongLatitudeAgain];
You can check the documentation at http://developer.apple.com - https://developer.apple.com/library/ios/documentation/userexperience/conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html
In particular you can check the Starting the Standard Location Service and Starting the Significant-Change Location Service sections. You have to use the startMonitoringSignificantLocationChanges or startUpdatingLocation method of CLLocationManager, cache your location somewhere and update it only when a new location is received, otherwise like it is stated in the documentation: "If a location update has already been delivered, you can also get the most recent location data directly from the CLLocationManager object without waiting for a new event to be delivered".
i dont know why you are initiating your location manager again again, also even if you some how manage to solve current problem but it's not proper way of dealing with location manage based applications.I had been in trouble previously when i was working on location based app. the best approach for location based app is singleton.
apple forum discussion
you can find
this
and this very helpful.
just an advice, :)
Thanks.
In iOS8 for me I had to call [locationManager stopUpdatingLocation]; before calling [locationManager startUpdatingLocation] to start getting updates second time and it works for me.
I'm trying to build an app that gives GPS coordinates on regular time intervals for display on a label and for sending to a web server, but it's proving difficult. I've managed to get it to give me accurate live GPS coordinates, but I have to press a button to get the label to refresh.
I figure the didUpdateLocation method is an ok place for this for now, but it seems to never run. I'm testing this by including an NSLog post - when I do this with Apple's LocateMe example app it runs like it should.
Below is my method:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
theLocation = [NSString stringWithFormat:#"latitude: %f
longitude: %f", locationManager.location.coordinate.latitude,
locationManager.location.coordinate.longitude];
NSLog(#"location manager did something!!!");
}
Though I'm guessing that the issue lies with something outside of the above method. I suppose I should include my viewDidLoad method as that's where I startUpdatingLocation:
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
[outletLabelData setText:(#"Loaded")];
}
I've also tried having the startUpdatingLocation in my button action method, and even having it work like a switch where you start and stop the updates (which should trigger the update event), but still no success.
Other details:
Xcode 4.4
iOS 5.1
Testing app on my iPhone while plugged into my mac
Can anyone help with this?
You need to tell your CCLocationManager who is the delegate. In your case it is your current controller.
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
and obviously make sure that your controller conforms to CLLocationManagerDelegate protocol.