-
Notifications
You must be signed in to change notification settings - Fork 356
IOIO Over OpenAccessory
Android OpenAccessory (AOA) is a protocol developed by Google (introduced on May 2011), which enables a hack-free connection of peripherals to Android devices. The protocol is supported in Android 2.3.4 and higher, and on a limited number of devices. Android 4.x devices generally support AOA.
Naturally, it makes sense for IOIO to communicate with the Android device using this protocol whenever it is available, avoiding the need for running the Android device with USB debugging enabled. In addition, the OpenAccessory connection also has some performance gains over ADB.
The OpenAccessory-enabled firmware and software support OpenAccessory in addition to ADB. Both will know how to "do the right thing" and use ADB whenever appropriate.
Both ADB and OpenAccessory are based on a USB connection. The IOIO firmware is built in such a way that if an Android device is connected, on which ADB is enabled, ADB will be used. If OpenAccessory is supported, OpenAccessory will be used. If both are available, ADB wins, and the Android-IOIO communication will use ADB. So you should be aware that in order to use OpenAccessory you should switch USB debugging off.
As you'll see below, your Android application also needs to be built in a certain way in order to be able to use OpenAccessory. Luckily, changing an existing IOIO application to use OpenAccessory a technical and very simple process.
Another important aspect is that your application has to be based on IOIOActivity
, IOIOService
, or IOIOAndroidApplicationHelper
for this to work. These classes take care of all the gory details (and believe me, they are gory) of communicating with an Android accessory.
Using OpenAccessory gives some nice improvements in comparison to ADB:
- One-way average latency improves from ~4ms to ~1ms.
- Jitter (i.e. variance in latency) is much smaller.
- Effective throughput increases from ~300KB/s to ~600KB/s.
- You can have the connecting of the IOIO automatically trigger your app of choice.
- IOIO is not using ADB. So you can leave it off, or use ADB over WiFi and debug your app while it is connected to the IOIO (may require rooting on certain Android devices).
Simply use the software / firmware with versions 3.21 or greater, from the Downloads page. You may use the IOIO Manager Application to upgrade the firmware. Note that this firmware requires a V3.x bootloader, so very old IOIO's that haven't had their bootloader upgraded may need a bootloader upgrade in order to install this firmware.
Notice that the examples shipped with the software bundle have OpenAccessory support, so you can use them as reference or just modify them to your needs.
In the software zip file, you'll find the IOIOLibAccessory library.
- Import it to your Eclipse workspace (File > Import > Existing Projects Into Workspace).
- Link it into your application by right-clicking the application's project > Properties > Android > click "Add..." in the library pane and choose the IOIOLibAccessory project.
- The IOIOLibAccessory library itself must be built against an Android target that supports OpenAccessory (e.g. API-10 + Google APIs). Otherwise, it won't compile. However, your application can be built against any Android API, 7 or higher. It will use OpenAccessory whenever it is available, and gracefully avoid it, if the runtime environment doesn't support it.
Some changes are required to the AndroidManifest.xml file of your application in order to utilize OpenAccessory. This file is found under the root directory of your project. Double-click it to edit inside Eclipse, using a specialized editor.
- If you prefer manually editing the xml file, click on the tab called "AndroidManifest.xml" at the bottom of the editor pane, and see an example file below.
- In the Manifest tab, "Manifest Extras" pane: if you don't have a "Uses Sdk" node, add one. Set "Min SDK Version" on the right to 7 or later. Setting it to a smaller number will cause the application to fail in run-time (see compatibility notes below).
- In the application tab, "application nodes" pane: "Add..." > "Create a new element..." > Users Library > Enter
com.android.future.usb.accessory
in the "name" box on the right, andfalse
in the "required" box (to enable graceful degradation). This tells Android that your application would like to use the OpenAccessory system library, if it's available. - In the application tab, "application nodes" pane: select activity > "Add..." > Intent Filter > "Add..." again > Action > Enter
android.hardware.usb.action.USB_ACCESSORY_ATTACHED
in the "name" box on the right. This tells Android that your application would like to register itself as one that can work with an accessory. - In the application tab, "application nodes" pane: select your activity > on the right, find the "Launch mode" setting (might need to scroll down) and set it to
singleTask
. This will make sure that no two instances of your application will be running at the same time (which would cause lots of problems with regards to communicating with the IOIO). - In the application tab, "application nodes" pane: select your activity > "Add..." > Meta Data > set Name to
android.hardware.usb.action.USB_ACCESSORY_ATTACHED
and Resource to@xml/accessory_filter
. This tells Android that your application works with a specific kind of accessories, as described in an XML resource file. - Under the
res
directory of your project, create a directory calledxml
. Create a file calledaccessory_filter.xml
in this directory. Edit it to include the contents below.
The accessory_filter.xml
file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-accessory model="IOIO" />
</resources>
An example AndroidManifest.xml
file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:a="http://schemas.android.com/apk/res/android"
package="ioio.examples.hello"
a:versionCode="1"
a:versionName="1.0">
<uses-sdk a:minSdkVersion="7" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<application a:icon="@drawable/icon" a:label="@string/app_name">
<uses-library a:name="com.android.future.usb.accessory" a:required="false" />
<activity a:name="MainActivity"
a:label="@string/app_name" a:launchMode="singleTask">
<intent-filter>
<action a:name="android.intent.action.MAIN" />
<category a:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action a:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data a:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
a:resource="@xml/accessory_filter" />
</activity>
</application>
</manifest>
Ideally, you'd want a single .apk file that would be compatible with any Android version, possibly taking advantage of later features, if they exist. The IOIO libraries are all built with that property in mind. Unfortunately, the Android libraries aren't...
If you look above, you'll see that we declared that our application would like to use the com.android.future.usb.accessory library. It also mentions that it doesn't require it. So far so good. But the required
attribute itself was only added in API-7 (Android 2.1). So earlier versions of Android won't let your application run as result of the library not being available, and thus there is no known way of having a single .apk that will work both with OpenAccessory AND with API < 7. If anyone knows of a workaround, please report it. Converting your application to work on API < 7 (without OpenAccessory, of course), is a simple matter of removing the <uses-library>
element, changing minSdkVersion
to 3 and rebuilding.