| page.title=USB Accessory |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>In this document</h2> |
| |
| <ol> |
| <li> |
| <a href="#choosing">Choosing the Right USB Accessory APIs</a> |
| |
| <ol> |
| <li><a href="#installing">Installing the Google APIs add-on library</a></li> |
| </ol> |
| </li> |
| |
| <li> |
| <a href="#api">API Overview</a> |
| |
| <ol> |
| <li><a href="#usage">Usage differences between the add-on library and the platform |
| APIs</a></li> |
| </ol> |
| </li> |
| |
| <li><a href="#manifest">Android Manifest Requirements</a></li> |
| |
| <li> |
| <a href="#working-a">Working with accessories</a> |
| |
| <ol> |
| <li><a href="#discovering-a">Discovering an accessory</a></li> |
| |
| <li><a href="#permission-a">Obtaining permission to communicate with an |
| accessory</a></li> |
| |
| <li><a href="#communicating-a">Communicating with an accessory</a></li> |
| |
| <li><a href="#terminating-a">Terminating communication with an accessory</a></li> |
| </ol> |
| </li> |
| </ol> |
| |
| <h2>See also</h2> |
| |
| <ol> |
| <li><a href="http://accessories.android.com/demokit">Android USB Accessory Development |
| Kit</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p>USB accessory mode allows users to connect |
| USB host hardware specifically designed for Android-powered devices. The accessories must adhere |
| to the Android accessory protocol outlined in the <a href= |
| "http://accessories.android.com/demokit">Android Accessory Development Kit</a> documentation. |
| This allows Android-powered devices that cannot act as a USB host to still interact with USB |
| hardware. When an Android-powered device is in USB accessory mode, the attached Android USB |
| accessory acts as the host, provides power to the USB bus, and enumerates connected devices. |
| Android 3.1 (API level 12) supports USB accessory mode and the feature is also backported to |
| Android 2.3.4 (API level 10) to enable support for a broader range of devices.</p> |
| |
| <h2 id="choosing">Choosing the Right USB Accessory APIs</h2> |
| |
| <p>Although the USB accessory APIs were introduced to the platform in Android 3.1, they are also |
| available in Android 2.3.4 using the Google APIs add-on library. Because these APIs were |
| backported using an external library, there are two packages that you can import to support USB |
| accessory mode. Depending on what Android-powered devices you want to support, you might have to |
| use one over the other:</p> |
| |
| <ul> |
| <li><code>com.android.future.usb</code>: To support USB accessory mode in Android 2.3.4, the |
| <a href="http://code.google.com/android/add-ons/google-apis/index.html">Google APIs add-on |
| library</a> includes the backported USB accessory APIs and they are contained in this |
| namespace. Android 3.1 also supports importing and calling the classes within this namespace to |
| support applications written with the add-on library. This add-on library is a thin wrapper |
| around the {@link android.hardware.usb} accessory APIs and does not support USB host mode. If |
| you want to support the widest range of devices that support USB accessory mode, use the add-on |
| library and import this package. It is important to note that not all Android 2.3.4 devices are |
| required to support the USB accessory feature. Each individual device manufacturer decides |
| whether or not to support this capability, which is why you must declare it in your manifest |
| file.</li> |
| |
| <li>{@link android.hardware.usb}: This namespace contains the classes that support USB |
| accessory mode in Android 3.1. This package is included as part of the framework APIs, so |
| Android 3.1 supports USB accessory mode without the use of an add-on library. Use this package |
| if you only care about Android 3.1 or newer devices that have hardware support for USB |
| accessory mode, which you can declare in your manifest file.</li> |
| </ul> |
| |
| <h3 id="installing">Installing the Google APIs add-on library</h3> |
| |
| <p>If you want to install the add-on, you can do so by installing the Google APIs Android API 10 |
| package with the SDK Manager. See <a href= |
| "http://code.google.com/android/add-ons/google-apis/installing.html">Installing the Google APIs |
| Add-on</a> for more information on installing the add-on library.</p> |
| |
| <h2 id="api">API Overview</h2> |
| |
| <p>Because the add-on library is a wrapper for the framework APIs, the classes that support the |
| USB accessory feature are similar. You can use the reference documentation for the {@link |
| android.hardware.usb} even if you are using the add-on library.</p> |
| |
| <p class="note"><strong>Note:</strong> There is, however, a minor <a href="#usage">usage |
| difference</a> between the add-on library and framework APIs that you should be aware of.</p> |
| |
| <p>The following table describes the classes that support the USB accessory APIs:</p> |
| |
| <table> |
| <tr> |
| <th>Class</th> |
| |
| <th>Description</th> |
| </tr> |
| |
| <tr> |
| <td>{@link android.hardware.usb.UsbManager}</td> |
| |
| <td>Allows you to enumerate and communicate with connected USB accessories.</td> |
| </tr> |
| |
| <tr> |
| <td>{@link android.hardware.usb.UsbAccessory}</td> |
| |
| <td>Represents a USB accessory and contains methods to access its identifying |
| information.</td> |
| </tr> |
| </table> |
| |
| <h3 id="usage">Usage differences between the add-on library and platform APIs</h3> |
| |
| <p>There are two usage differences between using the Google APIs add-on library and the platform |
| APIs.</p> |
| |
| <p>If you are using the add-on library, you must obtain the {@link |
| android.hardware.usb.UsbManager} object in the following manner:</p> |
| <pre> |
| UsbManager manager = UsbManager.getInstance(this); |
| </pre> |
| |
| <p>If you are not using the add-on library, you must obtain the {@link |
| android.hardware.usb.UsbManager} object in the following manner:</p> |
| <pre> |
| UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); |
| </pre> |
| |
| <p>When you filter for a connected accessory with an intent filter, the {@link |
| android.hardware.usb.UsbAccessory} object is contained inside the intent that is passed to your |
| application. If you are using the add-on library, you must obtain the {@link |
| android.hardware.usb.UsbAccessory} object in the following manner:</p> |
| <pre> |
| UsbAccessory accessory = UsbManager.getAccessory(intent); |
| </pre> |
| |
| <p>If you are not using the add-on library, you must obtain the {@link |
| android.hardware.usb.UsbAccessory} object in the following manner:</p> |
| <pre> |
| UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); |
| </pre> |
| |
| <h2 id="manifest">Android Manifest requirements</h2> |
| |
| <p>The following list describes what you need to add to your application's manifest file before |
| working with the USB accesory APIs. The <a href="#manifest-example">manifest and resource file |
| examples</a> show how to declare these items:</p> |
| |
| <ul> |
| <li>Because not all Android-powered devices are guaranteed to support the USB accessory APIs, |
| include a <code><uses-feature></code> element that declares that your application uses |
| the <code>android.hardware.usb.accessory</code> feature.</li> |
| |
| <li>If you are using the |
| <a href="http://code.google.com/android/add-ons/google-apis/index.html">add-on library</a>, |
| add the <code><uses-library></code> element specifying |
| <code>com.android.future.usb.accessory</code> for the library.</li> |
| |
| <li>Set the minimum SDK of the application to API Level 10 if you are using the add-on library |
| or 12 if you are using the {@link android.hardware.usb} package.</li> |
| |
| <li> |
| <p>If you want your application to be notified of an attached USB accessory, specify an |
| <code><intent-filter></code> and <code><meta-data></code> element pair for the |
| <code>android.hardware.usb.action.USB_ACCESSORY_ATTACHED</code> intent in your main activity. |
| The <code><meta-data></code> element points to an external XML resource file that |
| declares identifying information about the accessory that you want to detect.</p> |
| |
| <p>In the XML resource file, declare <code><usb-accessory></code> elements for the |
| accessories that you want to filter. Each <code><usb-accessory></code> can have the |
| following attributes:</p> |
| |
| <ul> |
| <li><code>manufacturer</code></li> |
| |
| <li><code>model</code></li> |
| |
| <li><code>version</code></li> |
| </ul> |
| |
| <p>Save the resource file in the <code>res/xml/</code> directory. The resource file name |
| (without the .xml extension) must be the same as the one you specified in the |
| <code><meta-data></code> element. The format for the XML resource file is also shown in |
| the <a href="#example">example</a> below.</p> |
| </li> |
| </ul> |
| |
| <h3 id="manifest-example">Manifest and resource file examples</h3> |
| |
| <p>The following example shows a sample manifest and its corresponding resource file:</p> |
| <pre> |
| <manifest ...> |
| <uses-feature android:name="android.hardware.usb.accessory" /> |
| <!-- version must be either 10 or 12 --> |
| <uses-sdk android:minSdkVersion="<<em>version</em>>" /> |
| ... |
| <application> |
| <uses-library android:name="com.android.future.usb.accessory" /> |
| <activity ...> |
| ... |
| <intent-filter> |
| <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" /> |
| </intent-filter> |
| |
| <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" |
| android:resource="@xml/accessory_filter" /> |
| </activity> |
| </application> |
| </manifest> |
| </pre> |
| |
| <p>In this case, the following resource file should be saved in |
| <code>res/xml/accessory_filter.xml</code> and specifies that any accessory that has the |
| corresponding model, manufacturer, and version should be filtered. The accessory sends these |
| attributes the Android-powered device:</p> |
| <pre> |
| <?xml version="1.0" encoding="utf-8"?> |
| |
| <resources> |
| <usb-accessory model="DemoKit" manufacturer="Google" version="1.0"/> |
| </resources> |
| </pre> |
| |
| <h2 id="working-a">Working with Accessories</h2> |
| |
| <p>When users connect USB accessories to an Android-powered device, the Android system can |
| determine whether your application is interested in the connected accessory. If so, you can set |
| up communication with the accessory if desired. To do this, your application has to:</p> |
| |
| <ol> |
| <li>Discover connected accessories by using an intent filter that filters for accessory |
| attached events or by enumerating connected accessories and finding the appropriate one.</li> |
| |
| <li>Ask the user for permission to communicate with the accessory, if not already |
| obtained.</li> |
| |
| <li>Communicate with the accessory by reading and writing data on the appropriate interface |
| endpoints.</li> |
| </ol> |
| |
| <h3 id="discovering-a">Discovering an accessory</h3> |
| |
| <p>Your application can discover accessories by either using an intent filter to be notified when |
| the user connects an accessory or by enumerating accessories that are already connected. Using an |
| intent filter is useful if you want to be able to have your application automatically detect a |
| desired accessory. Enumerating connected accessories is useful if you want to get a list of all |
| connected accessories or if your application did not filter for an intent.</p> |
| |
| <h4 id="discover-a-intent">Using an intent filter</h4> |
| |
| <p>To have your application discover a particular USB accessory, you can specify an intent filter |
| to filter for the <code>android.hardware.usb.action.USB_ACCESSORY_ATTACHED</code> intent. Along |
| with this intent filter, you need to specify a resource file that specifies properties of the USB |
| accessory, such as manufacturer, model, and version. When users connect an accessory that matches |
| your accessory filter,</p> |
| |
| <p>The following example shows how to declare the intent filter:</p> |
| <pre> |
| <activity ...> |
| ... |
| <intent-filter> |
| <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" /> |
| </intent-filter> |
| |
| <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" |
| android:resource="@xml/accessory_filter" /> |
| </activity> |
| </pre> |
| |
| <p>The following example shows how to declare the corresponding resource file that specifies the |
| USB accessories that you're interested in:</p> |
| <pre> |
| <?xml version="1.0" encoding="utf-8"?> |
| |
| <resources> |
| <usb-accessory manufacturer="Google, Inc." model="DemoKit" version="1.0" /> |
| </resources> |
| </pre> |
| |
| <p>In your activity, you can obtain the {@link android.hardware.usb.UsbAccessory} that represents |
| the attached accessory from the intent like this (with the add-on library):</p> |
| <pre> |
| UsbAccessory accessory = UsbManager.getAccessory(intent); |
| </pre> |
| |
| <p>or like this (with the platform APIs):</p> |
| <pre> |
| UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); |
| </pre> |
| |
| <h4 id="discover-a-enumerate">Enumerating accessories</h4> |
| |
| <p>You can have your application enumerate accesories that have identified themselves while your |
| application is running.</p> |
| |
| <p>Use the {@link android.hardware.usb.UsbManager#getAccessoryList() getAccessoryList()} method |
| to get an array all the USB accessories that are connected:</p> |
| <pre> |
| UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); |
| UsbAccessory[] accessoryList = manager.getAcccessoryList(); |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> Currently, only one connected accessory is supported at |
| one time, but the API is designed to support multiple accessories in the future.</p> |
| |
| <h3 id="permission-a">Obtaining permission to communicate with an accessory</h3> |
| |
| <p>Before communicating with the USB accessory, your applicaton must have permission from your |
| users.</p> |
| |
| <p class="note"><strong>Note:</strong> If your application <a href="#using-intents">uses an |
| intent filter</a> to discover accessories as they're connected, it automatically receives |
| permission if the user allows your application to handle the intent. If not, you must request |
| permission explicitly in your application before connecting to the accessory.</p> |
| |
| <p>Explicitly asking for permission might be neccessary in some situations such as when your |
| application enumerates accessories that are already connected and then wants to communicate with |
| one. You must check for permission to access an accessory before trying to communicate with it. |
| If not, you will receive a runtime error if the user denied permission to access the |
| accessory.</p> |
| |
| <p>To explicitly obtain permission, first create a broadcast receiver. This receiver listens for |
| the intent that gets broadcast when you call {@link |
| android.hardware.usb.UsbManager#requestPermission requestPermission()}. The call to {@link |
| android.hardware.usb.UsbManager#requestPermission requestPermission()} displays a dialog to the |
| user asking for permission to connect to the accessory. The following sample code shows how to |
| create the broadcast receiver:</p> |
| <pre> |
| private static final String ACTION_USB_PERMISSION = |
| "com.android.example.USB_PERMISSION"; |
| private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { |
| |
| public void onReceive(Context context, Intent intent) { |
| String action = intent.getAction(); |
| if (ACTION_USB_PERMISSION.equals(action)) { |
| synchronized (this) { |
| UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); |
| |
| if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { |
| if(accessory != null){ |
| //call method to set up accessory communication |
| } |
| } |
| else { |
| Log.d(TAG, "permission denied for accessory " + accessory); |
| } |
| } |
| } |
| } |
| }; |
| </pre> |
| |
| <p>To register the broadcast receiver, put this in your <code>onCreate()</code> method in your |
| activity:</p> |
| <pre> |
| UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); |
| private static final String ACTION_USB_PERMISSION = |
| "com.android.example.USB_PERMISSION"; |
| ... |
| mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); |
| IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); |
| registerReceiver(mUsbReceiver, filter); |
| </pre> |
| |
| <p>To display the dialog that asks users for permission to connect to the accessory, call the |
| {@link android.hardware.usb.UsbManager#requestPermission requestPermission()} method:</p> |
| <pre> |
| UsbAccessory accessory; |
| ... |
| mUsbManager.requestPermission(accessory, mPermissionIntent); |
| </pre> |
| |
| <p>When users reply to the dialog, your broadcast receiver receives the intent that contains the |
| {@link android.hardware.usb.UsbManager#EXTRA_PERMISSION_GRANTED} extra, which is a boolean |
| representing the answer. Check this extra for a value of true before connecting to the |
| accessory.</p> |
| |
| <h3 id="communicating-a">Communicating with an accessory</h3> |
| |
| <p>You can communicate with the accessory by using the {@link android.hardware.usb.UsbManager} to |
| obtain a file descriptor that you can set up input and output streams to read and write data to |
| descriptor. The streams represent the accessory's input and output bulk endpoints. You should set |
| up the communication between the device and accessory in another thread, so you don't lock the |
| main UI thread. The following example shows how to open an accessory to communicate with:</p> |
| <pre> |
| UsbAccessory mAccessory; |
| ParcelFileDescriptor mFileDescriptor; |
| FileInputStream mInputStream; |
| FileOutputStream mOutputStream; |
| |
| ... |
| |
| private void openAccessory() { |
| Log.d(TAG, "openAccessory: " + accessory); |
| mFileDescriptor = mUsbManager.openAccessory(mAccessory); |
| if (mFileDescriptor != null) { |
| FileDescriptor fd = mFileDescriptor.getFileDescriptor(); |
| mInputStream = new FileInputStream(fd); |
| mOutputStream = new FileOutputStream(fd); |
| Thread thread = new Thread(null, this, "AccessoryThread"); |
| thread.start(); |
| } |
| } |
| </pre> |
| |
| <p>In the thread's <code>run()</code> method, you can read and write to the accessory by using |
| the {@link java.io.FileInputStream} or {@link java.io.FileOutputStream} objects. When reading |
| data from an accessory with a {@link java.io.FileInputStream} object, ensure that the buffer that |
| you use is big enough to store the USB packet data. The Android accessory protocol supports |
| packet buffers up to 16384 bytes, so you can choose to always declare your buffer to be of this |
| size for simplicity.</p> |
| |
| <p class="note"><strong>Note:</strong> At a lower level, the packets are 64 bytes for USB |
| full-speed accessories and 512 bytes for USB high-speed accessories. The Android accessory |
| protocol bundles the packets together for both speeds into one logical packet for simplicity.</p> |
| |
| <p>For more information about using threads in Android, see <a href= |
| "{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes and |
| Threads</a>.</p> |
| |
| <h3 id="terminating-a">Terminating communication with an accessory</h3> |
| |
| <p>When you are done communicating with an accessory or if the accessory was detached, close the |
| file descriptor that you opened by calling {@link android.os.ParcelFileDescriptor#close close()}. |
| To listen for detached events, create a broadcast receiver like below:</p> |
| <pre> |
| BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { |
| public void onReceive(Context context, Intent intent) { |
| String action = intent.getAction(); |
| |
| if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) { |
| UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); |
| if (accessory != null) { |
| // call your method that cleans up and closes communication with the accessory |
| } |
| } |
| } |
| }; |
| </pre> |
| |
| <p>Creating the broadcast receiver within the application, and not the manifest, allows your |
| application to only handle detached events while it is running. This way, detached events are |
| only sent to the application that is currently running and not broadcast to all applications.</p> |
| |