为何离beacon很近的距离,也能检测到didExit方法?

我在测试的时候,将beacon距离设置为30m,在范围内可以感知到,能进入didEnter,但手机放着不动,离着beacon很近的距离,也能检测到didExit,退出事件,这是为啥?也太不准了吧?

请问beacon的广播频率设置的是?iOS的beacon刷新周期是1秒

广播频率是400多毫秒,为什么放着不动也能检测到退出呢?离beacon很近

请问手机是什么型号,什么系统?有时候广播的时候和手机的刷新时间没有对上,就会出现这种情况,可以在app里自己做一下处理,过滤一下

5c,ios9的系统,貌似ios8的也这样,这个如何进行过滤呢?有什么好的办法?感谢!!!

现在有种情况,就是通知太频繁,检测到进入之后通知了,没过一会就退出了,然后这样重复的提示,这有什么好的办法进行限制么?好的体验是只提示一次,离开之后再提示一次,我使用的是本地通知

过滤的逻辑很简单,你把上次enter和exit的时间记录下来,如果时间太短,就不认为是exit。通知太频繁也是一样的处理逻辑

恩,但有种不知道怎么处理,就是enter和exit是好多beacon,每次enter记录的都是当前的beacon,之前beacon的记录就会被覆盖,这个怎么记录每个beacon enter和exit时间呢?如何与每个beacon进行绑定?

beacon可以通过UUID/major/minor区分吧?难道你使用的时候,这些参数都相同?

不相同,目前办公室有好几十个beacon,扫描的时候都能扫描到,然后监测的时候,我是用一个for循环进行监测UUID/major/minor的,系统是不是会比如循环到20个的时候,后面的就不监测了?还是自动抽取几十个beacon中的20个?我说的enter与exit不好区分的意思是,进入enter与exit的时间是我们手动记录的吧,并不是beacon的属性,当后面有beacon进入或退出的时候,之前记录的时间不就被这个覆盖了么?然后比如第一个beacon要退出了,但是这个beacon的进入时间已经被其他进入的beacon覆盖了,已经不是第一个beacon进入的时间了,这个貌似很不好处理啊!

每个beacon的uuid/major/minor不同,那么按照这个记录enter和exit时间即可

{
 "uuid-major-minor1" : {"enter-time": 123, "exit-time": 456},
 "uuid-major-minor2" : {"enter-time": 123, "exit-time": 456},
 "uuid-major-minor3" : {"enter-time": 123, "exit-time": 456},
}

恩好,我搞下试试,目前办公室有好几十个beacon,扫描的时候都能扫描到,然后监测的时候,我是用一个for循环进行监测UUID/major/minor的,系统是不是会比如循环到20个的时候,后面的就不监测了?还是自动抽取几十个beacon中的20个?

你可以贴一下代码片段吗?我们可以给你一点具体的建议

好的,多谢!

  • (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
    {
    NSLog(@"_beacon.count = %lu",(unsigned long)beacons.count);
    // for (CLBeacon *beacon in beacons) {
    // NSLog(@“major= %d,minor = %d”,[beacon.major unsignedShortValue],[beacon.minor unsignedShortValue]);
    // }
    for (CLBeacon *beacon in beacons) {
    CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:beacon.proximityUUID major:[beacon.major unsignedShortValue] minor:[beacon.minor unsignedShortValue] identifier:[CWCommonTools ret32bitString]];
    [_locationManager startMonitoringForRegion:region];
    }

}

  • (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
    {
    CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region;
    NSString *string = [NSString stringWithFormat:@"%d|%d",[beaconRegion.major unsignedShortValue],[beaconRegion.minor unsignedShortValue]];
    if (![_beacons containsObject:string]) {
    [_beacons addObject:string];
    _type = 1;
    [NSThread detachNewThreadSelector:@selector(requestBeaconEvent:) toTarget:self withObject:beaconRegion];
    }

}

  • (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
    {
    CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region;
    NSString *string = [NSString stringWithFormat:@"%d|%d",[beaconRegion.major unsignedShortValue],[beaconRegion.minor unsignedShortValue]];
    if ([_beacons containsObject:string]) {
    [_beacons removeObject:string];
    _type = 2;
    [NSThread detachNewThreadSelector:@selector(requestBeaconEvent:) toTarget:self withObject:beaconRegion];
    }

}

将扫描到的用for循环进行minor,在进入和退出中,进行了下简单的过滤,用数组保存已经进入的beacon,如何有相同major和minor的话,就不通知了,但这样太简单粗暴了,有种刷屏的感觉,请见一下处理逻辑,谢谢!

假如从家到公司,进入公司之后,手机就放在那了,一天不动,那间隔时间很长,也不能认为是exit吧,貌似光用时间来判断也不行,如果加上地理位置呢

startMonitoringForRegion 最好别写到 didRangeBeacons 里面,range到的beacon可能是成百上千。
你需要监听哪些,就Monitoring哪些。如果Monitoring是数目实在太多,
建议你用didRangeBeacons得到的beacon,根据beacon的距离distance 去自定义进入 进出。
一般我们是monitor Region只传uuid,然后在enter里面去range该region,在回调didRangeBeacons里面去处理距离。

恩好的,beacon的距离就是accuracy属性吧?那退出的时候呢?也调用range该region么?因为在enter和exit中获取不到具体的beacon,只能在didRangeBeacons中获取,我按照这个逻辑处理一下,比如处理完了之后请求服务器,就在didRangeBeacons中进行请求的么?

1 Like

1.beacon的距离就是accuracy。
2.退出不用range,都exit了,range肯定得不到,你自己设定个距离,然后range时候得到的accuracy和你自己的距离对比呀,如果大于该距离,表示离开,如果在该距离内表示进入。可以更好的控制触发的条件。至于啥时候请求服务器就看具体需要了。

  • (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
    {
    for (CLBeacon *beacon in beacons) {

      NSLog(@"%.2fm",beacon.accuracy);
      if (beacon.accuracy < 30 && beacon.accuracy > 0) {
          
          _type = 1;
          [NSThread detachNewThreadSelector:@selector(requestBeaconEvent:) toTarget:self withObject:beacon];
    
      }
      if (beacon.accuracy < 0) {
          _type = 2;
          [NSThread detachNewThreadSelector:@selector(requestBeaconEvent:) toTarget:self withObject:beacon];
      }
    

    }

}
我在didRangeBeacon中这样写的
accuracy大于0表示在这个区域内,好像当设备exit时,获取到的accuracy=-1,这就表示离开了吧?我现在这样写,通知的总是同一个beacon的进出,其他的貌似出不来,请指教下,方法中怎样写更好控制些呢?谢谢!

你可以打印beacons看到当前有多少个beacon,并且可以实时看到每个beacon的距离,有助于你分析。而且可以把每个beacon对应一个时间间隔,控制推送的时间。