最近看到MFI配件的app,需要External Accessory Framework框架。
说起来,我大概在13年底就接触了这玩意,只不过当时这个框架有些类是私有API。当时是基于硬件单片机和CoreBluetooth的研究,如果你做相关的关于USB之类的东西,例如Lightning等,就必须得到苹果授权认证了。
那么什么是External Accessory Framework?
这里引用了Apple Developer内的原文:
The External Accessory framework
(ExternalAccessory.framework) provides a conduit for communicating with accessories attached to any iOS-based device. App developers can use this conduit to integrate accessory-level features into their apps.
意思简单理解就是:
External Accessory Framework提供了配件连接iOS设备的通道。开发者可以通过它来开发连接配件的app。
配件可以通过30pin、蓝牙、USB的方式连接iOS设备。
它包含三个类:
EAAccessory
代表了一个单例的硬件配件对象。
EAAccessoryManager
管理所有连接到iPhone的配件。
EASession
定义了iPhone app与外部配件的连接和通道。-
EAAccessory类
EAAccessory类的属性: 1) Boolean connected read-only 配件是否连接iPhone的标志 @property (nonatomic, readonly, getter = isConnected) BOOL connected 2) NSUInteger connectionID read-only 连接设备的配件唯一标识 @property (nonatomic, readonly) NSUInteger connectionID EAAccessory Framework提供了可用配件的列表,所以要用NSArray来处理: for (EAAccessory *accessory in _accessoryList) { if ([disconnectedAccessory connectionID] == [accessory connectionID]) { break; } disconnectedAccessoryIndex++;6 }
id delegate 定义了接收配件状态变化的notifications的对象
定义一个accController类
@interface accController : NSObject {
EAAccessory *_accessory;
EASession *_session;
NSString *_protocolString;
}- (void)accessoryDidDisconnect : (EAAccessory *)accessory;
@end
- (void)accessoryDidDisconnect : (EAAccessory *)accessory;
4) NSString firmwareRevision read-only 固件版本信息,注意兼容性
@property (nonatomic, readonly) NSString *firmwareRevision
5) NNString hardwareRevision read-only 硬件版本信息,同上
@property (nonatomic, readonly) NSString *hardwareRevison
6) NSString manufacturer read-only 配件所属公司
@property (nonatomic, readonly) NSString *manufacturer
7) NSString modelNumber read-only 配件设备号
@property (nonatomic, readonly) NSString *modelNumber
8) NSString name read-only 配件名称,反馈给用户连接了正确的配件
@property (nonatomic, readonly) NSString *name
9) NSArray protocolStrings read-only protocols的名称,注意,跟connectionID对应,所以是一个NSArray的对象
@property (nonatomic, readonly) NSArray *protocolStrings
代码示例:
- (void)setupAccessoryController : (EAAccessory *)accessory withProtocolString : (NSString *)protocolString {
[_accessory release]; // 防止断开连接后重连不同配件
_accessory = [accessory retain];
[_protocolString release];
_protocolString = [protocolString copy];
}
这段代码可以用在配件连接设备后来创建一个accessory controller对象。
调用的方法:
[accessoryController setupAccessoryController : _selectedAccessory withProtocolString : [[_selectedAccessory protocolStrings] objectAtIndex : 0]]; // 只能连接一个设备
10) NSString serialNumber read-only 连接的配件序列号,每个配件唯一
@property (nonatomic, readonly) NSString *serialNumber
EAAccessory类中的常量:
EAConnectionIDNone 实质为0,无效的连接,通过与connectionID的比较,可以尝试重连配件或者提示用户断开配件重新连接设备。
这第一个类EAAccessory就先了解到这里。
// 为协议创建了session、并为session配置输入输出流。在返回session对象的时候,应用已经连接到外设并且准备收发数据。
- (EASession *)openSessionForProtocol:(NSString *)protocolString {
NSArray *accessories = [[EAAccessoryManager sharedAccessoryManager] connectedAccessories];
EAAccessory *accessory = nil;
EASession *session = nil;
for (EAAccessory *obj in accessories) {
if ([[obj protocolStrings] containsObject:protocolString]) {
accessory = obj;
break;
}
}
if (accessory) {
session = [[EASession alloc] initWithAccessory:accessory forProtocol:protocolString];
if (session) {
[[session inputStream] setDelegate:self];
[[session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[session inputStream] open];
[[session outputStream] setDelegate:self];
[[session outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[session outputStream] open];
}
}
return session;
}
// Handle communications from the streams.
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventHasBytesAvailable:
// Process the incoming
break;
case NSStreamEventHasSpaceAvailable:
// Send the next queued command.
default:
break;
}
}
EAWiFiUnconfiguredAccessory和EAWiFiUnconfiguredAccessoryBrowser类是iOS8之后才有的。之前研究的时候是基于iOS6和iOS7,所以那时候基本上拿不到MFI认证的东西,现在有了这两个类,方便多了。