<原文鏈接>
關於外設
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