如何提高区域跨界精度(模拟)(地理围栏)
Posted
技术标签:
【中文标题】如何提高区域跨界精度(模拟)(地理围栏)【英文标题】:How to improve region boundary crossing accuracy (simulation) (geofencing) 【发布时间】:2012-04-06 16:07:42 【问题描述】:我正在组合一个应用程序,当用户离开家时会触发通知。所以我实现了半径为 25 的区域监控。 我遇到的问题是在模拟(iPhone 模拟器 5.0)时,我设置了一个自定义位置(家)来设置区域边界。然后在区域边界之外输入另一个自定义位置,即在街道的尽头。但是该应用程序没有注册该区域的退出。只有当我设置家庭位置和地区,然后更改为 Apple 总部时,它才会注册并发出通知。 该应用程序在后台模式下切换到显着的位置变化。但是在前台或后台时它有同样的问题。 我正在寻找的,比如“提醒”应用程序,是让应用程序在退出/离开区域边界(即走到街道尽头)后很快发出通知。如何让它更准确?
这是我的一些 viewcontroller.m 文件:
- (void)viewDidLoad
[super viewDidLoad];
// Create empty array to add region events to.
updateEvents = [[NSMutableArray alloc] initWithCapacity:0];
// Create location manager with filters set for battery efficiency.
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLLocationAccuracyBest; //could try KLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Start updating location changes.
[locationManager startUpdatingLocation];
- (void)viewDidAppear:(BOOL)animated
// Get all regions being monitored for this application.
NSArray *regions = [[locationManager monitoredRegions] allObjects];
// Iterate through the regions and add annotations to the map for each of them.
for (int i = 0; i < [regions count]; i++)
CLRegion *region = [regions objectAtIndex:i];
RegionAnnotation *annotation = [[RegionAnnotation alloc] initWithCLRegion:region];
[regionsMapView addAnnotation:annotation];
[annotation release];
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
NSLog(@"didFailWithError: %@", error);
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
NSLog(@"didUpdateToLocation %@ from %@", newLocation, oldLocation);
// Work around a bug in MapKit where user location is not initially zoomed to.
if (oldLocation == nil)
// Zoom to the current user location.
MKCoordinateRegion userLocation = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 100.0, 100.0);
[regionsMapView setRegion:userLocation animated:YES];
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
NSString *event = [NSString stringWithFormat:@"didEnterRegion %@ at %@", region.identifier, [NSDate date]];
[self updateWithEvent:event];
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
NSString *event = [NSString stringWithFormat:@"didExitRegion %@ at %@", region.identifier, [NSDate date]];
[self updateWithEvent:event];
//implement local notification:
UIApplication *app = [UIApplication sharedApplication];
UILocalNotification *notification = [[UILocalNotification alloc] init];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
if (notification == nil)
return;
notification.alertBody = [NSString stringWithFormat:@"Did You Lock Your House?"];
notification.alertAction = @"Lock House";
notification.soundName = UILocalNotificationDefaultSoundName;
notification.applicationIconBadgeNumber = 1;
[app presentLocalNotificationNow:notification];
[notification release];
// ends here
//following is an alert for the case of exiting boundary whilst app is in foreground
UIAlertView *alr=[[UIAlertView alloc] initWithTitle:@"Reminder didExitRegion" message:region.identifier delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Ok",nil];
[alr show];
[alr release];
//ends here
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
NSString *event = [NSString stringWithFormat:@"monitoringDidFailForRegion %@: %@", region.identifier, error];
[self updateWithEvent:event];
- (IBAction)addRegion
if ([CLLocationManager regionMonitoringAvailable])
// Create a new region based on the center of the map view.
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(regionsMapView.centerCoordinate.latitude, regionsMapView.centerCoordinate.longitude);
CLRegion *newRegion = [[CLRegion alloc] initCircularRegionWithCenter:coord
radius:25.0
identifier:[NSString stringWithFormat:@"%f, %f", regionsMapView.centerCoordinate.latitude, regionsMapView.centerCoordinate.longitude]];
// Create an annotation to show where the region is located on the map.
RegionAnnotation *myRegionAnnotation = [[RegionAnnotation alloc] initWithCLRegion:newRegion];
myRegionAnnotation.coordinate = newRegion.center;
myRegionAnnotation.radius = newRegion.radius;
[regionsMapView addAnnotation:myRegionAnnotation];
[myRegionAnnotation release];
// Start monitoring the newly created region.
[locationManager startMonitoringForRegion:newRegion desiredAccuracy:kCLLocationAccuracyBest];
[newRegion release];
else
NSLog(@"Region monitoring is not available.");
本作品来源于“Regions”模板。
【问题讨论】:
我在我的 iPhone 上部署了应用程序,设置了 15-25m 之间的区域,然后在该区域外走了 50m,什么也没有。有什么建议吗? 【参考方案1】:众所周知,ios 模拟器不适合使用退出/进入进行地理围栏更新。您可以确认这一点的一种方法是将您的应用程序上的地理围栏设置为您的当前位置。然后,从 iOS 模拟器的调试菜单中,按 location,然后按 Freeway Drive。你的设备现在将模拟在高速公路上行驶,如果你的模拟器和我的一样,它不会注册 didExitRegion 事件。
为什么?区域主要由 Apple 的隐藏算法确定,该算法使用 Wi-Fi、手机信号塔和手机上请求位置的其他应用程序。将模拟器视为不使用 Wi-Fi 或手机信号塔...区域监控几乎是不可能的。
要测试您的其余代码在区域退出后是否正常工作,您可以创建一个按钮或手动触发您的 locationManager:didExitRegion: 方法的东西。我还强烈建议在您的设备上编译该项目,方法是将其插入并将 iPhone 模拟器更改为您的 iOS 设备。然后,您可以拔下设备并从手机上运行您的应用程序进行测试。
【讨论】:
【参考方案2】:这大约是您将获得的最佳准确度。区域匹配仅使用蜂窝塔三角测量,因此在密集区域可能会在 50-100 米处触发,而在稀疏区域可能需要 100 米。
如果您想要更详细的信息,那么您将需要使用直接定位服务。但这会消耗电池,所以选择你的毒药。
【讨论】:
以上是关于如何提高区域跨界精度(模拟)(地理围栏)的主要内容,如果未能解决你的问题,请参考以下文章