iOS配对HID设备系统侧重连:如何让应用接收通知?
实现iOS设置连接HID设备时应用收到通知的方案
当然有办法实现这个需求!因为当HID设备通过系统设置直接连接到iOS系统时,你的应用并不会自动收到CBCentralManager的代理回调(这些回调只针对应用主动发起的连接/断开操作),但我们可以通过主动检测和状态监听的方式来捕捉这个变化。下面是几个可行的方案:
1. 监听应用前台状态,主动刷新已连接设备列表
当用户从iOS设置回到你的应用时,我们可以在应用进入前台时重新获取当前系统已连接的HID设备,和之前保存的列表对比,发现新增的连接设备就触发通知。
代码示例:
首先注册前台通知:
- (void)viewDidLoad { [super viewDidLoad]; // 注册应用进入前台的通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterForeground:) name:UIApplicationDidEnterForegroundNotification object:nil]; // 初始化时先获取一次已连接设备 self.connectedPeripherals = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:@"你的HID服务UUID"]]]; } - (void)applicationDidEnterForeground:(NSNotification *)notification { // 获取当前已连接的HID设备 NSArray<CBPeripheral *> *currentConnectedPeripherals = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:@"你的HID服务UUID"]]]; // 对比新旧列表,找出新增的设备 NSMutableSet *oldSet = [NSMutableSet setWithArray:self.connectedPeripherals]; NSMutableSet *newSet = [NSMutableSet setWithArray:currentConnectedPeripherals]; [newSet minusSet:oldSet]; if (newSet.count > 0) { // 触发自定义通知,告知应用有设备通过系统设置连接了 [[NSNotificationCenter defaultCenter] postNotificationName:@"HIDPeripheralConnectedViaSettings" object:newSet.allObjects.firstObject]; // 更新保存的列表 self.connectedPeripherals = currentConnectedPeripherals; } } // 记得在dealloc中移除观察者 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
2. 监听蓝牙中心管理器的状态变化
当iOS系统的蓝牙状态发生变化(比如从关闭到开启,或者系统连接了新设备),CBCentralManager的centralManagerDidUpdateState:方法会被调用。我们可以在这里重新检查已连接的设备列表。
代码示例:
- (void)centralManagerDidUpdateState:(CBCentralManager *)central { if (central.state == CBCentralManagerStatePoweredOn) { // 蓝牙已开启,重新获取已连接设备 NSArray<CBPeripheral *> *currentConnectedPeripherals = [central retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:@"你的HID服务UUID"]]]; // 对比并处理变化逻辑(和上面的前台监听逻辑一致) NSMutableSet *oldSet = [NSMutableSet setWithArray:self.connectedPeripherals]; NSMutableSet *newSet = [NSMutableSet setWithArray:currentConnectedPeripherals]; [newSet minusSet:oldSet]; if (newSet.count > 0) { [[NSNotificationCenter defaultCenter] postNotificationName:@"HIDPeripheralConnectedViaSettings" object:newSet.allObjects.firstObject]; self.connectedPeripherals = currentConnectedPeripherals; } } }
3. 定时轮询已连接设备列表(不推荐,但适合特殊场景)
如果你的应用需要实时感知设备连接变化(即使在后台,不过后台蓝牙操作有一定限制),可以考虑使用定时器定时调用retrieveConnectedPeripheralsWithServices来检查设备状态变化。不过注意,这种方式会消耗一定的资源,尽量控制轮询间隔(比如3-5秒一次)。
代码示例:
- (void)startPollingForConnectedPeripherals { self.pollTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(checkConnectedPeripherals) userInfo:nil repeats:YES]; } - (void)checkConnectedPeripherals { NSArray<CBPeripheral *> *currentConnectedPeripherals = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:@"你的HID服务UUID"]]]; // 对比逻辑同上,省略重复代码 } // 记得在不需要时停止定时器 - (void)stopPolling { [self.pollTimer invalidate]; self.pollTimer = nil; }
关键注意事项
- 确保你使用的HID服务UUID是正确的,否则
retrieveConnectedPeripheralsWithServices无法返回目标设备。 - 后台模式:如果需要在后台感知设备连接变化,需要开启应用的
Bluetooth LE accessories后台模式,并且轮询操作在后台会有系统限制,可能无法持续运行。 - 设备标识符:你可以保存设备的
identifier属性(CBPeripheral的identifier),用来精准识别特定设备,避免因为设备名称变化导致的识别错误。
内容的提问来源于stack exchange,提问作者Hassan Shahbazi




