ExternalAccessory(外部设备相关的一个框架)
主要的类:
hehhe
EAAccessoryManager: 管理设备,可以获取当前连接的所有的设备
EAAccessory: 连接的硬件设备
EASession:主要用来建立通道,让App和连接的设备进行数据的传输(发送和接受)
连接设备的两种方法
到系统蓝牙页面连接设备
应用内弹出tableView警告窗显示可用的传统蓝牙设备,点击即可连接设备
// 过滤器可过滤符合要求的设备
[[EAAccessoryManager sharedAccessoryManager] showBluetoothAccessoryPickerWithNameFilter:[NSPredicate predicateWithFormat:@"self CONTAINS 'Cubinote'"] completion:^(NSError * _Nullable error) {
NSLog(@"error = %@", error);
}];
// 不做过滤
[[EAAccessoryManager sharedAccessoryManager] showBluetoothAccessoryPickerWithNameFilter:nil completion:nil];
EAAccessoryManager(获取连接设备)
当有硬件断开或连接的时候,ExternalAccessory框架会发送EAAccessoryDidDisconnectNotification和EAAccessoryDidConnectNotification通知,但是需要我们自己注册通知
[[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(accessoryDidConnect:) name:EAAccessoryDidConnectNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(accessoryDidDisconnect:) name:EAAccessoryDidDisconnectNotification object:nil]
- (void)accessoryDidConnect:(NSNotification *)notification {
EAAccessory *conAccessory = [[notification userInfo] objectForKey:EAAccessoryKey]; // 用EAAccessoryKey来获取连接的设备
}
- (void)accessoryDidDisconnect:(NSNotification *)notification {
EAAccessory *disConAccessory = [[notification userInfo] objectForKey:EAAccessoryKey]; // 用EAAccessoryKey来获取断开的设备
}
获取当前所连接的所有设备
// 利用EAAccessoryManager的connectedAccessories属性获取
NSArray *accessoryArray = [[EAAccessoryManager sharedAccessoryManager] connectedAccessories];
判断是否是自己的设备根据协议名来判断.在info.plist添加UISupportedExternalAccessoryProtocols,添加硬件提供的协议
创建EASession (打开输入、输出通道)
[[EASession alloc] initWithAccessory:accessory forProtocol:protocolString]; // 根据EAAccessory和协议名创建EASession
// 1.创造了可以进行发送和接受数据的EASesssion对象
- (BOOL)openSession {
// 根据已经连接的EAAccessory对象和这个协议(反向域名字符串)来创建EASession对象,并打开输入、输出通道
EASession *session = [[EASession alloc] initWithAccessory:self.accessory forProtocol: kSPKLightingHeadphoneProtocolString];
if(session != nil) {
// open input stream
session.inputStream.delegate = self;
[session.inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
// open output stream
session.outputStream.delegate = self;
[session.outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream open];
}
else {
NSLog(@"Failed to create session");
}
return (nil != session);
}
// close the session with the accessory.
- (void)closeSession {
[[_session inputStream] close];
[[_session inputStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[_session inputStream] setDelegate:nil];
[[_session outputStream] close];
[[_session outputStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[_session outputStream] setDelegate:nil];
_session = nil;
_writeData = nil;
_readData = nil;
}
// 2.进行发送、接受数据;因为遵守了NSStreamDelegate利用代理的回调监听输入流和输出流
// asynchronous NSStream handleEvent method
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventNone: // 没有事情发生
break;
case NSStreamEventOpenCompleted: // 流被成功打开
break;
case NSStreamEventHasBytesAvailable: // 有数据可以读取
[self _readData];
break;
case NSStreamEventHasSpaceAvailable: // 流可以接受写入数据
[self _writeData];
break;
case NSStreamEventErrorOccurred: // 在流上有错误发生
break;
case NSStreamEventEndEncountered: // 到达了流的结束位置
break;
default:
break;
}
发送接受数据
- HasBytesAvailable:表示stream中有数据需要读取(硬件发送了数据给App)
- HasSpaceAvailable:表示stream中可以接收数据的写入(App发送了数据给硬件)。其实主要判断stream的hasBytesAvailable属性为Yes就可以直接发送数据给硬件,没必要等到这个回调。
- (void)_writeData {
while (([[_session outputStream] hasSpaceAvailable]) && ([_writeData length] > 0)) {
NSInteger bytesWritten = [[_session outputStream] write:[_writeData bytes] maxLength:[_writeData length]];
if (bytesWritten == -1) {
NSLog(@"write error");
break;
}
else if (bytesWritten > 0) {
[_writeData replaceBytesInRange:NSMakeRange(0, bytesWritten) withBytes:NULL length:0];
NSLog(@"bytesWritten %ld", (long)bytesWritten);
}
}
}
- (void)_readData {
#define EAD_INPUT_BUFFER_SIZE 128
uint8_t buf[EAD_INPUT_BUFFER_SIZE];
while ([[_session inputStream] hasBytesAvailable]) {
NSInteger bytesRead = [[_session inputStream] read:buf maxLength:EAD_INPUT_BUFFER_SIZE];
if (_readData == nil) {
_readData = [[NSMutableData alloc] init];
}
[_readData appendBytes:(void *)buf length:bytesRead];
NSString *stirng = [[NSString alloc] initWithData:_readData encoding:NSUTF8StringEncoding];
NSLog(@"read %ld bytes from input stream", (long)bytesRead);
}
}