iOS上的背景信标测距
我理解监视和测距之间的区别,我也理解iOS的局限性,即信标测距只能在进入和退出区域时发生在前台或后台,如下所述()。但我想知道如何解决一个常见的问题 如果我在百货公司安装了一堆信标,我该如何检测一个人在这些信标的范围内移动?按照目前的工作方式,当用户进入商店(iOS上的背景信标测距,ios,core-location,ibeacon,Ios,Core Location,Ibeacon,我理解监视和测距之间的区别,我也理解iOS的局限性,即信标测距只能在进入和退出区域时发生在前台或后台,如下所述()。但我想知道如何解决一个常见的问题 如果我在百货公司安装了一堆信标,我该如何检测一个人在这些信标的范围内移动?按照目前的工作方式,当用户进入商店(didEnterRegion)时,应用程序将获得一个事件,因为所有信标的集合都是一个大区域。但是没有办法知道用户正在商店的不同区域之间移动,除非信标放置得足够远,用户可以退出并再次进入该区域,这可能是不实际的 我想在后台设置信标范围的原因是
didEnterRegion
)时,应用程序将获得一个事件,因为所有信标的集合都是一个大区域。但是没有办法知道用户正在商店的不同区域之间移动,除非信标放置得足够远,用户可以退出并再次进入该区域,这可能是不实际的
我想在后台设置信标范围的原因是,我可能需要知道用户在商店的特定部分/产品上,以显示该部分的特定优惠/信息(通过通知),而无需用户打开应用程序
在我看来,这似乎是商场和博物馆等的常见场景。。。我想知道其他开发人员是如何解决这个问题的,或者是否有其他方法来实现我想要的
我没有在这里包含代码片段,因为问题不在于代码,它只是一个概念问题。如果需要任何澄清或代码,我也可以添加
谢谢我可能会通过将商店分为多个区域来建模。它们的建模方式将基于您在触发通知时的用例 我会给他们所有相同的UUID,但不同的主要值。然后使用次要值来区分不同的存储。这样,当他们从区域移动时,应用程序将注册一个
dienter
事件
您可以注册大约20个区域,因此我在将信标分组时会非常小心
例如:
- UUID:
专业:754A5D70-C59E-4E39-AA56-ED646903EF5B
→ 入口1
- UUID:
专业:754A5D70-C59E-4E39-AA56-ED646903EF5B
→ 收银机2
- UUID:
专业:754A5D70-C59E-4E39-AA56-ED646903EF5B
→ 服装3
- UUID:
专业:754A5D70-C59E-4E39-AA56-ED646903EF5B
→ 家庭用品4
你需要做的是确保你所有的信标都有相同的UUID。然后,注册一个仅指定该UUID的用于监视的CLBeaconRegion。不要包含主要值或次要值。这将导致在输入与UUID匹配的任何信标时调用
didEnterRegion:
(主要值和次要值为通配符)。但是,这里返回的CLBeaconRegion将只包含UUID,而没有主/辅,就像您注册它的方式一样,因此您不知道究竟触发了哪个信标。要准确确定您的设备所看到的信标,当调用dienterregion:
时,告诉位置管理器使用输入的区域startrangbeaconregion:
。然后,位置管理器将通过didRangeBeacons:
传递一组CLBeacons向您回电话。这些CLBeacon将知道它们的主要值和次要值,通过这些值,您可以准确地确定用户所在存储区的哪个部分(因为您知道带有该主要值/次要值的信标部署在何处)。这一切都可以在应用程序处于后台时完成
这样,您只需注册一个CLBeaconRegion,但仍然可以与任何与您注册的UUID匹配的信标进行交互
我使用这种方法在一个区域成功部署了80多个信标,所有信标都在前台和后台成功发射。您无需用户打开应用程序即可完成此操作。答案中最重要的部分是我的同事@csexton在对该问题的另一个答案中记录的技术 为了解决第二个问题,即转换后只能获得10秒的测距时间,您可以请求额外的时间来保持测距。iOS允许您在后台继续测距长达180秒。这不需要后台模式,也不需要AppStore的特殊许可 下面是如何设置的:
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
if (_inBackground) {
[self extendBackgroundRunningTime];
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self logString: [NSString stringWithFormat:@"applicationDidEnterBackground"]];
[self extendBackgroundRunningTime];
_inBackground = YES;
}
- (void)extendBackgroundRunningTime {
if (_backgroundTask != UIBackgroundTaskInvalid) {
// if we are in here, that means the background task is already running.
// don't restart it.
return;
}
NSLog(@"Attempting to extend background running time");
__block Boolean self_terminate = YES;
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"DummyTask" expirationHandler:^{
NSLog(@"Background task expired by iOS");
if (self_terminate) {
[[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
_backgroundTask = UIBackgroundTaskInvalid;
}
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Background task started");
while (true) {
NSLog(@"background time remaining: %8.2f", [UIApplication sharedApplication].backgroundTimeRemaining);
[NSThread sleepForTimeInterval:1];
}
});
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[self logString: [NSString stringWithFormat:@"applicationDidBecomeActive"]];
_inBackground = NO;
}
让180秒在背景中射程不是万能的,但它解决了许多10秒无法解决的用例
你可以在这里阅读一篇关于这项工作原理的完整文章,以及测试结果:我考虑过了。问题是将信标分成多个区域可能不够精细。在某些情况下,我可能需要显示与特定单个信标相关的报价或信息。据我所知,iOS在所有应用程序中都有20个区域的全球限制,因此这并不实际。我认为你可以解决这个问题,请参阅我的编辑--尝试解决这个问题。感谢您的澄清。另一个问题是,一旦我得到区域条目回调,我只能在10秒左右的时间内对信标进行测距,然后,应用程序返回到后台。因此,如果我们有一个大的服装区,我们将只在区域的边缘范围内,但不能在区域内范围内,以防我需要显示关于特定信标的通知。除非用户打开应用程序。@csexon在这项技术上是绝对正确的。有关延长测距时间的信息,请参阅我提供的答案。这正是我现在所做的。但这不允许你在进去后继续寻找信标