iOS - Geofencing with WiFi turned off - iphone

I have code that creates a geofence on my iPhone that will trigger some code to be executed when didExitRegion gets called. However, I have found that when I have WiFi switched off that didExitRegion never gets triggered.
Is WiFi required for monitoring region changes on iOS?
My desired accuracy is set to kCLLocationAccuracyHundredMeters.
I am testing on iOS 6.1 and iPhone 4.
Here is my code for setting up location monitoring:
- (id)init {
self = [super init];
if (self) {
CLLocationManager *manager = [[CLLocationManager alloc] init];
manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
manager.distanceFilter = RADIUS/10.0;
manager.headingFilter = kCLHeadingFilterNone;
self.locationManager = manager;
self.authorizationStatus = [CLLocationManager authorizationStatus];
}
return self;
}
Thanks

iOS devices use three methods to discover user location. From (usually) most accurate to least accurate they are:
GPS hardware
By identifying nearby wifi networks
Cell Tower Triangulation
If your app doesn't use GPS or is not running (ie. has previously been terminated), the device will attempt to use methods 2 and 3 above to locate the user. So the device's ability to locate the user (when the GPS hardware is not in use or there is a weak GPS signal) depends on the availability of wifi networks and cell towers. The more wifi networks and cell towers, the better the location accuracy. Therefore, when a user enters or exits a monitored region (ie. crosses a "geofence"), it is impossible to predict exactly when the user will receive the notification if at all. (Of course, if the region in question is always the same, the device will more or less locate the user with the same degree of accuracy on each occasion).
Here's the relevant documentation from the Location Awareness Programming Guide:
The specific threshold distances are determined by the hardware and the location technologies that are currently available. For example, if Wi-Fi is disabled, region monitoring is significantly less accurate. However, for testing purposes, you can assume that the minimum distance is approximately 200 meters.
So, wifi is not required for region monitoring to work, but with it enabled, your device will have a better chance in determining whether or not the user has crossed a region's geofence.

If you turn off WiFi, your location accuracy lowers. If you don't have GPS signal(inside some buildings), you will not get any location updates. Have you tried this when you are outside, or if you used the location simulator to test?
Also, WiFI is not required for geofence function if you have GPS(iPhones or iPad with sims).

Weird weird stuff can happen without wifi using core location. To help in your case I would get rid of the distance filter, that can mess with things and it is not very helpful. I would probably only use kCLLocationAccuracyBest for anything where I need the accuracy required to set up a geofence. Using other accuracies and filters for me would sometimes through the gps meter off by 1000 meters and take a minute or two to correct itself. If this is too much battery then set up a system where it turns off and on based on how far away it is from the fence.

Related

iOS - accelerometer in background shows location services popup, but we don't need location services

Our app would like to access accelerometer data in background. A possible way to achieve is to use Core Motion for accelerometer readings -
with
CLLocationManager* locationManager;
CMMotionManager* motionManager;
...
[motionManager startAccelerometerUpdatesToQueue: ... withHandler: ...]
which works fine on the foreground, but the only way I've found to receive the updates in background is to set the app to allow using Location in background, and call
[locationManager startUpdatingLocation]
in -applicationWillResignActive:
The problem is, when I call startUpdatingLocation that a window pops up with text Turn On Location Services to Allow "app" to Determine Your Location.
But of course, I receive accelerometer readings regardless of whether Location Services are enabled, but the popup is annoying and will probably confuse users.
Is getting accelerometer data in the background somewhat tied to attempting to receive location updates?
You can use startAccelerometerUpdatesToQueue in background, the only thing you need to meet — use any background mode to make you app running in the background (location updates (your case), playback, VoIP or BT4 central).

Get every location update from GPS

I am new to iOS.
I am making one app using GPS location update.
I am fetching current location and update location to server.
I want to get every change in meter and update it to server.
Here is the code i am using:
locationManager = [[CLLocationManager alloc] init] ;
locationManager.delegate = self; // send loc updates to myself
locationManager.distanceFilter = 1.0f; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
But the location is not updating after every meter. It updates but not regularly.
Thanks for Help!
It doesn't work like that. AGPS, which is what iPhone uses, has limited accuracy which depends on many factors. It uses GPS, Wi-Fi and Cell Towers triangulation and at any given moment it can use any combination of these. So, when GPS signal is lost and there is no Wi-Fi hotspots around you could be getting location based on Cell Towers location which is very inaccurate (a few hundred meters). It could be worse than that, you could be getting cached location which is nowhere near your current location. And even when you have GPS signal you can't expect to get 1 meter accurate location everywhere you go. GPS accuracy itself depends on many factors.
Use kCLLocationAccuracyBestForNavigation always. There is no real battery usage difference between that and kCLLocationAccuracyBest, they both use the GPS at top speed. The main difference is in the post-processing that Apple does.So you can try the kCLLocationAccuracyBestForNavigation.

How accurate is iPhone GPS (in radius)?

