蓝牙
概述
现有蓝牙实现方案
GameKit.framework(用法简单)
只能用于iOS设备之间的连接,多用于游戏(比如五子棋对战),从iOS7开始过期
MultipeerConnectivity.framework
只能用于iOS设备之间的连接,从iOS7开始引入,主要用于文件共享(仅限于沙盒的文件)
ExternalAccessory.framework
可用于第三方蓝牙设备交互,但是蓝牙设备必须经过苹果MFi认证(国内较少)
CoreBluetooth.framework(时下热门)
可用于第三方蓝牙设备交互,必须要支持蓝牙4.0
硬件至少是4s,系统至少是iOS6
蓝牙4.0以低功耗著称,一般也叫BLE(Bluetooth Low Energy)
目前应用比较多的案例:运动手坏、嵌入式设备、智能家居
MultipeerConnectivity用法跟GameKit很像,ExternalAccessory很少用,因此简单记录下GameKit和CoreBluetooth(处于Core OS Layer)在蓝牙上的用法
GameKit
gamekit只能用于iOS设备间传递且还设备运行的必须是同一个应用程序,此外系统提供的解决方案没有进度显示UE很差(一般只用于小数据传递)
开发步骤:
1、显示可以连接的蓝牙设备列表
GKPeerPickerController *ppc = [[GKPeerPickerController alloc] init]; ppc.delegate = self; // 设置代理 [ppc show];
2、在代理方法中监控蓝牙的连接
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session { NSLog(@"连接到设备:%@", peerID); // 关闭蓝牙设备显示界面 [picker dismiss]; // 设置接收到蓝牙数据后的监听器 [session setDataReceiveHandler:self withContext:nil]; // 保存session self.session = session; }
PS:成为GKSession的Handler的类必须实现receiveData: fromPeer: inSession: context: 方法
(采用的是方法回调方式)
3、处理接收到的蓝牙数据
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context { //处理逻辑。。。 }
4、利用GKSession给其他设备发送数据
//给指定的连接设备发送数据 - (BOOL)sendData:(NSData *) data toPeers:(NSArray *)peers withDataMode:(GKSendDataMode)mode error:(NSError **)error; //给所有连接的设备发送数据 - (BOOL)sendDataToAllPeers:(NSData *) data withDataMode:(GKSendDataMode)mode error:(NSError **)error;
CoreBluetooth
概述
>每个蓝牙4.0设备都是通过服务(Service)和特征(Characteristic)来展示自己的
一个设备必然包含一个或多个服务,每个服务下面又包含若干个特征
>特征是与外界交互的最小单位
eg: 一台蓝牙4.0设备,用特征A来描述自己的出厂信息,用特征B来收发数据
>服务和特征都是用UUID来唯一标识的,通过UUID就能区别不同的服务和特征
>设备里面各个服务(service)和特征(characteristic)的功能,均由蓝牙设备硬件厂商提供,比如哪些是用来交互(读写),哪些可获取模块信息(只读)等
Core Bluetooth的开发步骤
1.建立中心设备
// 创建中心设备 CBCentralManager *mgr = [[CBCentralManager alloc] init]; self.mgr = mgr; // 设置代理 mgr.delegate = self;
2.扫描外设(Discover Peripheral)
//利用中心设备扫描外部设备 //如果指定数组代表只扫描指定的设备 [mgr scanForPeripheralsWithServices:nil options:nil]; #pragma mark - CBCentralManagerDelegate - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { // 保存扫描到得外部设备 // 判断如果数组中不包含当前扫描到得外部设置才保存 if (![self.peripherals containsObject:peripheral]) { peripheral.delegate = self; [self.peripherals addObject:peripheral]; } }
3.连接外设(Connect Peripheral)
for (CBPeripheral *peripheral in self.peripherals) { // 连接外设 [self.mgr connectPeripheral:peripheral options:nil]; } // 连接外设成功调用 - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { // 扫描外设中得服务 [peripheral discoverServices:nil]; } //连接外设失败调用 - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { }
4.扫描外设中的服务和特征(Discover Services And Characteristics)
#pragma makr - CBPeripheralDelegate /** * 只要扫描到服务就会调用 * * @param peripheral 服务所在的外设 */ - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { // 获取外设中所有扫描到得服务 NSArray *services = peripheral.services; for (CBService *service in services) { // 拿到需要的服务 if ([service.UUID.UUIDString isEqualToString:@"123"]) { // 从需要的服务中查找需要的特征 // 从peripheral中得service中扫描特征 [peripheral discoverCharacteristics:nil forService:service]; } } } /** * 只要扫描到特征就会调用 * * @param peripheral 特征所属的外设 * @param service 特征所属的服务 */ - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { // 拿到服务中所有的特诊 NSArray *characteristics = service.characteristics; // 遍历特征, 拿到需要的特征处理 for (CBCharacteristic * characteristic in characteristics) { if ([characteristic.UUID.UUIDString isEqualToString:@"xxxx"]) { ..... } } }
5.利用特征与外设做数据交互(Explore And Interact)
6.断开连接(Disconnect)