Communicating with external devices from the iPhone and iPad

An expanding marketplace for devices capable of interacting with iPad and iPhone applications is sure to be a major driver of corporate iOS-related spending in 2011. Starting with the release of iOS 3.0 in June 2009, external hardware devices connected via the dock connector or wirelessly over Bluetooth could for the first time, using a new iOS framework called External Accessories, communicate with iPhone/iPad devices. While Apple referenced medical devices as a major user of this new capability, other use cases, such as Point of Sale and Game Controllers have taken off in the marketplace in the past year. These external hardware devices are required to be part of the ‘Made for iPod’ (MFi) and Works With iPhone licensee program (http://developer.apple.com/programs/mfi/), and to contain a chip to decode the communication between the iPhone/iPad and the external device.

To be able to communicate with external devices, manufacturers must support at least one command protocol, or custom scheme for sending data back and forth between the device and iOS application. Each command contained within the protocol is sent in fixed or variable sized data packets or groups of packets, and is generally ordered by decreasing importance of information. The protocol must be defined in the info.plist file of the iOS project, and must have a unique name, typically using a reverse-DNS form: com.yourcompany.${PRODUCT_NAME:rfc1034identifier}. In addition, the info.plist file should include a UISupportedExternalAccessoryProtocols key to declare (as an array of strings) the specific hardware protocols supported by the project.

The External Accessory (EA) Framework ultimately provides the conduit for communication between an iOS app and an external MFi devices. A shared EAAccessoryManager offers the main entry point for communicating with the external device. To listen for device connections and disconnections, a registerForLocalNotifications method in EAAccessoryManager should be implemented; it will receive a EAAccessoryDidConnectNotification for connections, and a EAAccessoryDidDisconnectNotification for disconnects.

The EA Framework’s EASession class is used to create a per-protocol communication channel between the app and device (multiple protocols can exist between app and device), and streams are used to handle the actual data communication between the app and the device.

To create a EASession, create a reference to an EASession object called session using the standard alloc-init method:

EASession * session [[EASession alloc] initWithAccessory: accessory forProtocol:protocolString];

To handle the stream of data to and from the device, the Cocoa classes NSInputStream and NSOutputStream are used. To create the streams, one typically:

  • Checks that the session is open (i.e., you are talking with your device),
  • Sets the stream delegate (usually to self)
  • Schedules the stream to execute in a run loop
  • Opens the stream

In code form, the snippet might look like:

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];
}

Once the streams have been open, theStream:handleEvent method, a framework for which is shown below, will handle events from the input and output streams (since the delegate above was set to self for both streams).

 // Handle communications from the streams.
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
switch(streamEvent)
{
  case NSStreamEventNone:
    break;
  case NSStreamEventOpenCompleted:
    break;
  case NSStreamEventHasBytesAvailable:// Process the incoming stream data
    break;
  case NSStreamEventHasSpaceAvailable://Send the next queued command
    break;
  case NSStreamEventErrorOccurred:
    break;
  case NSStreamEventEndEncountered:
    break;
  default:
    break;
  }
}

Using the External Accessory framework, iOS applications can communicate with “Made for Ipod” (Mfi) hardware accessories either wirelessly using bluetooth or through a 30-pin dock connector. While the framework contains a small number of classes, the implementation of communication between an iOS application and an external device can be complex. For further reading on this topic, the Apple Developer iOS Reference Library documentation (http://bit.ly/ca12lZ) and the book “Building iPhone OS Accessories: Use the iPhone Accessories API to Control and Monitor Devices” (http://amzn.to/acHveK) are strongly recommended guides.

About the Author

Object Partners profile.
Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Android Development for iOS Developers
Android development has greatly improved since the early days. Maybe you tried it out when Android development was done in Eclipse, emulators were slow and buggy, and Java was the required language. Things have changed […]
Add a custom object to your Liquibase diff
Adding a custom object to your liquibase diff is a pretty simple two step process. Create an implementation of DatabaseObject Create an implementation of SnapshotGenerator In my case I wanted to add tracking of Stored […]
Keeping Secrets Out of Terraform State
There are many instances where you will want to create resources via Terraform with secrets that you just don’t want anyone to see. These could be IAM credentials, certificates, RDS DB credentials, etc. One problem […]
Validating Terraform Plans using Open Policy Agent
When developing infrastructure as code using terraform, it can be difficult to test and validate changes without executing the code against a real environment. The feedback loop between writing a line of code and understanding […]