一引言
最近在为下一个项目做准备, 其中有一项是手机跟蓝牙4.0的外设连接并实现通讯(非4.0的外设会很麻烦, 需要了解的可以自行的去查, 这里不再具体说).所有抽空简单学习了一下iOS中的coreBluetooth框架以及一些简单的应用, 由于我们的通讯已经有同事封装了现成的sdk, 这里不涉及通讯的内容(其实是我也不太清楚).就跟大家简单的说一下扫描和连接.
二.iOS蓝牙连接的解决方案
iOS设备蓝牙连接主要有一下几种实现方式:
①.参加苹果的(MFI)计划, 也就是需要得到苹果的认证, 费用高, 至于高到什么程度, 自己可以去查一下.
②.coreBluetooth框架. 只支持4.0的蓝牙设备, 也是本文的主角, 一会会具体说.
③.GameKit框架. 这个框架只用用于iOS设备之间的蓝牙连接通讯, 并不符合我们的需求, 没有仔细研究.
④.私有API(BluetoothManager框架). 这个东西怎么说, 对于一些经历过被拒的惨痛教训的人来说, 用私有api?还是算了吧, 如果你想用, 你可以试试,反正我是不用!
⑤.越狱. 如果你做越狱包得话,这个就随意了, 想怎么用怎么用.
三.coreBluetooth框架连接4.0的蓝牙外设
CoreBluetooth两个很重要的概念,Central 和 Periperal Devices. 也就是中心和外设, 这里我们是要用手机扫描外设, 连接之后实现通讯, 所以这里我们的手机就是Central了.
首先, 我们创建一个工程, 导入coreBluetooth框架
然后就是在我们的项目中引入coreBluetooth框架了.这里封装了一个工具类, .h文件如下代码
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import <UIKit/UIKit.h>
/** 工具类
* @note 用于扫描周边的蓝牙4.0设备,并存储
*/
@interface GetBluetoothEquipmentNearby : NSObject<CBCentralManagerDelegate>
/*...用于存储周边的设备列表...*/
@property (nonatomic, strong)NSMutableArray * devicesListArray;
/** 扫描周边外设
* @note 扫描周边的所有蓝牙4.0外设
*/
-(void)discoverDevices;
以下是代码的实现部分了:
-(void)discoverDevices
{
/*...创建manager对象, 创建完成之后会回调代理方法...*/
self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
/*...扫描周边的外设...*/
[self.bluetoothManager scanForPeripheralsWithServices:nil options:nil];
}
创建完之后, 会回调代理方法
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch ([central state])
{
case CBCentralManagerStateUnsupported:
NSLog(@"蓝牙不可用");
break;
case CBCentralManagerStateUnauthorized:
NSLog(@"未授权");
break;
case CBCentralManagerStatePoweredOff:
NSLog(@"蓝牙未打开");
break;
case CBCentralManagerStatePoweredOn:
NSLog(@"蓝牙已打开");
break;
case CBCentralManagerStateUnknown:
NSLog(@"状态未知");
default:
NSLog(@"不明情况了");
;
}
}
接着就是扫描外设了, 这里我们参数都传的是nil, 意思就是扫描所有的外设.当然你也可以传一个UUID进去, 是以数组的形式传得.这里由于我们做的是模拟第一次连接, 也就没有指定的UUID了, 有兴趣的可以自己测一下传一个UUID进去.
/*...扫描周边的外设...*/
[self.bluetoothManager scanForPeripheralsWithServices:nil options:nil];
这就开始扫描了外设, 扫描到外设的时候同样是会回调代理方法来通知我们的.
/*...扫描到外设的时候会调该方法...*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
if(![self.devicesListArray containsObject:peripheral])
[self.devicesListArray addObject:peripheral];
NSLog(@"%@", peripheral.identifier);
NSLog(@"%@", peripheral);
}
这里打印出来的peripheral.identifier就是外设的UUID, 以我的代码风格来说的话, 这个时候我会用个model来存储该外设的所有信息. 以后用的话也方便, 至于你想怎么用, 这个就因人而异了.另外还有注意的是,打印的一些其他参数advertisementData是广告数据,rssi代表着信号强度. 由于我这会并没有外设让我来测试, 我这边也没法贴图给大家了,见谅.
像苹果这样这么追求用户体验的,有开始扫描, 必定会有停止扫描了, 至于在什么时候停止, 这就看各位看官们的心情了.
[self.bluetoothManager stopScan];
下面就是连接了, 这里很方便:
//连接指定的设备
-(BOOL)connect:(CBPeripheral *)peripheral
{
[self.bluetoothManager connectPeripheral:peripheral
options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
return YES;
}
这里连接到的设备是可以自己去指定的.显然以苹果的风格, 连接成功之后需要回调来通知我们连接成功的.
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@"Did connect to peripheral: %@", peripheral);
}
到这里, 就实现了扫描蓝牙4.0的外设并实现连接了.至于加定时器来监控连接超时, 这个我想大家应该都会写, 这里不再贴代码.
四.结语
正如我开头说的, 我们的通讯有同事封装好的SDK, 所以这里就没有介绍扫描外设中的服务, 以及订阅这些内容了.只是单纯的一个扫描和连接, 如果你想让你的功能类更强大, 就可以根据需求填一些功能了, 比如监听连接状态, 连接超时, 自动重连等等.
另:我这边有一个问题一直没有解决, 就是:第一次用的时候, 跳到设置里面去把蓝牙打开之后, 我不知道怎么让他自动跳回到应用中, 害的我每次都要重新启动应用.这里希望知道怎么解决的朋友说一下, 不胜感激!--CP