蓝牙 LE iOS 无法在后台扫描

Posted

技术标签:

【中文标题】蓝牙 LE iOS 无法在后台扫描【英文标题】:Bluetooth LE iOS unable to scan in background 【发布时间】:2018-02-13 11:26:27 【问题描述】:

设置、情况的独特性和前台成功扫描

我正在尝试从CBPeripheral 设备获取蓝牙读数。这个特定设备的有趣之处在于它发出的 UUID 直接将信息嵌入其中。 (这看起来很奇怪,但我对 BLE 的了解还不够,无法知道这是否是典型的。最终没有发生实际连接 - 只发送了广告。)

在前台,我能够识别出哪些读数是我的,因为[peripheral name] 保持不变。因此,我可以通过在didDiscoverPeripheral 内部进行以下检查来获取相关的读数:

if ([[peripheral name] isEqualToString:@"UNIQUE_IDENTIFIER"]) 
    NSLog(@"*** Got a reading ***");

这在前台运行良好 - 我正在运行

[self.centralManager scanForPeripheralsWithServices:nil options:nil];

在一个循环中(细节似乎无关紧要),代码能够打印出我希望它打印的所有读数。

后台扫描问题并尝试解决

我的应用的 Info.plist 包含以下条目:

我还检查了(我认为是)XCode 的 Capabilities 选项卡中的相应字段:

这些东西都没有被证明是有用的。 didDiscoverPeripheral 被完美调用,直到我关闭我的应用程序,此时它立即停止。

我在互联网上读到的另一件事是,当使用nil 调用scanForPeripheralsWithServices 时,仍然不会发生后台处理,但是如果改为传递一个非空的服务数组,那么它应该会成功。 我不确定这是否正确。问题是,我只能找到调用scanForPeripheralsWithServices 的示例,其中服务由UUIDs 标识,例如

NSArray *services = @[[CBUUID UUIDWithString: @"2456f1b9-26e2-8f83-e744-f34f01e9d701"]];
[self.centralManager scanForPeripheralsWithServices:services options:nil];

但不是他们的name 属性。

问题

所以我想我的问题是:提供name 过滤器数组(而不是UUIDs)有助于应用程序在后台运行,如果是,我将如何用代码写?如果没有,我错过了什么以使我的应用程序仍然只能在前台运行?

编辑:当我认为我的意思是说“名称”时,我以前使用过术语“标识符”,所以我回去更改了这些。从文档中,这是我想在后台扫描的名称值https://developer.apple.com/documentation/corebluetooth/cbperipheral/1519029-name?language=objc

【问题讨论】:

您的应用不会在后台扫描新设备,但(简要地)可以保持连接到已连接的设备并监控它们(来源:Apple) @holex 该句的其余部分表示这与“尚未声明支持任一核心蓝牙后台执行模式的应用程序”有关。但是我认为我已经在我的应用程序中正确地做到了。 它还显示 "bluetooth-central – 该应用使用 CoreBluetooth 框架在后台与蓝牙配件通信。",我在这里强调了关键字:“交流”(=interact)而不是“扫描”。 @holex 后台模式部分的另一个引用:“当您的应用程序在后台时,您仍然可以发现并连接到外围设备,......”所以看起来好像您也可以发现设备在后台运行时。 实际上,同一段的其余部分清楚地表明,尽管在某些方面可能表现不同,但在后台扫描是一个真正的功能。 (@holex) 【参考方案1】:

为了在后台扫描新设备,您必须指定您感兴趣的服务的 UUID。文档对此非常清楚。

设备的identifier 是由 ios 本地确定的值,而不是设备本身,并且会因连接到同一外围设备的不同 iOS 设备而异。如果您知道之前发现的设备的标识符,则可以将标识符用于connect 到设备,但您无法扫描标识符。

外围设备可以在其服务广告中包含数据,这可能就是您的外围设备正在做的事情。如果是这样,那么您将无法在后台获取读数,因为当您的应用程序在后台时不会传递重复的设备发现事件。

只要您知道它正在宣传的服务,您就可以在后台发现并连接到新设备,但任何后续数据传输都需要设备就更改的特性发出通知。它不能使用广告框架的制造商数据部分。

【讨论】:

谢谢,这很有见地。我一直在寻找使用正则表达式或通配符 UUID 进行扫描的方法,但到目前为止还没有找到任何东西。 实际上 Paulw11,我想我最初在问题中说错了(现在编辑)。我实际上是在尝试按名称属性进行过滤(编辑中提供的链接)。你知道这是否可能吗?还没有见过这种性质的东西。 不,你不能。您只能搜索正在宣传的服务。要按名称过滤,您需要让代码检查新发现设备的名称,如果不指定要扫描的服务,您将无法在后台执行此操作。 谢谢 - 我在这里做更多的研究,如果它证实了这一切,我会回来选择这个答案。谢谢!

以上是关于蓝牙 LE iOS 无法在后台扫描的主要内容,如果未能解决你的问题,请参考以下文章

iOS蓝牙后台模式

锁定 iOS 设备扫描 BTLE 设备

在应用程序处于后台时使用蓝牙 LE

Xamarin IOS 蓝牙 LE 广告

iOS 蓝牙 LE 无法以编程方式获取通知,但可以在其他应用程序中

蓝牙 LE 不扫描设备