diff options
-rw-r--r-- | docs/html/guide/guide_toc.cs | 12 | ||||
-rw-r--r-- | docs/html/guide/topics/usb/accessory.jd | 461 | ||||
-rw-r--r-- | docs/html/guide/topics/usb/host.jd | 443 | ||||
-rw-r--r-- | docs/html/guide/topics/usb/index.jd | 67 | ||||
-rw-r--r-- | docs/html/images/usb-host-accessory.png | bin | 0 -> 47143 bytes |
5 files changed, 982 insertions, 1 deletions
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 46763c2..5b8aa7a 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -301,6 +301,17 @@ <li><a href="<?cs var:toroot?>guide/topics/nfc/index.html"> <span class="en">Near Field Communication</span></a> <span class="new">new!</span></li> + <li class="toggle-list"> + <div><a href="<?cs var:toroot?>guide/topics/usb/index.html"> + <span class="en">USB</span></a> + <span class="new">new!</span> + </div> + <ul> + <li><a href="<?cs var:toroot ?>guide/topics/usb/accessory.html">Accessory</a></li> + <li><a href="<?cs var:toroot ?>guide/topics/usb/host.html">Host</a></li> + </ul> + </li> + <li><a href="<?cs var:toroot?>guide/topics/network/sip.html"> <span class="en">Session Initiation Protocol</span></a> <span class="new">new!</span> @@ -347,7 +358,6 @@ <a href="<?cs var:toroot ?>guide/topics/testing/what_to_test.html"> <span class="en">What To Test</span></a> </li> - </ul> </li> </ul> diff --git a/docs/html/guide/topics/usb/accessory.jd b/docs/html/guide/topics/usb/accessory.jd new file mode 100644 index 0000000..7638e30 --- /dev/null +++ b/docs/html/guide/topics/usb/accessory.jd @@ -0,0 +1,461 @@ +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><a href="http://accessories.android.com/demokit">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</a> <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="addon">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> + diff --git a/docs/html/guide/topics/usb/host.jd b/docs/html/guide/topics/usb/host.jd new file mode 100644 index 0000000..942708d --- /dev/null +++ b/docs/html/guide/topics/usb/host.jd @@ -0,0 +1,443 @@ +page.title=USB Host +@jd:body + + <div id="qv-wrapper"> + <div id="qv"> + <h2>In this document</h2> + + <ol> + <li><a href="#api">API Overview</a></li> + + <li><a href="#usage">Android Manifest Requirements</a></li> + + <li> + <a href="#working-d">Working with devices</a> + + <ol> + <li><a href="#discovering-d">Discovering a device</a></li> + + <li><a href="#permission-d">Obtaining permission to communicate with a device</a></li> + + <li><a href="#communicating-d">Communicating with a device</a></li> + + <li><a href="#terminating-d">Terminating communication with a device</a></li> + </ol> + </li> + </ol> + + <h2>Related Samples</h2> + + <ol> + <li><a href="{@docRoot}resources/samples/USB/AdbTest/index.html">AdbTest</a></li> + + <li><a href= + "{@docRoot}resources/samples/USB/MissileLauncher/index.html">MissleLauncher</a></li> + </ol> + </div> + </div> + + <p>When your Android-powered device is in USB host mode, it acts as the USB host, powers the bus, + and enumerates connected USB devices. USB host mode is supported in Android 3.1 and higher.</p> + + <h2 id="api">API Overview</h2> + + <p>Before you begin, it is important to understand the classes that you need to work with. The + following table describes the USB host APIs in the {@link android.hardware.usb} package.</p> + + <p class="table-caption"><strong>Table 1.</strong> USB Host 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 devices.</td> + </tr> + + <tr> + <td>{@link android.hardware.usb.UsbDevice}</td> + + <td>Represents a connected USB device and contains methods to access its identifying + information, interfaces, and endpoints.</td> + </tr> + + <tr> + <td>{@link android.hardware.usb.UsbInterface}</td> + + <td>Represents an interface of a USB device, which defines a set of functionality for the + device. A device can have one or more interfaces on which to communicate on.</td> + </tr> + + <tr> + <td>{@link android.hardware.usb.UsbEndpoint}</td> + + <td>Represents an interface endpoint, which is a communication channel for this interface. An + interface can have one or more endpoints, and usually has input and output endpoints for + two-way communication with the device.</td> + </tr> + + <tr> + <td>{@link android.hardware.usb.UsbDeviceConnection}</td> + + <td>Represents a connection to the device, which transfers data on endpoints. This class + allows you to send data back and forth sychronously or asynchronously.</td> + </tr> + + <tr> + <td>{@link android.hardware.usb.UsbRequest}</td> + + <td>Represents an asynchronous request to communicate with a device through a {@link + android.hardware.usb.UsbDeviceConnection}.</td> + </tr> + + <tr> + <td>{@link android.hardware.usb.UsbConstants}</td> + + <td>Defines USB constants that correspond to definitions in linux/usb/ch9.h of the Linux + kernel.</td> + </tr> + </table> + + <p>In most situations, you need to use all of these classes ({@link + android.hardware.usb.UsbRequest} is only required if you are doing asynchronous communication) + when communicating with a USB device. In general, you obtain a {@link + android.hardware.usb.UsbManager} to retrieve the desired {@link android.hardware.usb.UsbDevice}. + When you have the device, you need to find the appropriate {@link + android.hardware.usb.UsbInterface} and the {@link android.hardware.usb.UsbEndpoint} of that + interface to communicate on. Once you obtain the correct endpoint, open a {@link + android.hardware.usb.UsbDeviceConnection} to communicate with the USB device.</p> + + <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 host APIs:</p> + + <ul> + <li>Because not all Android-powered devices are guaranteed to support the USB host APIs, + include a <code><uses-feature></code> element that declares that your application uses + the <code>android.hardware.usb.host</code> feature.</li> + + <li>Set the minimum SDK of the application to API Level 12 or higher. The USB host APIs are not + present on earlier API levels.</li> + + <li>If you want your application to be notified of an attached USB device, specify an + <code><intent-filter></code> and <code><meta-data></code> element pair for the + <code>android.hardware.usb.action.USB_DEVICE_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 device that you want to detect. + + <p>In the XML resource file, declare <code><usb-device></code> elements for the USB + devices that you want to filter. The following list describes the attributes of + <code><usb-device></code>. In general, use vendor and product ID if you want to filter + for a specific device and use class, subclass, and protocol if you want to filter for a group + of USB devices, such as mass storage devices or digital cameras.</p> + + <ul> + <li><code>vendor-id</code></li> + + <li><code>product-id</code></li> + + <li><code>class</code></li> + + <li><code>subclass</code></li> + + <li><code>protocol</code> (device or interface)</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 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.host" /> + <uses-sdk android:minSdkVersion="12" /> + ... + <application> + <activity ...> + ... + <intent-filter> + <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> + </intent-filter> + + <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" + android:resource="@xml/device_filter" /> + </activity> + </application> +</manifest> +</pre> + + <p>In this case, the following resource file should be saved in + <code>res/xml/device_filter.xml</code> and specifies that any USB device with the corresponding + vendor ID and product ID should be filtered. These IDs are specific to the device and are + specified by the device's manufacturer:</p> + <pre> +<?xml version="1.0" encoding="utf-8"?> + +<resources> + <usb-device vendor-id="1234" product-id="5678" /> +</resources> +</pre> + + <h2 id="working-d">Working with Devices</h2> + + <p>When users connect USB devices to an Android-powered device, the Android system can determine + whether your application is interested in the connected device. If so, you can set up + communication with the device if desired. To do this, your application has to:</p> + + <ol> + <li>Discover connected USB devices by using an intent filter to be notified when the user + connects a USB device or by enumerating USB devices that are already connected.</li> + + <li>Ask the user for permission to connect to the USB device, if not already obtained.</li> + + <li>Communicate with the USB device by reading and writing data on the appropriate interface + endpoints.</li> + </ol> + + <h3 id="discovering-d">Discovering a device</h3> + + <p>Your application can discover USB devices by either using an intent filter to be notified when + the user connects a device or by enumerating USB devices that are already connected. Using an + intent filter is useful if you want to be able to have your application automatically detect a + desired device. Enumerating connected USB devices is useful if you want to get a list of all + connected devices or if your application did not filter for an intent.</p> + + <h4 id="using-intents">Using an intent filter</h4> + + <p>To have your application discover a particular USB device, you can specify an intent filter to + filter for the <code>android.hardware.usb.action.USB_DEVICE_ATTACHED</code> intent. Along with + this intent filter, you need to specify a resource file that specifies properties of the USB + device, such as product and vendor ID. When users connect a device that matches your device + filter, the system presents them with a dialog that asks if they want to start your application. + If users accept, your application automatically has permission to access the device until the + device is disconnected.</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_DEVICE_ATTACHED" /> + </intent-filter> + + <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" + android:resource="@xml/device_filter" /> +</activity> +</pre> + + <p>The following example shows how to declare the corresponding resource file that specifies the + USB devices that you're interested in:</p> + <pre> +<?xml version="1.0" encoding="utf-8"?> + +<resources> + <usb-device vendor-id="1234" product-id="5678" /> +</resources> +</pre><!-- REMEMBER TO ADD PROTOCOL, and device class and subclass, if applicable --> + + <p>In your activity, you can obtain the {@link android.hardware.usb.UsbDevice} that represents + the attached device from the intent like this:</p> + <pre> +UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); +</pre> + + <h4>Enumerating devices</h4> + + <p>If your application is interested in inspecting all of the USB devices currently connected + while your application is running, it can enumerate devices on the bus. Use the {@link + android.hardware.usb.UsbManager#getDeviceList() getDeviceList()} method to get a hash map of all + the USB devices that are connected. The hash map is keyed by the USB device's name if you want to + obtain a device from the map.</p> + <pre> +UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); +... +HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); +Iterator<UsbDevice> deviceIterator = deviceList.values().iterator(); +while(deviceIterator.hasNext()){ + UsbDevice device = deviceIterator.next(); + // your code +} +</pre> + + <p>If desired, you can also just obtain an iterator from the hash map and process each device one + by one:</p> + <pre> +UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); +... +HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); +Iterator<UsbDevice> deviceIterator = deviceList.values().iterator(); +while(deviceIterator.hasNext()){ + UsbDevice device = deviceIterator.next() + //your code +} +</pre> + + <h3 id="permission-d">Obtaining permission to communicate with a device</h3> + + <p>Before communicating with the USB device, 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 USB devices 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 device.</p> + + <p>Explicitly asking for permission might be neccessary in some situations such as when your + application enumerates USB devices that are already connected and then wants to communicate with + one. You must check for permission to access a device before trying to communicate with it. If + not, you will receive a runtime error if the user denied permission to access the device.</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 device. 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) { + UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + + if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { + if(device != null){ + //call method to set up device communication + } + } + else { + Log.d(TAG, "permission denied for device " + device); + } + } + } + } +}; +</pre> + + <p>To register the broadcast receiver, add 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 device, call the {@link + android.hardware.usb.UsbManager#requestPermission requestPermission()} method:</p> + <pre> +UsbDevice device; +... +mUsbManager.requestPermission(device, 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 + device.</p> + + <h3 id="communicating-d">Communicating with a device</h3> + + <p>Communication with a USB device can be either synchronous or asynchronous. In either case, you + should create a new thread on which to carry out all data transmissions, so you don't block the + UI thread. To properly set up communication with a device, you need to obtain the appropriate + {@link android.hardware.usb.UsbInterface} and {@link android.hardware.usb.UsbEndpoint} of the + device that you want to communicate on and send requests on this endpoint with a {@link + android.hardware.usb.UsbDeviceConnection}. In general, your code should:</p> + + <ul> + <li>Check a {@link android.hardware.usb.UsbDevice} object's attributes, such as product ID, + vendor ID, or device class to figure out whether or not you want to communicate with the + device.</li> + + <li>When you are certain that you want to communicate with the device, find the appropriate + {@link android.hardware.usb.UsbInterface} that you want to use to communicate along with the + appropriate {@link android.hardware.usb.UsbEndpoint} of that interface. Interfaces can have one + or more endpoints, and commonly will have an input and output endpoint for two-way + communication.</li> + + <li>When you find the correct endpoint, open a {@link android.hardware.usb.UsbDeviceConnection} + on that endpoint.</li> + + <li>Supply the data that you want to transmit on the endpoint with the {@link + android.hardware.usb.UsbDeviceConnection#bulkTransfer bulkTransfer()} or {@link + android.hardware.usb.UsbDeviceConnection#controlTransfer controlTransfer()} method. You should + carry out this step in another thread to prevent blocking the main UI thread. For more + information about using threads in Android, see <a href= + "{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes and + Threads</a>.</li> + </ul> + + <p>The following code snippet is a trivial way to do a synchronous data transfer. Your code + should have more logic to correctly find the correct interface and endpoints to communicate on + and also should do any transferring of data in a different thread than the main UI thread:</p> + <pre> +private Byte[] bytes +private static int TIMEOUT = 0; +private boolean forceClaim = true; + +... + +UsbInterface intf = device.getInterface(0); +UsbEndpoint endpoint = intf.getEndpoint(0); +UsbDeviceConnection connection = mUsbManager.openDevice(device); +connection.claimInterface(intf, forceClaim); +connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread +</pre> + + <p>To send data asynchronously, use the {@link android.hardware.usb.UsbRequest} class to {@link + android.hardware.usb.UsbRequest#initialize initialize} and {@link + android.hardware.usb.UsbRequest#queue queue} an asynchronous request, then wait for the result + with {@link android.hardware.usb.UsbDeviceConnection#requestWait requestWait()}.</p> + + <p>For more information, see the <a href= + "{@docRoot}resources/samples/USB/AdbTest/index.html">AdbTest sample</a>, which shows how to do + asynchronous bulk transfers, and the <a href= + "{@docRoot}resources/samples/USB/MissileLauncher/index.html">MissleLauncher sample</a>, which + shows how to listen on an interrupt endpoint asynchronously.</p> + + <h3 id="terminating-d">Terminating communication with a device</h3> + + <p>When you are done communicating with a device or if the device was detached, close the {@link + android.hardware.usb.UsbInterface} and {@link android.hardware.usb.UsbDeviceConnection} by + calling {@link android.hardware.usb.UsbDeviceConnection#releaseInterface releaseInterface()} and + {@link android.hardware.usb.UsbDeviceConnection#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_DEVICE_DETACHED.equals(action)) { + UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + if (device != null) { + // call your method that cleans up and closes communication with the device + } + } + } +}; +</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> + diff --git a/docs/html/guide/topics/usb/index.jd b/docs/html/guide/topics/usb/index.jd new file mode 100644 index 0000000..18af06a --- /dev/null +++ b/docs/html/guide/topics/usb/index.jd @@ -0,0 +1,67 @@ +page.title=USB Host and Accessory +@jd:body + + <div id="qv-wrapper"> + <div id="qv"> + <h2>Topics</h2> + + <ol> + <li><a href="{@docRoot}/guide/topics/USB/accessory.jd">USB Accessory</a></li> + + <li><a href="{@docRoot}/guide/topics/USB/host.jd">USB Host</a></li> + </ol> + </div> + </div> + + <p>Android supports a variety of USB peripherals and Android USB accessories (hardware that + implements the Android accessory protocol) through two modes: USB accessory and USB host. In USB + accessory mode, the external USB hardware act as the USB hosts. Examples of accessories might + include robotics controllers; docking stations; diagnostic and musical equipment; kiosks; card + readers; and much more. This gives Android-powered devices that do not have host capabilities the + ability to interact with USB hardware. Android USB accessories must be designed to work with + Android-powered devices and must adhere to the <a href= + "http://accessories.android.com/demokit">Android accessory communication protocol</a>. In USB + host mode, the Android-powered device acts as the host. Examples of devices include digital + cameras, keyboards, mice, and game controllers. USB devices that are designed for a wide range of + applications and environments can still interact with Android applications that can correctly + communicate with the device.</p> + + <p>Figure 1 shows the differences between the two modes. When the Android-powered device is in + host mode, it acts as the USB host and powers the bus. When the Android-powered device is in USB + accessory mode, the connected USB hardware (an Android USB accessory in this case) acts as the + host and powers the bus.</p><img src="{@docRoot}images/usb-host-accessory.png" alt=""> + + <p class="img-caption"><strong>Figure 1.</strong> USB Host and Accessory Modes</p> + + <p>USB accessory and host modes are directly supported in Android 3.1 (API level 12) or newer + platforms. USB accessory mode is also backported to Android 2.3.4 (API level 10) as an add-on + library to support a broader range of devices. Device manufacturers can choose whether or not to + include the add-on library on the device's system image.</p> + + <p class="note"><strong>Note:</strong> Support for USB host and accessory modes are ultimately + dependant on the device's hardware, regardless of platform level. You can filter for devices that + support USB host and accessory through a <a href= + "{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a> element. See + the USB <a href="{@docRoot}guide/topics/USB/accessory.html">accessory</a> and <a href= + "{@docRoot}guide/topics/USB/host.html">host</a> documentation for more details.</p> + + <h2>Debugging considerations</h2> + + <p>When debugging applications that use USB accessory or host features, you most likely will have + USB hardware connected to your Android-powered device. This will prevent you from having an + <code>adb</code> connection to the Android-powered device via USB. You can still access + <code>adb</code> over a network connection. To enable <code>adb</code> over a network + connection:</p> + + <ol> + <li>Connect the Android-powered device via USB to your computer.</li> + + <li>From your SDK <code>platform-tools/</code> directory, enter <code>adb tcpip 5555</code> at + the command prompt.</li> + + <li>Enter <code>adb connect <device-ip-address>:5555</code> You should now be connected + to the Android-powered device and can issue the usual <code>adb</code> commands like <code>adb + logcat</code>.</li> + + <li>To set your device to listen on USB, enter <code>adb usb</code>.</li> + </ol> diff --git a/docs/html/images/usb-host-accessory.png b/docs/html/images/usb-host-accessory.png Binary files differnew file mode 100644 index 0000000..f82fd6f --- /dev/null +++ b/docs/html/images/usb-host-accessory.png |