Showing Posts From

Ancs

处理ANCS设备连接绑定问题

ANCS(Apple Notification Center Service,苹果通知中心)的目的是提供给蓝牙外设一种简单、方便的获取iOS设备通知信息的方式。使得蓝牙手环,手表可以接收到来自iPhone的来电、短信及QQ、微信等应用的通知消息。 如果你已经能够连接普通蓝牙,初次面对ANCS设备可能会有以下问题:问题一:遵循ANCS协议的的设备会直接和系统相连,即使杀掉应用,连接还是存在的。而如果蓝牙设备处于连接状态,它不会被扫描到,怎么再次连接呢?在Core Bluetooth framework里提供了两个方法,用于获取已连接的设备 //通过传入的peripherals.identifier返回与系统连接的已知设备数组 - (NSArray<CBPeripheral *> *)retrievePeripheralsWithIdentifiers:(NSArray<NSUUID *> *)identifiers; //通过传入设备的serviceID返回已连接的设备数组 - (NSArray<CBPeripheral *> *)retrieveConnectedPeripheralsWithServices:(NSArray<CBUUID *> *)serviceUUIDs;我们就可以通过这两个方法,获取已连接设备,并建立重连。参考代码: NSArray *peripherals = [central retrieveConnectedPeripheralsWithServices:@[serviceUUID]]; if (peripherals.count > 0) { CBPeripheral *peripheral = [peripherals firstObject]; peripheral.delegate = self; self.peripheral = peripheral;//**关键**需要转存外设值,才能发起连接 [central connectPeripheral:self.peripheral options:nil]; } else { [central scanForPeripheralsWithServices:@[serviceUUID] options:nil]; }根据不同的使用情况,可能会有不同的扫描,连接的逻辑,苹果提供了一个流程图:问题二:有绑定和解除功能,如何处理两者的关系首先我们要知道,不能通过代码,断开ANCS设备与系统之间的连接,那么如果我们想解除设备的绑定,只能控制设备与APP之间的断开。 ###绑定 再回看上面提到的苹果提供的两个获取已连接设备的方法,一个是通过serviceUUID,它可以返回同一类型的设备列表;一个是通过设备UUID,它在一定情况下就是唯一的(如果设备名唯一,这里可以使用设备名),返回的是唯一设备。那么我们就可以利用UUID的唯一性,作为绑定的标示,存到NSUserDefault里面,对于未绑定的设备通过serviceUUID去获取设备列表。参考代码: NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; NSString *uuidString = [userDefault objectForKey:RWBLE_BANDIDENTIFI_ID];NSArray *peripherals; if (uuidString) {         //通过uuid获取连接设备     NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:uuidString];         peripherals = [self.centralManager retrievePeripheralsWithIdentifiers:@[uuid]]; }else{         //通过serviceUUID获取连接设备         peripherals = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:ST_SERVICE_UUID]]]; } /* peripherals connect code */###解绑 不能使ANCS设备与系统连接断开,那么我们就在程序里销毁这个外设对象,这样APP与蓝牙设备的连接通讯就不存在了,造成了一种断开的感觉。参考代码: //解绑设备 - (void)unbindDevice{     [self disconnect];//通知app,设备已经断开    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];     [userDefault removeObjectForKey:RWBLE_BANDIDENTIFI_ID];//销毁uuid     self.peripheral = nil; }这么写看似已经解决问题了,但是会出现一种情况:解绑了设备,杀掉应用,再次进入设备还是能连上。why?因为虽然没有了UUID,但进入程序会通过serviceUUID再次获取连接。 这时可以在扫面做一个判断,是否刚解绑过设备。可以是个BOOL值,绑定和初始绑定为NO,解绑操作改为YES。如果刚解绑过设备,就直接返回不做后面的扫描操作,这样就解决了上面的问题。这个比较简单,就不列具体代码了。 参考文档: Best Practices for Interacting with a Remote Peripheral Device