<原文链接>
关于外设
ExternalAccessory.framework为外设与任何iOS设备提供了一种交流的管道。开发者可以利用这个管道将外设的特性扩展到他们的应用程序中。
和外设交互需要你和外设硬件厂商密切合作,理解外设提供的服务。厂商必须在外设中构建与ios交互构建明确的支持。作为支持的一部分,一个外设至少支持一个命令协议,这个协议是应用与外设传输数据的机制。Apple没有维护协议的注册,而是取决于厂商打算支持哪个协议和是否使用自定义协议或者被其他厂商支持的标准协议。
作为和外设厂商交流的一部分,你必须找出设备支持的协议。为了防止命名冲突,建议使用反向DNS字符串命名,这样可以允许每一个厂商为他们的设备定义很多的协议。
概述
和外设交互需要外设本身的信息,这意味着你必须从硬件厂商获取。然后,你可以使用 External Accessory框架的类来创建应用与硬件的桥梁。
在你的项目中导入 ExternalAccessory.framework
为了使用External Accessory框架,你必须添加ExternalAccessory.framework到你的项目,并且链接到相关的targets。访问framework中的类,需要在源文件头引入<ExternalAccessory/ExternalAccessory.h>。
声明你的应用所支持的协议
应用想要和外设交互必须在Info.plist中声明所支持的协议。声明协议能够使操作系统知道在设备连接的时候你的应用可以启动。如果操作系统不知道哪个应用支持所连接的设备,它将会启动App store,并指出可以使用设备的应用。
声明所支持的协议,在Info.plist中添加UISupportedExternalAccessoryProtocols键,这个键包含了一个字符串数组,用来说明所支持的协议。你的应用可以包含任何数量的协议,并且无顺序要求。操作系统并不使用这个字符串数组来指名你的应用应该选择哪个协议,而只是声明你的应用是否可以和连接的设备交互。和外设交互使用的协议取决于你的代码。
和外设交互
应用和外设交互需要创建一个EASession对象,用来管理外设的动作。Sesion对象通过系统底层工作来在应用和外设之间传输数据包。一旦连接创建,应用的数据传输通过NSInputStream和NSOutputStream对象,这两个对象在Sesion对象中提供。接收外设的数据,我们需要使用一个自定义委托对象监听的input stream。发送数据给外设,需要向outstream写入字节包。数据包的格式取决于外设交互时使用的协议。
外设的连接
外设在连接到系统和配置好之前通过External Accessory框架是不可见的。当外设变为可见,你的应用便可以获得适当的外设对象,并通过外设支持的协议创建一个会话。
共享对象EAAccessoryManager,提供了应用程序的寻找外设的主入口点。这个类包含已经连接的外设对象的数组,你可以枚举以查看你的应用支持的外设。EAAccessory 对象中大部分信息只是为了显示。验证应用程序是否可以连接外设,你必须查看你的应用中是否有外设支持协议中的一个。
对于一个指定的外设对象,在同一时刻只能允许一个session。每个EAAccessory对象的ProtocolStrings属性包含了一个所支持协议的字典。如果你试图使用一个正在使用协议创建session,EXternal Accessory框架会在打开新session之前关闭已经存在的。
List1 展示了一个方法:检查连接的外设,并抓取第一个应用支持的外设。
为协议创建了session、并为session配置输入输出流。在返回session对象的时候,应用已经连接到外设并且准备收发数据。
1 - (EASession *)openSessionForProtocol:(NSString *)protocolString 2 { 3 NSArray *accessories = [[EAAccessoryManager sharedAccessoryManager]connectedAccessories]; 4 EAAccessory *accessory = nil; 5 EASession *session = nil; 6 7 for (EAAccessory *obj in accessories) 8 { 9 if ([[obj protocolStrings] containsObject:protocolString]) 10 { 11 accessory = obj; 12 break; 13 } 14 } 15 if (accessory) 16 { 17 session = [[EASession alloc] initWithAccessory:accessory forProtocol:protocolString]; 18 if (session) 19 { 20 [[session inputStream] setDelegate:self]; 21 [[session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 22 [[session inputStream] open]; 23 [[session outputStream] setDelegate:self]; 24 [[session outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 25 [[session outputStream] open]; 26 [session autorelease]; 27 } 28 } 29 return session; 30 }
在配置好输入输出流后,最后的步骤是处理流数据。
List2展示了流代理对象处理数据的基本结构。这个方法会在设备有输入、输出事件时响应。
当外设发送数据到应用的时候,事件讲指明有字节可以读取。类似的,当设备准备从应用接收数据,事件也会指出。(当然,应用不必在可写数据到流之前一直等带的到达的事件。而且,应用可以调用流的方法hasBytesAvailable来查看设备是否仍旧能够接收数据)。
List2
1 // Handle communications from the streams. 2 - (void)stream:(NSStream*)theStream handleEvent:(NSStreamEvent)streamEvent 3 { 4 switch (streamEvent) 5 { 6 case NSStreamHasBytesAvailable: 7 // Process the incoming stream data. 8 break; 9 case NSStreamEventHasSpaceAvailable: 10 // Send the next queued command. 11 break; 12 default: 13 break; 14 } 15 }
监听外设相关的事件
External Accessory framework有能力在硬件外设连接或者断开时发送通知。但是,这不是自动的。你的应用必须专门申请获取通知,通过EAAccessoryManager的registerForLocalNotifications方法来注册通知。
1.当设备连接、认证并准备好跟应用交互,框架将发送 EAAccessoryDidConnectNotification这个通知。
2.当设备断开连接,框架将发送 EAAccessoryDidDisconnectNotification这个通知。
你可以通过NSNotificationCenter注册接收这些通知,所有通知都包含了相关的设备的信息。
除了从通知中心收到通知之外,应用可以赋值一个delegate去响应EAAccessory对象和被通知一些变化。Delegate必须遵循EAAccessoryDelegate协议,这个协议包含了一个可选方法accessoryDidDisconnect:,你可以用此方法来接收断开通知而不用在刚开始设定一个通知监听者。
如果当通知到达的时候你的应用在后台,那么通知将会放入一个队列。当程序重新开始运行。通知队列将把通知交给应用。通知也合并和过滤尽可能消除任何无关紧要的事件。例如,如果一个外设在应用休眠期间连接并随后断开连接,你的应用程序将最终没有收到任何指示。
这里有个Apple的EADemo