Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Geofence CLCircularRegion monitoring. locationManager:didExitRegion does not seem to work as expected

I am currently trying to get my app to monitor particular regions using CoreLocation however I am finding that it does not seem to work as expected, it seems to me that it cannot work with small a small radius set for each location i.e. 10m.

I've also put together a little test app which plots the circle radius on a map so I can visually see what is happening.

The code I am using for monitoring locations is as follows:

self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;

// Set-up a region
CLLocationDegrees latitude = 52.64915;
CLLocationDegrees longitude = -1.1506367;
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(latitude, longitude);

CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:centerCoordinate
                                                                 radius:10 // Metres
                                                             identifier:@"testLocation"];

[self.locationManager startMonitoringForRegion:region];

I have not put up the code here for DidEnter region etc as I know that works when I go over 100m away from the monitored region.

Here is a screen shot of the app when I am well over 10 meters away from the purple location on the map, the did exit region events do not fire, however if I switch my location to London it fires and also when I set my location back to where the blue location is currently it also fires.

Example Region

Does anyone know if there is a limitation with the minimum region radius at all or perhaps I am doing something wrong.

Thanks Aaron

like image 807
MonkeyBlue Avatar asked May 26 '14 08:05

MonkeyBlue


People also ask

How are regions monitored in iOS and macOS?

In iOS, regions are monitored by the system, which wakes up your app as needed when the user crosses a defined region boundary. In macOS, region monitoring works only while the app is running (either in the foreground or background) and the user’s system is awake. The system does not launch Mac apps to deliver region-related notifications.

What is region monitoring and how does it work?

Region monitoring (also known as geofencing) is a way for your app to be alerted when the user enters or exits a geographical region. You might use region monitoring to perform location-related tasks.

How do I monitor regions in cllocationmanager?

You define the regions you want to monitor and register them with the system by calling the startMonitoring (for:) method of your CLLocationManager object. The system monitors your regions until you explicitly ask it to stop or until the device reboots.

How to monitor a circular region in Swift?

The way region monitoring works in Swift requires that first you define a circular region. We can center our region on the coordinates we want to monitor, and specify how big it will be by giving it a radius. A CLCircularRegion also needs an identifier, so that they can be differentiated from other regions on your application. 2.


3 Answers

I don't think region monitoring will work well for such a small radius.

  • The best accuracy with the GPS chip and kCLLocationAccuracyBestForNavigation is often just 10 meters.
  • Apple says (in the Location & Maps PG) that the minimum distance for regions should be assumed to be 200m
  • I've heard that region monitoring is using WiFi to get it's position (which makes sense for power savings). WiFi accuracy is more like 20m-100m. I'm not sure how having another app using background location (i.e. using GPS) would affect this. Probably, the location manager would share information to make the accuracy better.
  • Region monitoring can take 30 seconds to fire once inside a region, and a couple of minutes to fire after leaving a region (to prevent location glitches from triggering it).
  • When region-monitoring was first introduced, they said that it would only work with 100m regions and anything smaller would be bumped up. This probably still happens.
  • There's a deprecated method startMonitoringForRegion:desiredAccuracy: which allowed you to specify the distance past the region border to start generating notifications. Presumably this feature has been rolled into startMonitoringForRegion: but is still there. A 10m region might end up with a 10m buffer.
  • If you want to do this, specify a larger region around where you want to monitor, and when the device wakes up in that region, start background location updates (GPS) and use CLCircularRegion's -containsCoordinate: to trigger when the device is within 10m manually. This method is officially sanctioned by Apple (see WWDC 2013 Session 307).

From the CLCircularRegion docs:

Remember that the location manager does not generate notifications immediately upon crossing a region boundary. Instead, it applies time and distance criteria to ensure that the crossing was intended and should genuinely trigger a notification. So choose a center point and radius that are appropriate and give you enough time to alert the user.

From the Location & Maps PG:

Region events may not happen immediately after a region boundary is crossed. To prevent spurious notifications, iOS doesn’t deliver region notifications until certain threshold conditions are met. Specifically, the user’s location must cross the region boundary, move away from the boundary by a minimum distance, and remain at that minimum distance for at least 20 seconds before the notifications are reported.
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.

There's further inside scoop from this post by Kevin McMahon, who asked the Core Location engineers about region monitoring at a lab at WWDC 2012. This info will have changed in the meantime, but the part about region categories is interesting. Here's an edit:

Fine Region (0 - 150m)
- With the floor of 100m this category's range is effectively 100-150m.
- For regions this size performance is heavily dependent on the location-related hardware
- The amount of time that it takes Core Location to detect and call the appropriate delegate method is roughly 2-3 minutes on average after the region boundary has been crossed.
- Some developers have figured out independently that smaller regions would see quicker callbacks and would cluster smaller regions to cover one large area to improve region crossing notifications.

like image 90
nevan king Avatar answered Oct 18 '22 23:10

nevan king


This seems to be a bug in CLLocationManager. I've done extensive testing using various region radius configurations and locationManager:didExitRegion does not fire in an expected way. This seems to be either a rather nasty bug or region monitoring does not happen at all like the documentation suggests. I have the test harness available to anyone who wants it:

http://www.mediafire.com/download/x863zkttltyalk6/LocationTest.zip

