背景中的iBeacons有时会有延迟

时间:2014-05-04 16:45:25

标签: ios iphone bluetooth ibeacon

我有一个iBeacons应用程序,可以在后台或不运行时为信标范围。我实施UILocalNotifications并且它们工作正常,这意味着当我到达信标范围时我会收到通知。

没有真正的灯塔我创建了一个应用程序(对于另一个设备,让我们说下一个场景的 iPad )就像2个不同的信标,这意味着它可以播放2个不同的信号,相同的UUID但不同的Major/Minor值(称为信标A和B),显然一次一个。我的问题是在这种情况下:

  1. 将我的iPhone(关闭iBeacons应用程序)锁定在屏幕上
  2. 激活我的 iPad 应用,广播信标A
  3. 我的iPhone会向我显示通知
  4. 我从广播信标A停止iPad应用,等待1秒,开始广播信标B
  5. 我的iPhone DOESN' T 做出反应
  6. 我阻止iPad播放
  7. 几分钟后(约2)我的iPhone向我显示了信标B的通知
  8. 现在我不明白的是这种延迟,这是我的iPhone第一次立即做出反应,第二次需要大约2分钟通知我的灯塔。

    如果在信标B通知后,我重新开始广播信标(A或B),我的iPhone会立即做出反应,然后下次总是等待2分钟。

    为什么会这样?我读过一篇文章说它是因为当应用程序处于后台时,蓝牙每2-4分钟唤醒一次,所以我可以获得的信息不会比这次快。但是我在这方面没有多大意义,因为每当我收到第二次通知时,信标的广播(在我的方案中 B )已经停止,这意味着如果蓝牙在那个时刻醒来,没有信标在空中!但是我得到了通知,所以这意味着在我停止广播之前我的iPhone发现了它。

    这是一个可以解决的问题吗?

    使用某些代码进行编辑

    这是我的viewDidLoad

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        // Initialize location manager and set ourselves as the delegate and beacons dictionary
        _beacons = [[NSMutableDictionary alloc] init];
        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
    
        // Create a NSUUID with the same UUID as the broadcasting beacon
        NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"6C1AA496-1653-403D-BD1E-7F630AA6F254"];
    
        // Setup a new region with that UUID and same identifier as the broadcasting beacon
        self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
                                                                 identifier:@"testregion"];
    
        NSLog(@"startMonitoring");
        // Tell location manager to start monitoring for the beacon region
        [self.locationManager startMonitoringForRegion:self.myBeaconRegion];
        [self.locationManager startRangingBeaconsInRegion:self.myBeaconRegion];
    
        _myBeaconRegion.notifyEntryStateOnDisplay = YES;
    
        // Check if beacon monitoring is available for this device
        if (![CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]){
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Monitoring not available" message:nil delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; return;
        }
    
    }
    

    现在每当我拿到一个灯塔我发送通知时,我只是想尝试它是如何工作的,所以我没有实现只发送1个通知的方式,这意味着我得到大约9个通知,每秒1个这是代码在后台我可以运行的活动时间(假设为1秒输入区域,9为信标范围)

    -(void)locationManager:(CLLocationManager*)manager
           didRangeBeacons:(NSArray*)beacons
                  inRegion:(CLBeaconRegion*)region
    {
        if([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground){
            UILocalNotification *notification = [[UILocalNotification alloc] init];
            notification.alertBody = @"Found Beacon";
            notification.soundName = @"Default";
            [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
        }
    }
    

    实际上更具体一点,如果我从多任务处理视图完全关闭我的应用程序,或者只是让它在后台播放,一旦我开始播放信标,我就会得到通知** S **(1秒延迟)。然后停止广播并重新播放延迟变为大约几分钟。

    现在对于一个真实场景,我应该在同一个地方有很多信标,这个延迟可能是一个问题,只要我在距离信标本身已经很远的时候收到通知。

    我的代码有问题吗?我读了这些文章,但我从未发现延迟15分钟。

    davidgyoung建议后的EDIT2

    我修改了我的代码,正如你所说的为信标A和B使用2个不同的区域,延迟总是为空。我还记录了你提供的代码,我发现了这一点。

    1. 广播Region_1
    2. 的信标
    3. 设备向我显示Region_1
    4. 的通知
    5. 停止广播Region_1
    6. 的信标
    7. 日志说我仍然在该地区,只有几分钟后我才能得到日志" OUTSIDE Region_1"刚才我可以重播广播从Region_1获取另一个通知。
    8. 所以我对此感到好奇,我读了文章http://beekn.net/2014/03/apple-ios-7-1-launches-major-ibeacon-improvement/

      作者说,从iOS 7.1开始,退出某个地区的响应能力很快,实际上我正在运行7.1但我也有几分钟的延迟。为什么这个?你在测试中发现了同样的问题吗?

      现在,我读到一个设备可以监听不超过20个区域吗?这意味着如果我有100个信标,我可以设置20个区域并将这100个分成20组,获得不超过20个通知(假设这100个在同一个地方,都在我的设备范围内)?这可能是一个问题,因为它将迫使用户在前台运行应用程序以获取所有信息(假设100个信标中的每一个都具有特定的单位角色),我是对的吗?

3 个答案:

答案 0 :(得分:2)

编辑:这是我在看到代码之前的第一个答案。

我无法根据您的描述解释此行为,但我怀疑设置可能存在问题,即延迟您的本地通知或在发送通知时错误地报告信标区域B的状态。

有两件事可以帮助验证/消除这个可能的原因:

  1. didDetermineState: forRegion:回调中添加NSLog语句,如下所示,然后重复测试报告日志结果。

    // put this in your AppDelegate
    - (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
    {
        if(state == CLRegionStateInside) {
            NSLog(@"locationManager didDetermineState INSIDE for %@", region.identifier);
        }
        else if(state == CLRegionStateOutside) {
            NSLog(@"locationManager didDetermineState OUTSIDE for %@", region.identifier);
        }
        else {
            NSLog(@"locationManager didDetermineState OTHER for %@", region.identifier);
        }
    }
    
  2. 发布设置监控的代码,并在检测时发出通知。

  3. 如果你还没有读过这篇文章,你可能想快速浏览一下我测量背景检测时间的类似测试:

    http://developer.radiusnetworks.com/2013/11/13/ibeacon-monitoring-in-the-background-and-foreground.html

    http://developer.radiusnetworks.com/2014/03/12/ios7-1-background-detection-times.html

答案 1 :(得分:2)

看到代码之后,我认为这里有一些问题:

  1. 该代码仅定义包含BOTH信标A和信标B的单个区域,防止独立区域进入/退出监视回调,并且当从发送信标A切换到信标B时停止电话被唤醒。是至关重要的,因为这意味着如果您从发送信标A切换到信标B,iOS将认为自己仍然在一个区域。这可能会导致手机无法获得将在后台唤醒手机的监控事件。

  2. 测距回调中没有代码可以检查哪个信标可见,因此似乎无法确定哪个信标会导致通知。即使传递给测距回调方法的信标数组为空(即,如果没有检测到信标),通知也会触发。

  3. 测距通常不适用于后台。唯一的例外是在进入/退出某个区域后几秒钟。我怀疑你报告的两分钟延迟是iPhone为iBeacons执行下一次后台扫描所需的时间(此延迟可以是2,4或15分钟,具体取决于手机状态)。在执行下一次下一次扫描之后,检测到区域转换(可能是因为没有正在发送的退出区域通知),并且范围启动5秒,然后发出通知。

  4. 如果没有直接记录我的第一个答案中提到的监控区域回调以及测距回调,并记录检测到的信标的标识符,这一切都非常难以测试和排除故障。确保您了解哪些回调是针对哪些信标而触发的,并且不要一次尝试排除太多问题!

    除了首先对各个回调进行故障排除外,我还建议:

    • 更改代码以使每个信标具有一个区域,以获得最大的背景响应。
    • 将检测到的信标标识符放入通知中,以便您知道信标会导致通知触发。

答案 2 :(得分:0)

DavidGYoung是对的。当感测到信标区域遍历时,iOS7.1将在终止时调用您的应用程序。但是,这是至关重要的,iOS只会在您输入或退出信标区域时调用已终止的应用程序,并且仅当您的应用程序先前已注册该特定信标区域的位置事件时。

在上面的解释中,看起来您只监控一个信标区域(您没有指定主要/次要号码,因此任何具有相同UUID的信标都符合条件)。不幸的是,您创建了两个具有相同UUID的信标发射器。因此,当你启动灯塔时,你会得到一个通知(ENTER),但不得不等待几分钟而另一个(退出)。通常我会在信标停止传输后约30秒看到退出通知。

如果您想再次执行实验,请尝试注册两个不同的信标区域(声明两个带有差异主要/次要编号的区域,或制作两个差异UUID),然后在信标发射器中使用这两个差异值。应该工作。 汤姆