i want to know how accurate our gps on iphone 4/4S because my new project is using gps for tracking something. i mean accurate is about meter. I have search other question like mine but i don't have the answer. Is it possible to track radius just say for 1 meter? how long accuracy that the gps iphone 4/4s have (in minimum)? 10 meter? how about 1 meter? can it track for 1 meter radius? oh again, my next project for my company is outdoor application. I know i can test it by myself but it more quick to get the answer from here. thank you.
The simple answer is: No, it's not accurate down to 1m.
In some cases though it is, but don't count on it. In an urban landscape I've sometimes been displaced by about 20m. but it seems like all devices gets the same displacement, so you can detect if they are close or not.
Edit: I should say that I have worked a lot with the location services on the iphone, so I'm absolutely sure of this answer.
I have tested the 4S using the standard GPS test of positioning the unit over a known point (survey point - 1 cm accuracy) for a specific period of time. This 30 minute continuous test was done in Tucson, AZ (good GPS territory) versus New York City (tall buildings and further north) using GPS Photo-Link. So we typically look for 10 meter accuracy which means that 92% to 97% of the points are within 10 meters NSEW of the known point. The iPhone failed the first test so I tossed the results and stopped testing it. I am waiting for WAAS on phones to see phones improve GPS but I think most phone companies are going to throw their money into making the camera better.
Well, may be you can set the accuracy you want like
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
locationManager.distanceFilter = 10;
[locationManager startUpdatingLocation];
For more information please refer apple documentation
Hope this help you. good luck.

CLLocationManager Update frequency

I have configured locationManager as follows.
_locationManager = [[CLLocationManager alloc] init];
[_locationManager setDelegate:self];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
When the application runs, I get some updates from the delegate methods.
And when I do not change the location, and the mobile is stationary for about 2 hrs, I receive about 10-12 updates in the first 10 mins, and then stop receiving updates.
What I understand is that desiredAccuracy is how long the device will keep trying more and more accurate methods to get the current location. So in my case, it takes about 10 mins to get the desired accuracy.
I want to confirm if this is true. Also is there a way where I can get regular location updates even if the device is not moving?
Why would you expect the location to be updated if it hasn't changed?
If you want to periodically refresh your results, use an NSTimer you've created yourself.
When the device gets a location with a margin of error < desiredAccuracy, it will stop asking for more accurate results. If the device moves then it will start asking again, until it once again gets the location to the desired accuracy.
If you're specifying 10m for the accuracy then you're almost certainly going to be relying on GPS - cell towers and wifi aren't that accurate (usually).
To determine if the device has moved, it uses distance filter - by setting this to none you are asking it to be accurate to the nearest 10m all the time - this is probably going to be quite draining on the battery ;)

Compass True Heading in iPhone/iPad

I having some problem on the iPhone/iPad compass development.
The trueHeading taken from the CLHeading alway give me the '-1' value, I'm stuck here. Here is my code:
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;
self.locationManager.headingFilter = 0.5; //1 degrees
[self.locationManager startUpdatingHeading];
I also found out something, that is when I on the map app or the compass app which has use the location stuff, the trueHeading value suddenly read correct. I wonder what is the cause, any idea? It happen on both iPhone4 and on the iPad.
It also happen whenever I off the Location Services in settings and re-enable it, it will become unable to read the correct trueHeading value, i wonder because the location services cannot be enable by the app I creating?
anyway, thank in advance
---My Solution---
see below.
to avoid the heading keep returning -1.000000, not JUST run startUpdatingHeading but run startUpdatingLocation together, this helps.
Try using this...
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyBestForNavigation;
// Start heading updates.
if (locationManager.headingAvailable && locationManager.locationServicesEnabled)
{
locationManager.headingFilter = kCLHeadingFilterNone;
[locationManager startUpdatingHeading];
}
and after doing this CLLocationManager delegate methods calls
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
// Use the true heading if it is valid.
[lblAccuracy setText:[NSString stringWithFormat:#"%.1fmi",newHeading.headingAccuracy]];
}
But this coding works on device not in simulator...
Happy coding..
---My Solution---
What I did was, add in the [self.locationManager startUpdatingLocation] to before or after the [self.locationManager startUpdatingHeading]; (when Location Services is off & re-enable from the Settings). I'm not sure this is a good solution, but this is what I did to make it work, if you have any better solution please share.
I had some trouble with the location manager myself and found out that for me it helped to unplug the iPhone from the computer when testing. Somehow the calibration alert only popped up after unplugging the iPhone.
I had this same problem. I moved startUpdatingHeading into a button action, then moved it back to where the CLLocationManager is allocated -- where it had been working fine -- and it started returning only -1.
I rebooted my iPad and it started working again. Hopefully it stays that way.
Edit: Nope, it didn't stay that way. I had to use startUpdatingLocation too. Won't this wear down the battery though? I set desiredAccuracy to kCLLocationAccuracyThreeKilometers, because I am not using location data anyway.
A TRUE reading requires knowing the magnetic variation for the place where you are using the compass. From the previous discussion, it appears to be that the function that corrects the true direction from magnetic direction needs your location for obtaining the variation value. If you don't like to use the location GPS information in your code, I suggest reading the magnetic reading and correct the value by yourself. You need to obtain the variation for the desired location first then apply the following formula: T=M ± V, where T is the true direction, M is the compass magnetic reading and V is the variation. Use "+" for East and "-" for West. I found the allowing web site provide the variation(magnetic declination) for any needed location: http://www.geomag.nrcan.gc.ca/calc/mdcal-eng.php.
When location services are off, the didUpdateHeading delegate method returns only the magnetic heading. You can use it according to your needs. According to Apple docs..
To begin the delivery of heading-related events, assign a delegate to
the location manager object and call its startUpdatingHeading method.
If location updates are also enabled, the location manager returns
both the true heading and magnetic heading values. If location updates
are not enabled, the location manager returns only the magnetic
heading value.
Working on this problem now. I can get updates from Core Motion when I use SpriteKit. It's about being able to call a function continuously like once a frame (1/60th of a second) or every few frames. Without using SpriteKit, the documentation says to invoke the updates within a closure, which I assume will be on their own thread and up to you to release.
There's an algorithm for converting the magnetometer readings to actual degrees relative to true north. Picture a graph that looks like the time domain function of alternating current and you'll see that interpolating the data is a simple matter of applying Maxwell's equations. Here's an example on honeywell