Run it in the simulator and start the test by by selecting Debug -> Location -> Freeway Drive in the iOS simulator menu. The number you see is the distance from the center of the monitored region. The background color will be green while the device is within the monitored region and red when outside the region. The text below the distance are event logs.

enter image description here

After running the app, you should see locationManager:didExitRegion fire at 5319 meters from the monitored region. The route will loop every 37 minutes and you'll see the device exiting the region always at 5319 meters.

I've submitted a radar with Apple (17064346). I'll update this answer once I hear back from them. At least then we'll have some input from the canonical source.

Here's the detailed text sent to Apple:

Using a test app on the iOS simulator as well as on an iPhone 5S the CLLocationManager doesn't seem to fire didExitRegion callbacks in an expected way. Regardless of the radius of the circular region being monitored, the callback won't happen until a threshold of around 5000 meters is hit.

Steps to Reproduce:
1. Run the attached app
2. Start region tracking by selecting Debug -> Location -> Freeway Drive in the iOS simulator
3. Monitor the app. The large # indicates the distance from the center of the watched region.
4. After about 190 seconds and 5300 meters didExitRegion will finally fire.

Ths issue does not seem to be related at all to the size of the region. According to the Apple docs, even small regions are supported:

In iOS 6, regions with a radius between 1 and 400 meters work better on iPhone 4S or later devices. (In iOS 5, regions with a radius between 1 and 150 meters work better on iPhone 4S and later devices.) On these devices, an app can expect to receive the appropriate region entered or region exited notification within 3 to 5 minutes on average, if not sooner.

Although region events don't happen instantaneously, they should happen fairly quickly. From the Apple docs:

Region events may not happen immediately after a region boundary is crossed. To prevent spurious notifications, iOS doesn’t deliver region notifications until certain threshold conditions are met. Specifically, the user’s location must cross the region boundary, move away from the boundary by a minimum distance, and remain at that minimum distance for at least 20 seconds before the notifications are reported.

This is not at all what I am seeing in the test harness. On the simulator the device will always be 5000+ meters away from the region before a locationManager:didExitRegion event occurs.

like image 38
memmons Avatar answered Oct 18 '22 22:10

memmons


I like the answers by both Michael and Nevan. I would like to add more information from my personal experience/opinion in developing Location Based iOS Application with Region Monitoring and also highlight some important points:-

Be realistic on Region Monitoring

Region Monitoring is using Global Positioning System (GPS), Wifi and other technologies to determine if the device is inside or outside the monitored region. Don't forget that our earth is 510 square kilometers and about 30% are land (149 million km2). It is a huge area. Remember the recent MH370 missing case? Our current most advance technology could not even pinpoint an estimated region of that missing plane.

If you want to monitor for a small region with only 10 meter radius. It could possibly work inside a highly dense city with a lot of cell towers and wifi connected areas. But at the same time, the signal might be blocked by high rise towers which might cause the signal loss for a few seconds/minutes which caused the delay in delivering the notification.

So, you really have to consider the above information before deciding how big is the region that you want to monitor. Personally I think 10 meter radius is too small.

Be Realistic on the Number of Monitored Regions

The current Core Location technology can only monitors up to maximum 20 regions on a single app. Make sure that the monitored regions are not too close to each other as well.

I personally have tested 3 regions that are about 100 meters in radius which are about 200 meters aways from each others. Sometimes I can get notifications from all these 3 regions when I am driving through them, but sometimes, I can only get the notification from the First region only. What could be the reason? I could not know. The regions might be too close to each other. Or the cell towers decide that my device does not actually inside the monitored region.

There was one person on StackOverFlow who wants to monitor 1800 points on our Earth. Don't be like him as he is quite unrealistic and probably does not understand the limitation of current Core Location technology. Link: Check if the user location is near of some points

Fine Tune The LocationManager

If your app needs to monitor a small area or needs the location update frequently. Here are the potential properties of your location Manager.

self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;

kCLLocationAccuracyBestForNavigation will consume more battery compare with kCLLocationAccuracyBest. But, it will be more accurate.

I found a glitch in region monitoring in iOS 7 when there are multiple notifications triggered at the same time in different monitored regions. I have found a solution to filter out this glitch. For more info, please visit: Region Monitoring Glitch on iOS 7 - Multiple Notifications at the same time

Don't Be Over Ambitious

You might have used some apps which can monitor a small region and are very accurate and able to notify your the same second you step into the region. And you have the inspiration to develop the exact same app to compete with them. But do you understand what happens behind scene? What additional technologies that they are using? And what partners that they are collaborating with?

I have done some research on that and found out that some of the technologies that they use are not available publicly. Some of those companies are heavily funded and could pay a premium to the telecommunication companies in order to get the best location accuracy for the best user experience. I do not understand the details on how it works. I believe most of the location determination is actually on the server end (back end), not the mobile (front end).

So, the apps that are developed by those companies not only can pinpoint the best accurate location but also does not consume a lot of battery.

NOTE: I just want to share my 2 cents. The above information consists of my experience and personal opinion. It might not be 100% accurate as I am still learning Core Location and Region Monitoring.

like image 17
Ricky Avatar answered Oct 18 '22 23:10

Ricky