我看到崩溃实例的大量增加,在一些不同的崩溃报告中,它们都以相同的致命异常结束:
[BluetoothDevice classicDevice]: unrecognized selector sent to instance 0x2805a8ba0
它在 iOS 12 中发生了几次,但在 iOS 13 中它就出轨了。还有人看到这个吗?是否与 iOS 13 中蓝牙的新隐私权限有关?我没有其他线索可循,只是试图找到其他看到这一点的人。
导致它的堆栈跟踪在我的应用程序代码中没有任何内容,只有 AppDelegate 的声明行。它是 Foundation、CoreFoundation 和一些名为 BluetoothSettings 的 Apple 框架的混合体。正如你所看到的,我的崩溃日志丢失了很多细节——可能是 dsyms 有问题,不确定......但他们在这里。
Fatal Exception: NSInvalidArgumentException
-[BluetoothDevice classicDevice]: unrecognized selector sent to instance 0x2805a8ba0
0 CoreFoundation 0x191b8d54c (Missing)
1 libobjc.A.dylib 0x1918a80c8 (Missing)
2 CoreFoundation 0x191a8bb60 (Missing)
3 CoreFoundation 0x191b91bd4 (Missing)
4 CoreFoundation 0x191b93ac0 (Missing)
5 BluetoothSettings 0x1bb3ae944 (Missing)
6 Foundation 0x191f56a94 <redacted>
7 CoreFoundation 0x191ae5478 (Missing)
8 CoreFoundation 0x191ae54c8 (Missing)
9 CoreFoundation 0x191ae47c0 …Run Code Online (Sandbox Code Playgroud) 我的应用程序使用BLE(蓝牙4)连接到物理外围设备.我的用户和我一再遇到一个错误,在某些时候,应用程序停止连接到外围设备 - 您可以看到发现BLE外围设备并建立连接的指示,但几秒钟之后,连接被丢弃.
只有在重新启动iDevice后,事情才会恢复正常.
我已经做了很长时间的检查,并彻底研究了这个问题,直到我得出结论,这必定是iOS中的一个错误(用7.1测试,但也可能在8.0上发生).
您可以想象这样的问题对我的用户体验产生的负面影响,因为BLE连接对于产品至关重要.
我将非常感谢您就如何解决问题提出建议和意见.
谢谢!
Apple回应了我的技术支持请求:
底线:
到目前为止,iOS 8并没有发生这种情况,但另一方面,我可以看到有关其他蓝牙问题的帖子,这些问题不一定相关,但谁知道.
完整答案:
我回应你的发现,你和你的客户发现在使用一段时间后,iOS BLE无法保持连接.您表明问题已通过iOS 7.1识别出来.有关iOS BLE的问题已经报道并已通过iOS 8.0修复.为了最好地确定您的问题是否已得到解决,当然最简单的方法是安装iOS 8并查看问题是否可以复制.但是,当您报告可以使用iOS 7.1复制问题时,首先要获取蓝牙服务器配置文件,将其安装到您的deivce,复制问题,然后在出现问题时获取BLE服务器日志.该配置文件将让BLE服务器报告其他日志记录详细信息,这有助于报告服务器遇到的问题.我们可以看看问题是否是之前报道的问题.需要考虑的是,对于所有新的错误报告问题,Core蓝牙工程师要求使用当前发布的iOS版本(即8.0)回退所有问题.对于使用iOS 7.x的客户,将不再有iOS 7更新 - 所有软件修复和错误修复都将在iOS 8中使用.因此,只会调查iOS 8报告的问题.您可以从Apple Developer错误报告网页https://developer.apple.com/bug-reporting/ios/bluetooth/获取BLE服务器配置文件.安装配置文件和捕获日志的说明显示在网页上.如果您使用iOS 7.x捕获日志,则可以将其发送给我进行审核.然而,这将是一个学术练习 - 要知道iOS是否解决了这个问题,或者它是否仍然存在,我们需要看看问题是否发生在iOS 8下.一旦你将设备更新到iOS,需要记住一些事情8,您将无法将其还原到以前的版本.我很高兴看看你的结果.但是,如果问题在iOS 8下仍然存在,最好提交错误报告以获得Core Bluetooth工程师对此事的关注.您可以使用Apple Developer错误报告网页提交错误报告.- http://bugreport.apple.com
objective-c ios core-bluetooth bluetooth-lowenergy ios-bluetooth
我的应用程序作为蓝牙 LE 外围设备运行,我试图在广告中发送几个字节的自定义数据。
func btStartBroadcasting(peripheral: CBPeripheralManager!) {
// create an array of bytes to send
var byteArray = [UInt8]()
byteArray.append(0b11011110); // 'DE'
byteArray.append(0b10101101); // 'AD'
// convert that array into an NSData object
var manufacturerData = NSData(bytes: byteArray,length: byteArray.count)
// define a UIUD for the service
let theUUid = CBUUID(NSUUID: uuid)
// build the bundle of data
let dataToBeAdvertised:[String: AnyObject!] = [
CBAdvertisementDataLocalNameKey : "I wish this worked",
CBAdvertisementDataManufacturerDataKey : manufacturerData,
CBAdvertisementDataServiceUUIDsKey : [theUUid],
]
peripheral.startAdvertising(dataToBeAdvertised)
}
Run Code Online (Sandbox Code Playgroud)
但 CBAdvertisementDataManufacturerDataKey 中的数据集似乎被删除并且没有通过无线电发送出去。我已经阅读了苹果文档和网上能找到的所有关于此问题的小片段。共识似乎是核心蓝牙忽略数据,因为仅支持 …
core-bluetooth bluetooth-lowenergy ios-bluetooth swift cbperipheralmanager
我正在编写一个iOS应用程序,用于与迷你mPlay Drumi MP18B(小型蓝牙扬声器)进行通信。据我所知,showBluetoothAccessoryPickerWithNameFilter仅显示将协议字符串添加到Info.plist的“支持的外部附件协议”键中的设备。因此,我需要将此协议字符串添加到列表中。
在哪里可以找到该设备的协议字符串?互联网上任何地方都有设备支持的协议列表吗?大多数制造商并未在其技术规格中提及此信息。
Apple在文档中引用此协议字符串(或ID):
选择器仅显示在扩展查询响应中包括基于蓝牙的iAP唯一ID的蓝牙设备。
我需要做一个能够判断我当前是否连接到经典蓝牙设备的应用程序(实际上,它将是蓝牙车载设备).
我的第一步是告诉当前连接的经典蓝牙设备是什么.我不能使用CoreBluetooth因为它只适用于LE.我尝试使用外部附件框架.
这是代码(一个按钮启动方法):
- (IBAction)startMethodGetConnected:(id)sender {
NSLog(@"button taped");
// Get the number of accessories connected
NSUInteger NumberOfAccessoriesConnected = [[EAAccessoryManager sharedAccessoryManager].connectedAccessories count];
//Display the number
NSLog(@"number of accessories connected : %d", NumberOfAccessoriesConnected);
}
Run Code Online (Sandbox Code Playgroud)
当iPhone连接到蓝牙键盘和蓝牙耳机时我试过了.在这两种情况下,控制台都会显示该数字为0.
如何显示正确的数字?
我目前正在开发的 iPhone 应用程序需要在外围设备建立本地连接后每秒读取一次 RSSI CBCentralManager,无论是在前台还是后台。这意味着设置CBCentralManagerScanOptionAllowDuplicatesKey为true“调用时”scanForPeripherals(withServices:options:)是不可能的,因为当应用程序在后台运行时它会被忽略,并且它仅通过CBCentralManagerDelegate的centralManager(_:didDiscover:advertisementData:rssi:)方法启用 RSSI 更新,此时外设尚未连接。
受这个答案的启发,我在外围设备中实现了一个特性,该特性具有一个notify属性并每秒更新一次。在我的应用程序中,我使用 的CBPeripheral方法setNotifyValue(_:for:)通过 获取特征更新的通知peripheral(_:didUpdateValueFor:error:)。在此方法中,我peripheral.readRSSI()大约每秒通过 调用并获取 RSSI 更新peripheral(_:didReadRSSI:error:)。
我的代码的简化版本如下所示:
...
peripheral.setNotifyValue(true, for: characteristicUpdatingEverySecond)
...
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
peripheral.readRSSI()
}
func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
print("Peripheral \(peripheral) read RSSI: \(RSSI)")
}
Run Code Online (Sandbox Code Playgroud)
与核心蓝牙状态保存和恢复的正确实现相结合,这似乎工作得很好。尽管这似乎是一个可以接受的解决方案,但我仍然想知道是否有其他解决方案不依赖于外围设备的自我更新特性。
我曾考虑过使用 iBeacon(与蓝牙外设并行),但这对我们来说不是一个好的解决方案,因为它很容易被欺骗,我们在设置连接时依赖某些验证方法来确保外设是正品。
是否有人有使用核心蓝牙在前台和后台应用程序状态下轮询蓝牙外设的 RSSI 的经验?您是否找到了替代/不同/更好的解决方案?
我已经研究了很长时间,没有一种解决方案似乎可行。例如:iOS 10上Force软件键盘中引用的文章
我们的蓝牙条形码扫描仪具有一个按钮,该按钮可以上/下按下软/虚拟键盘,但这绝对不如专注于文本输入时弹出键盘那样方便用户使用。
无论如何,iOS上是否可以同时容纳虚拟/软键盘和蓝牙键盘输入?谢谢!
我们还研究了这种看似有希望的方法,当连接蓝牙输入设备时显示软键盘(iPad), 但它需要导入专用框架,而较新的XCode则不支持这种框架,并且不支持App Store吗?
barcode-scanner ios ios-bluetooth react-native react-native-ios
首先的问题是,在核心角色中使用核心蓝牙将数据发送到蓝牙 LE 设备的最佳方式是什么。需要处理数据,如果它在 UI 线程上运行,则需要足够的时间在 UI 线程上引起问题。用户将在手机应用程序打开的情况下启动该过程,然后继续使用该应用程序或关闭该应用程序并期望数据继续发送到设备。
我发现了 2 种非常糟糕的方法,它们似乎有效
这似乎源于 iOS 线程/调度队列以及 iOS 蓝牙内部结构。
蓝牙 LE iOS 应用程序作为核心角色连接到蓝牙 LE 设备。CBCentralManager 是根据苹果文档初始化的。队列定义为:
用于调度中心角色事件的调度队列。如果值为 nil,则中央管理器使用主队列分派中央角色事件。
正如vladiulianbogdan 对 Swift 的回答所建议的:为蓝牙中央管理器选择队列,我们应该为 CBCentralManager 创建一个串行队列。这似乎是有道理的,有一段时间我一直在遵循这个建议。此外allprog评论斯威夫特CoreBluetooth:在一个单独的线程应该CentralManager运行 表明,主队列将暂停,但其他队列不会,这是我所看到的是相反的。
在为蓝牙使用串行队列时,最好使用与主线程不同的队列。有一个问题:回调:
-(void)peripheralIsReadyToSendWriteWithoutResponse:(CBPeripheral *)peripheral
{
[self sendNextBluetoothLePacket];
}
Run Code Online (Sandbox Code Playgroud)
停止被调用。还有另一种方法可以检查外设是否准备好发送更多数据,CBPeripheral 有一个成员变量 canSendWriteWithoutResponse,如果可以发送则返回 true。此变量也开始重新调整 false 并且永远不会回到 true。
我从Sandeep Bhandari找到了这条评论,它说当应用程序进入后台时,所有队列线程都会停止,除非它们是苹果提供的后台模式之一。Biniou 发现他能够通过在视图控制器而不是应用程序委托中初始化来解决他的核心蓝牙背景问题。这对我来说没有意义。
我的应用程序确实在其 info.plist 中选择了核心蓝牙背景模式,因此它应该是这些背景模式之一。我发现当我的应用程序进入后台时,应用程序确实会继续处理数据。我看到来自每 100 毫秒运行一次的轮询循环的日志消息。
如果我从这些轮询循环中触发蓝牙 LE 写入,我就可以继续发送数据。问题是我无法确定发送数据的安全速率,要么速度很慢,要么数据有时会丢失。
我不确定如何最好地处理这个问题。任何建议,将不胜感激。似乎无论我在后台做什么,我都无法确定发送数据是否安全。
我看到这条评论 …
grand-central-dispatch ios core-bluetooth ios-bluetooth dispatch-queue
我目前正在设计一个简单的室内定位项目来评估蓝牙 5.1 标准的可能性。我想使用的功能是蓝牙 5.1 中引入的 AoA(到达角度)。
根据该标准,AoA 允许通过近似角度并测量定位器/接收器 (rx) 上的 RSSI 来测量发射设备 (tx) 的位置。由于AoA是5.1中新实现的功能,因此我理解rx需要支持5.1蓝牙标准。发射装置怎么样?它需要支持的最低蓝牙版本是多少?我可以使用 4.x BLE 信标(或模拟信标的 Android/iOS 设备)来实现此目的吗?
bluetooth core-bluetooth bluetooth-lowenergy android-bluetooth ios-bluetooth
我试图在后台监听我的蓝牙设备,但似乎什么也没发生。我尝试按照此处的指南并针对 SwiftUI 进行修改。
我启用了bluetooth-central后台模式。
我选择加入状态保护和恢复。
let options = [CBCentralManagerOptionRestoreIdentifierKey : "myCentralManagerIdentifier"]
centralManager = CBCentralManager(delegate: self, queue: nil, options: options)
Run Code Online (Sandbox Code Playgroud)
我添加了恢复委托方法。当我第一次再次运行该应用程序时,会调用此方法。
func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
guard let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] else {
return
}
for peripheral in peripherals {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
启动选项的步骤似乎对我不起作用。字典launchOptions永远nil适合我。
import SwiftUI
import UIKit
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool …Run Code Online (Sandbox Code Playgroud) ios-bluetooth ×10
ios ×8
swift ×3
bluetooth ×1
ios13 ×1
objective-c ×1
react-native ×1
swiftui ×1