iphone : using Background location services is stopped after a little time - iphone

i'm trying to get a location and compare it with a location online all that happen in background
the method i create is working fine using background location service but after a minute or so the location icon in the status bar is getting disappear and the method is not getting called any longer
here is the code
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
double lat = newLocation.coordinate.latitude;
double lon = newLocation.coordinate.longitude;
NSURL * locationURL = [NSURL URLWithString:[NSString stringWithFormat:#"http://somedomainname.com/iphoneLocation?lat=%f&lon=%f",lat,lon]];
NSData * responseData = [NSData dataWithContentsOfURL:locationURL];
NSString* aStr;
aStr = [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding];
if ([aStr isEqualToString:#"out Of Any Knowen Range"] ){
UILocalNotification *notify =[[UILocalNotification alloc] init];
notify.alertAction = [[NSString alloc] initWithString: #"View"];
notify.fireDate=nil;
notify.alertBody = [NSString stringWithFormat:#"New Data Occured"];
notify.soundName = UILocalNotificationDefaultSoundName;
NSLog(#"Local notification should display");
[[UIApplication sharedApplication] presentLocalNotificationNow:notify];
}
}
and in the viewDid load i'm using something like this
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
CLLocation *userLocation = [locationManager location];
so what is the wrong with it

You need to modify your AppName-Info.plist file by adding a key Required background modes with an item with value App registers for location updates. Another thing I think you should do as you connect online and this may not happen very fast, so the operation that you connect online, post the location and wait for response should start in another thread and meanwhile if you have received another location from CLLocationManager and your previous request has not finished yet to skip posting the new location...

I wonder if the Location Manager is getting released somewhere and therefore not sending any more updates.
Have you tried setting the location manager to a retained property in your view controller?
#property (nonatomic, strong) CLLocationManager *locationManager

Related

Xcode GPS location manager access message

How can I do the following please?
I have a button in my iPhone app that the user clicks to start GPS navigation. All I do when the button is clicked is get their location, and pass it to Google maps to do the rest.
However, as soon as I land on the screen where the button is, the application ask me the standard "This app would like to use your current location". But I dont want this to be asked as soon as I land on the screen. Instead, it should be asked when the button is clicked.
Here is how I handle the scenario in my views .m file:
- (void)viewDidLoad
{
self.locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
And then when the button is clicked. Also tried to put the code from viewDidLoad here as can be seen from the commented out section. This works in that I dont get asked the question when the view loads, but then the GPS does not work once button is clicked. I get an error message on the app screen saying "The app was unable to establish a route to the nearest road". And the "This app would like to access your current location" only flashes up on the screen briefly.
- (IBAction)gpsNavigation:(id)sender
{
/*
self.locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
*/
NSString *destAddress = #"52.269444, -9.708674";
NSString *url = [NSString stringWithFormat: #"http://maps.apple.com/maps?saddr=%f%f&daddr=%#",
locationManager.location.coordinate.latitude,
locationManager.location.coordinate.longitude,
[destAddress stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}
Please use commented code in gpsNavigation: method.
Your problem is that you get locationManager.location as soon as you call [locationManager startUpdatingLocation].
So your code can be as following.
- (IBAction)gpsNavigation:(id)sender
{
self.locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSString *destAddress = #"52.269444, -9.708674";
NSString *url = [NSString stringWithFormat: #"http://maps.apple.com/maps?saddr=%f%f&daddr=%#",
locationManager.location.coordinate.latitude,
locationManager.location.coordinate.longitude,
[destAddress stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
[locationManager stopUpdatingLocation];
}
As soon as you call [locationManager startUpdatingLocation] your app request locations and will ask the user for permission. So delay this call untill you need it (button pressed)

Posting current location to rails from iPhone

I am building a rails-backed iphone app that uses AFNetworking to create posts at specific locations. So the post model has lat/lng parameters that should be filled in with the client's current location.
At this point, the posts can be made, but the lat/lng comes up as null.
In my (save:) method I pass a conditional to see if a location was found- this is what is failing i.e. "No Location" is logged.
- (void)save:(id)sender {
[self getLocation];
NSArray *locations;
CLLocation *location = [locations objectAtIndex:0];
Post *post = [[Post alloc] init];
post.content = self.contentTextView.text;
post.photoData = UIImagePNGRepresentation(self.imageView.image);
[self.view endEditing:YES];
ProgressView *progressView = [ProgressView presentInWindow:self.view.window];
if (location) {
[post savePostAtLocation:location withBlock:^(CGFloat progress) {
[progressView setProgress:progress];
} completion:^(BOOL success, NSError *error) {
[progressView dismiss];
if (success) {
[self.navigationController popViewControllerAnimated:YES];
} else {
NSLog(#"ERROR: %#", error);
}
}];
} else {
NSLog(#"No Location");
}
}
I have also attempted to implement a locationManager like so
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
[self getLocation];
}
-(CLLocation *) getLocation{
CLLocationManager * locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
self.locationManager.distanceFilter = 80.0f;
[locationManager startUpdatingLocation];
CLLocation * location = [locationManager location];
return location;
}
I think ideally I would implement the savePostAtlocation in the CLLocationManagerDelegate where I could pass in the locations array like this:
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations objectAtIndex:0 /* firstObject */];
if (location) {
[Post createPostAtLocation:location...
But I want to have the post created onSave so I am trying to identify the location but running into some problems..
How do I properly get the current location and pass it into the dictionary?
Any advice on this would be greatly appreciated. Thanks!
Looking at your code, I think you have a slight misunderstanding about how CLLocationManager is designed to work. It looks like you are trying to call [self getLocation] from inside locationManager:didUpdateLocations. This is not correct. Try something like this, inside your save method that is called when you press your button (I would remove the code that's currently in there while testing):
CLLocationManager * locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
self.locationManager.distanceFilter = 80.0f;
[locationManager startUpdatingLocation];
Then it will start generating location data. When that happens, the phone will automatically call locationManager:didUpdateLocations very rapidly. Then, in locationManager:didUpdateLocations you could use:
CLLocation * location = [manager location];
NSLog(#"%#", location);
To see your location data in the console.
What I have written here should get the phone generating location data for you. What you say about createPostAtLocation: in locationManager:didUpdateLocations is probably the correct way to go. When you get the location data, call [manager stopUpdatingLocation] to make the phone stop, then post the location data you got back to your server.

iOS - if user allow using his current location or not

in my app in map view i want to show the nearest 10 stores for the user's current location
but first i have to take current location first then i can show the stores according to user's location
in first start of the app the app ask user if he allow to get current location or not so i must do something like
if user allow
list stores on map
else
go back to main page
now i am using the code below:
mtMap.showsUserLocation=YES;
mymanager=[[CLLocationManager alloc] init];
mymanager.delegate=self;
CLLocation *location = [mymanager location];
CLLocationCoordinate2D coordinate2 = [location coordinate];
NSString *latitude1 = [NSString stringWithFormat:#"%f", coordinate2.latitude];
NSString *longitude1 = [NSString stringWithFormat:#"%f", coordinate2.longitude];
NSString *myURL = [[NSString alloc] initWithFormat:#"http://www.xxxx.com/xxxx/aaaaa.ashx?term=%#,%#",latitude1,longitude1];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:myURL]];
NSInputStream *dataStream=[[NSInputStream alloc]initWithData:data];
[dataStream open];
if(dataStream)
{
NSError *err=nil;
id jsonobject=[NSJSONSerialization JSONObjectWithStream:dataStream options:NSJSONReadingAllowFragments error:&err];
if([jsonobject respondsToSelector:#selector(objectForKey:)])
{
//fill arr
}
}
but it doesn't work for the first time when the user opens the app because of late allowing or getting current location late i can't reach where he is so i can't show nearest places
there can be a problem with my logic. i mean may be i shouldn't do all the job in viewDidload
so could anyone help how can i solve this problem?
Instead of doing it under the viewDidLoad section, what about inserting the code in this method?
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
CLLocation *location = newLocation;
...
That would make the code run once the user's location was updated.
You could also add an if statement inside the method to check if it is the first time the code has been run and if not to return.

Calculating exact distance in iPhone

I am trying to calculate distance from start using Core Location framework, but when i put the Application on an iPhone device, the data is not correct. Distance keeps on fluctuating and showing random data. Kindly help me out. Also, Altitude is showing zero.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
//Altitude
if(startingPoint==nil)
self.startingPoint=newLocation;
NSString *currentAltitude = [[NSString alloc] initWithFormat:#"%g",
newLocation.altitude];
heightMesurement.text=currentAltitude;
[currentAltitude release];
//Distance
if(startingPoint==nil)
self.startingPoint=newLocation;
//if(newLocation.horizontalAccuracy <= 100.0f) {
// [locationManager stopUpdatingLocation];
//}
//test start.......................................................
//startlocation
NSString *sp = [[NSString alloc]
initWithFormat:#"%f",startingPoint];
NSLog(#"\nStarting point=%#",startingPoint);
ssp.text=sp;
//endlocation
NSString *ep = [[NSString alloc]
initWithFormat:#"%f",newLocation];
NSLog(#"\nStarting point=%#",newLocation);
eep.text=ep;
//test end............................................................
CLLocationDistance mydistance=[newLocation distanceFromLocation:startingPoint];
NSString *tripString = [[NSString alloc]
initWithFormat:#"%f",mydistance];
distLabel.text=tripString;
[tripString release];
//test........................
[sp release];
[ep release];
}//Location Manager ends..
//Time interval of 3 sec....
-(void)locationUpdate:(NSTimer*)timer{
if(timer != nil) [timer invalidate];
[self.locationManager startUpdatingLocation];
}
As to why your altitude may be zero, please see this answer to a similar question.
This may just be a problem with your NSLog statements, but both the starting and ending points are printed out with NSLog statements that say
NSLog(#"\nStarting point=%#",
The way you seem to have scheduled a 3-second timer is not really the way iOS wants you to use CLLocationManager. The preferred way is to tell CLLocationManager what your location criterion are, and then just start it updating. You don't actually need to keep telling it to start updating every 3 seconds. You can just do it once, and then if you ever decide you don't need any more updates, then call
[locationManager stopUpdatingLocation];
If the OS has no new location information, it probably doesn't make sense to keep asking. It'll tell you when it has new location information, via locationManager:didUpdateToLocation:fromLocation. So, I would recommend starting the process more like this:
CLLocationManager* locationManager = [[CLLocationManager alloc] init];
if ([locationManager locationServicesEnabled]) {
Reachability* netStatus = [Reachability sharedReachability];
if (([netStatus internetConnectionStatus] != NotReachable) || ([netStatus localWiFiConnectionStatus] != NotReachable)) {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = 100.0; // 100 m, or whatever you want
[locationManager startUpdatingLocation];
} else {
// TODO: error handling
}
}
self.locMgr = locationManager;
[locationManager release];
The location manager will often deliver you multiple results, with increasing accuracy as it hones in on your location. If you're continually restarting it, I'm wondering if that's causing it problems.

Returning a users lat lng as a string iPhone

Is there a way to return the users location as a string from a model?
I have a model thats job is to download same JSON data from a web service. When sending in my request I need to add ?lat=LAT_HERE&lng=LNG_HERE to the end of the string.
I have seen tons of examples using the map or constantly updating a label. But I cant find out how to explicitly return the lat and lng values.
Im only 2 days into iPhone dev so go easy on me :)
You need to leverage Core Location, specifically CLLocationManager. Apple doesn't provide any CL programming guide, so just look at one of the samples like LocateMe to see how to do it.
You need to use CLLocationManager like this:
- (void)viewDidLoad
{
// this creates the CCLocationManager that will find your current location
CLLocationManager *locationManager = [[[CLLocationManager alloc] init] autorelease];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[locationManager startUpdatingLocation];
}
// this delegate is called when the app successfully finds your current location
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// retrieve lat and lng in a string from newLocation.coordinate
NSString *lat = [NSString stringWithFormat:#"%d", newLocation.coordinate.latitude];
NSString *lng = [NSString stringWithFormat:#"%d", newLocation.coordinate.longitude];
}
// this delegate method is called if an error occurs in locating your current location
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"locationManager:%# didFailWithError:%#", manager, error);
}