Tuesday, September 6, 2011

This is About Choice.

Working with the USB APIs with Android essentially requires three choices: 

Mode: Do you want to use USB accessory mode or USB host mode? See http://developer.android.com/guide/topics/usb/index.html.
Platform: Do you want to target Android 3.1 (API level 12) and higher or Android 2.3.4 (API level 10)? 
API: Do you want to include the Google add-on library (see http://code.google.com/android/add-ons/google-apis/index.htmlor work with the framework API?


These choices are certainly intertwined in a demonical fashion. What follows is the abridged lowdown (you can read the whole story here http://developer.android.com/guide/topics/usb/index.html).

A word of caution. This area is still a bit maker/hacker/nerd territory. In neither case you can be absolutely certain that USB is supported on an Android device/platform - this ultimately depends on the device manufacturer, the current firmware or particular mod the device is on. So its better to check - especially for 2.3.4The device specs usually do not have that information yet and the internets are full of "works/doesn't work" reports. The Nexus One, Nexus S and (the US version (?) of the) Motorola Xoom are "officially ok'ed" for the ADK challenge. 

So here are the rules:

Mode
If you want to use USB host mode you must target 3.1 or later
If you want to use USB accessory mode you can choose to target 3.1 or 2.3.4.

Platform
If you target 3.1 or later you can use host mode or accessory mode. For accessory mode you can choose to use the add-on library (for compatibility with 2.3.4) or the framework API. For host mode there is only the framework API.
If you target 2.3.4 you must use the add-on library and it is accessory mode only.

API
If you use accessory mode with the add-on libraryyou import the package:
com.android.future.usb

Then you obtain the UsbManager object like this:
UsbManager manager = UsbManager.getInstance(this);

If you have declared an Intent filter (see http://developer.android.com/guide/topics/usb/accessory.html) for the attachment/detachment of devices you obtain the UsbAccessory object like this:
UsbAccessory accessory = UsbManager.getAccessory(intent);

In the Manifest you need to declare
<uses-feature android:name="android.hardware.usb.accessory"/>
within <manifest> and
<uses-library android:name="com.android.future.usb.accessory"/>
within <application>.

If you work with the framework API however, you import from
android.hardware.usb
and get a reference to these objects as follows: 
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

In the Manifest declare
<uses-feature android:name="android.hardware.usb.accessory"/>
and <uses-sdk android:minSdkVersion="12"/> within the <manifest> tag.
The other methods, declarations, intent filters and bruhaha seem to work in the same manner across both options. My intent (pun!) here was to highlight the differences. Also, as we are mainly concerned with accessory mode, I left out host mode here. 
Read:
For the ADK challenge I am using accessory mode with the framework API on a 3.1 device.