iOS上的背景信标测距

iOS上的背景信标测距,ios,core-location,ibeacon,Ios,Core Location,Ibeacon,我理解监视和测距之间的区别,我也理解iOS的局限性,即信标测距只能在进入和退出区域时发生在前台或后台,如下所述()。但我想知道如何解决一个常见的问题 如果我在百货公司安装了一堆信标,我该如何检测一个人在这些信标的范围内移动?按照目前的工作方式,当用户进入商店(didEnterRegion)时,应用程序将获得一个事件,因为所有信标的集合都是一个大区域。但是没有办法知道用户正在商店的不同区域之间移动,除非信标放置得足够远,用户可以退出并再次进入该区域,这可能是不实际的 我想在后台设置信标范围的原因是

我理解监视和测距之间的区别,我也理解iOS的局限性,即信标测距只能在进入和退出区域时发生在前台或后台,如下所述()。但我想知道如何解决一个常见的问题

如果我在百货公司安装了一堆信标,我该如何检测一个人在这些信标的范围内移动?按照目前的工作方式,当用户进入商店(
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
    → 家庭用品
然后,当应用程序的用户在商店中移动时,您可以在跨越区域边界时触发操作

这样,您可以:

  • 获取enter和exit回调函数
  • 开始测量以找出次要值(可能是每个存储或每个信标的唯一值)
  • 发送本地通知

  • 你需要做的是确保你所有的信标都有相同的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在这项技术上是绝对正确的。有关延长测距时间的信息,请参阅我提供的答案。这正是我现在所做的。但这不允许你在进去后继续寻找信标