背景中的 iBeacons 有时会有延迟

Posted

技术标签:

【中文标题】背景中的 iBeacons 有时会有延迟【英文标题】:iBeacons ranging in background sometimes has delay 【发布时间】:2014-05-04 16:45:24 【问题描述】:

我有一个 iBeacons 应用程序,能够在后台或未运行时测量信标范围。我实现了UILocalNotifications,它们工作正常,这意味着当我到达信标的范围时我会收到通知。

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

    让我的 iPhone(关闭 iBeacons 应用程序)处于锁定屏幕状态 激活我的 iPad 应用,广播信标 A 我的 iPhone 做出反应,向我显示通知 我停止 iPad 应用程序广播信标 A,等待 1 秒,开始广播信标 B 我的 iPhone 没有反应 我停止 iPad 广播 几分钟后(大约 2 分钟)我的 iPhone 向我显示信标 B 的通知

现在我不明白的是这种延迟,第一次我的 iPhone 立即反应,第二次大约需要 2 分钟通知我信标。

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

为什么会这样?我读过一些文章说这是因为蓝牙在应用程序处于后台时每 2-4 分钟唤醒一次,所以我不能比这个时间更快地获取信息。但我认为这没有多大意义,因为每当我收到 second 通知时,信标的广播(在我的场景中为 B)已经 停止 strong>,这意味着如果蓝牙在那一刻醒来,空中就没有信标!但是我收到了通知,所以这意味着我的 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 建议后编辑 2

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

    广播Region_1的信标 设备向我显示Region_1 的通知 停止广播Region_1的信标 日志说我还在该地区,几分钟后我得到日志“OUTSIDE Region_1”,刚才我可以重新播放广播以从Region_1获得另一个通知。

所以我对此很好奇,我阅读了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 个信标中的每一个都具有特定的单元角色),对吗?

【问题讨论】:

如果您跳过第 6 步。第 7 步是否会发生? 是的,几分钟后我还是收到了通知 即使使用 iOS7.1,后台检测也不是即时的,可能需要几分钟。我什至发布了证明! (请参阅我的第一个答案中的链接。)。是的,iOS 将您限制为 20 个监控区域,因此您必须谨慎设置。如果可以,请确定您将在其中传输重叠的信标 ID,并为它们使用单​​独的区域。 (或者只是忍受多个信标被视为一个区域的限制。) 【参考方案1】:

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

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

两件事将有助于验证/消除这种可能的原因:

    在您的 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);
        
    
    

    发布设置监控并发出检测通知的代码。

如果您还没有阅读本文,您可能想快速浏览一下我为测量背景检测时间所做的类似测试:

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

【讨论】:

我编辑了我的问题,添加了一些代码。我也登录了didDetermineState,但看起来不错,这意味着没有关于此的特别报告【参考方案2】:

看到代码后,我认为这里发生了一些问题:

    代码只定义了一个包含信标 A 和信标 B 的区域,防止独立的区域进入/退出监视回调,并在从传输信标 A 切换到信标 B 时阻止手机被唤醒。这个这很关键,因为这意味着如果您从传输信标 A 切换到信标 B,iOS 将认为自己仍在一个区域中。这可以防止手机收到会在后台唤醒手机的监控事件。

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

    测距通常在后台不起作用。唯一的例外是进入/退出区域后的几秒钟。我怀疑您报告的两分钟延迟是您的 iPhone 对 iBeacons 执行下一次后台扫描所需的时间(此延迟可能是 2、4 或 15 分钟,具体取决于手机状态)。在执行下一次扫描后,检测到区域转换(可能是退出区域通知,因为没有任何传输),并且测距启动 5 秒以触发通知。

如果不直接记录我的第一个答案中提到的监控区域回调以及测距回调,并记录检测到的信标的标识符,这一切都很难测试和排除故障。确保您了解这些回调中的哪些是按顺序触发的信标,并且不要尝试一次进行太多故障排除!

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

将代码更改为每个信标有一个区域,以实现最大的后台响应能力。 将检测到的信标标识符放入通知中,以便您知道信标导致通知触发。

【讨论】:

感谢您的回答!我会尝试你所说的,记录更多:D,现在我更好地理解了事情是如何运作的。但你也意味着我应该为我应该到达的每个信标创建一个区域?在我的代码中,我刚刚创建了一个具有单个 UUID 的区域,并且所有信标都广播了相同的 UUID 但不同的主要/次要,现在我应该(在这种情况下)创建 2 个区域,不仅区分 UUID,而且区分主要/未成年人,我说的对吗?在这种情况下,我一次可以监控多少个区域?意思是如果我有 100 个信标,我可以寻找 100 个区域吗?谢谢 在收到您的建议后,我再次编辑了我的第一个问题,如果您能看一下它并说出您的印象,我会很高兴。再次感谢【参考方案3】:

DavidGYoung 是正确的。 iOS7.1 将在感应到信标区域遍历后终止时调用您的应用程序。但是,这很关键,iOS 只会在您进入或退出信标区域时调用已终止的应用程序,并且只有当您的应用程序之前已注册该特定信标区域的位置事件时。

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

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

【讨论】:

以上是关于背景中的 iBeacons 有时会有延迟的主要内容,如果未能解决你的问题,请参考以下文章

您如何检测 iBeacon 发射器何时关闭?安卓

如何检查用户的设备是不是支持和授权 iBeacon 使用以及是不是开启了蓝牙?

检测 iBeacons 的延迟

CBPeripheralManager 延迟停止广告/位置管理器范围停止 iBeacon

iBeacon App 有时只能工作,在 iPhone 5 上传输从不工作

接近 API 的不一致行为 - iOS iBeacon