You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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系统的蓝牙状态发生变化(比如从关闭到开启,或者系统连接了新设备),CBCentralManagercentralManagerDidUpdateState:方法会被调用。我们可以在这里重新检查已连接的设备列表。

代码示例:

- (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属性(CBPeripheralidentifier),用来精准识别特定设备,避免因为设备名称变化导致的识别错误。

内容的提问来源于stack exchange,提问作者Hassan Shahbazi

火山引擎 最新活动