bluetooth.jd revision 33baa5ad7d8cdcc89ce4fbc3bc8cd537d5f5d639
1page.title=Bluetooth
2page.tags=wireless,bluetoothadapter,bluetoothdevice
3@jd:body
4
5<div id="qv-wrapper">
6<div id="qv">
7 
8  <h2>In this document</h2>
9  <ol> 
10    <li><a href="#TheBasics">The Basics</a></li>
11    <li><a href="#Permissions">Bluetooth Permissions</a></li>
12    <li><a href="#SettingUp">Setting Up Bluetooth</a></li> 
13    <li><a href="#FindingDevices">Finding Devices</a> 
14      <ol> 
15        <li><a href="#QueryingPairedDevices">Querying paired devices</a></li> 
16        <li><a href="#DiscoveringDevices">Discovering devices</a></li> 
17      </ol></li> 
18    <li><a href="#ConnectingDevices">Connecting Devices</a> 
19      <ol> 
20        <li><a href="#ConnectingAsAServer">Connecting as a server</a></li> 
21        <li><a href="#ConnectingAsAClient">Connecting as a client</a></li> 
22      </ol></li> 
23    <li><a href="#ManagingAConnection">Managing a Connection</a></li>
24    <li><a href="#Profiles">Working with Profiles</a> 
25      <ol>
26        <li><a href="#AT-Commands">Vendor-specific AT commands</a>
27        <li><a href="#HDP">Health Device Profile</a>
28      </ol></li>
29  </ol> 
30 
31  <h2>Key classes</h2> 
32  <ol> 
33    <li>{@link android.bluetooth.BluetoothAdapter}</li> 
34    <li>{@link android.bluetooth.BluetoothDevice}</li> 
35    <li>{@link android.bluetooth.BluetoothSocket}</li> 
36    <li>{@link android.bluetooth.BluetoothServerSocket}</li> 
37  </ol> 
38 
39  <h2>Related samples</h2> 
40  <ol> 
41    <li><a href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat</a></li> 
42    <li><a href="{@docRoot}resources/samples/BluetoothHDP/index.html">Bluetooth HDP (Health Device Profile)</a></li>
43  </ol> 
44 
45</div> 
46</div> 
47 
48 
49<p>The Android platform includes support for the Bluetooth network stack,
50which allows a device to wirelessly exchange data with other Bluetooth devices.
51The application framework provides access to the Bluetooth functionality through
52the Android Bluetooth APIs. These APIs let applications wirelessly
53connect to other Bluetooth devices, enabling point-to-point and multipoint
54wireless features.</p> 
55 
56<p>Using the Bluetooth APIs, an Android application can perform the
57following:</p>
58<ul>
59  <li>Scan for other Bluetooth devices</li>
60  <li>Query the local Bluetooth adapter for paired Bluetooth devices</li>
61  <li>Establish RFCOMM channels</li>
62  <li>Connect to other devices through service discovery</li>
63  <li>Transfer data to and from other devices</li>
64  <li>Manage multiple connections</li>
65</ul>
66
67<p>This document describes how to use <em>Classic Bluetooth</em>. Classic
68Bluetooth is the right choice for more battery-intensive operations such as streaming
69and communicating between Android devices. For Bluetooth devices with low power requirements,
70Android 4.3 (API Level 18) introduces API support for Bluetooth Low Energy. To learn more,
71see <a href="{@docRoot}guide/topics/connectivity/bluetooth-le.html">Bluetooth Low Energy</a>.</p>
72
73<h2 id="TheBasics">The Basics</h2>
74
75<p>This document describes how to use the Android Bluetooth APIs to accomplish
76the four major tasks necessary to communicate using Bluetooth: setting up
77Bluetooth, finding devices that are either paired or available in the local
78area, connecting devices, and transferring data between devices.</p> 
79 
80<p>All of the Bluetooth APIs are available in the {@link android.bluetooth}
81package. Here's a summary of the classes and interfaces you will need to create Bluetooth
82connections:</p> 
83 
84<dl> 
85<dt>{@link android.bluetooth.BluetoothAdapter}</dt> 
86<dd>Represents the local Bluetooth adapter (Bluetooth radio). The
87{@link android.bluetooth.BluetoothAdapter} is the entry-point for all Bluetooth
88interaction. Using this,
89you can discover other Bluetooth devices, query a list of bonded (paired)
90devices, instantiate a {@link android.bluetooth.BluetoothDevice} using a known
91MAC address, and create a {@link android.bluetooth.BluetoothServerSocket} to
92listen for communications
93from other devices.</dd> 
94 
95<dt>{@link android.bluetooth.BluetoothDevice}</dt> 
96<dd>Represents a remote Bluetooth device. Use this to request a connection
97with a remote device through a {@link android.bluetooth.BluetoothSocket} or
98query information about the
99device such as its name, address, class, and bonding state.</dd> 
100 
101<dt>{@link android.bluetooth.BluetoothSocket}</dt> 
102<dd>Represents the interface for a Bluetooth socket (similar to a TCP
103{@link java.net.Socket}). This is the connection point that allows
104an application to exchange data with another Bluetooth device via InputStream
105and OutputStream.</dd> 
106 
107<dt>{@link android.bluetooth.BluetoothServerSocket}</dt> 
108<dd>Represents an open server socket that listens for incoming requests
109(similar to a TCP {@link java.net.ServerSocket}). In order to connect two
110Android devices, one device must open a server socket with this class. When a
111remote Bluetooth device makes a connection request to the this device, the
112{@link android.bluetooth.BluetoothServerSocket} will return a connected {@link
113android.bluetooth.BluetoothSocket} when the
114connection is accepted.</dd> 
115 
116<dt>{@link android.bluetooth.BluetoothClass}</dt> 
117<dd>Describes the general characteristics and capabilities of a Bluetooth
118device. This is a read-only set of properties that define the device's major and
119minor device classes and its services. However, this does not reliably describe
120all Bluetooth profiles and services supported by the device, but is useful as a
121hint to the device type.</dd> 
122 
123<dt>{@link android.bluetooth.BluetoothProfile}</dt> <dd>An interface that
124represents a Bluetooth profile. A <em>Bluetooth profile</em> is a wireless
125interface specification for Bluetooth-based communication between devices. An
126example is the Hands-Free profile.  For more discussion of profiles, see <a
127href="#Profiles">Working with Profiles</a></dd> 
128
129<dt>{@link android.bluetooth.BluetoothHeadset}</dt> <dd>Provides support for
130Bluetooth headsets to be used with mobile phones. This includes both  Bluetooth
131Headset and Hands-Free (v1.5) profiles.</dd> 
132
133<dt>{@link android.bluetooth.BluetoothA2dp}</dt> <dd> Defines how high quality
134audio can be streamed from one device to another over a Bluetooth connection.
135"A2DP" stands for Advanced Audio Distribution Profile.</dd> 
136
137<dt>{@link android.bluetooth.BluetoothHealth}</dt>
138<dd> Represents a Health Device Profile proxy that controls the Bluetooth service.</dd>
139
140<dt>{@link android.bluetooth.BluetoothHealthCallback}</dt>
141
142<dd>An abstract class that you use to implement {@link
143android.bluetooth.BluetoothHealth} callbacks. You must extend this class and
144implement the callback methods to receive updates about changes in the
145application’s registration state and Bluetooth channel state.</dd>
146
147<dt>{@link android.bluetooth.BluetoothHealthAppConfiguration}</dt>
148
149<dd>Represents an application configuration that the Bluetooth Health third-party 
150application registers to communicate with a remote Bluetooth health
151device.</dd> 
152
153<dt>{@link android.bluetooth.BluetoothProfile.ServiceListener}</dt>
154
155<dd>An interface that notifies {@link android.bluetooth.BluetoothProfile} IPC
156clients when they have  been connected to or disconnected from the service (that
157is, the internal service that runs a particular profile). </dd>
158 
159</dl> 
160 
161 
162 
163 
164<h2 id="Permissions">Bluetooth Permissions</h2> 
165 
166<p>In order to use Bluetooth features in your application, you must declare
167the Bluetooth permission {@link android.Manifest.permission#BLUETOOTH}.
168You need this permission to perform any Bluetooth communication,
169such as requesting a connection, accepting a connection, and transferring data.</p>
170
171<p>If you want your app to initiate device discovery or manipulate Bluetooth
172settings, you must also declare the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
173permission. Most applications need this permission solely for the
174ability to discover local Bluetooth devices. The other abilities granted by this
175permission should not be used, unless the application is a "power manager" that
176will modify Bluetooth settings upon user request. <strong>Note:</strong> If you
177use {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission, then you must
178also have the {@link android.Manifest.permission#BLUETOOTH} permission.</p> 
179 
180<p>Declare the Bluetooth permission(s) in your application manifest file. For
181example:</p> 
182 
183<pre> 
184&lt;manifest ... >
185  &lt;uses-permission android:name="android.permission.BLUETOOTH" />
186  ...
187&lt;/manifest>
188</pre> 
189 
190<p>See the <a
191href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission></a> 
192reference for more information about declaring application permissions.</p> 
193 
194 
195<h2 id="SettingUp">Setting Up Bluetooth</h2> 
196 
197<div class="figure" style="width:200px"> 
198<img src="{@docRoot}images/bt_enable_request.png" /> 
199<strong>Figure 1:</strong> The enabling Bluetooth dialog.
200</div> 
201 
202<p>Before your application can communicate over Bluetooth, you need to verify
203that Bluetooth is supported on the device, and if so, ensure that it is enabled.</p> 
204 
205<p>If Bluetooth is not supported, then you should gracefully disable any
206Bluetooth features. If Bluetooth is supported, but disabled, then you can request that the
207user enable Bluetooth without leaving your application. This setup is
208accomplished in two steps, using the {@link android.bluetooth.BluetoothAdapter}.</p> 
209 
210 
211<ol> 
212<li>Get the {@link android.bluetooth.BluetoothAdapter}
213<p>The {@link android.bluetooth.BluetoothAdapter} is required for any and all Bluetooth
214activity. To get the {@link android.bluetooth.BluetoothAdapter}, call the static {@link
215android.bluetooth.BluetoothAdapter#getDefaultAdapter()} method. This returns a
216{@link android.bluetooth.BluetoothAdapter} that represents the device's own
217Bluetooth adapter (the Bluetooth radio). There's one Bluetooth adapter for the
218entire system, and your application can interact with it using this object. If
219{@link android.bluetooth.BluetoothAdapter#getDefaultAdapter()} returns null,
220then the device does not support Bluetooth and your story ends here. For example:</p> 
221<pre> 
222BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
223if (mBluetoothAdapter == null) {
224    // Device does not support Bluetooth
225}
226</pre> 
227</li> 
228 
229<li>Enable Bluetooth
230<p>Next, you need to ensure that Bluetooth is enabled. Call {@link
231android.bluetooth.BluetoothAdapter#isEnabled()} to check whether Bluetooth is
232currently enable. If this method returns false, then Bluetooth is disabled. To
233request that Bluetooth be enabled, call {@link
234android.app.Activity#startActivityForResult(Intent,int) startActivityForResult()}
235with the {@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_ENABLE} action Intent.
236This will issue a request to enable Bluetooth through the system settings (without
237stopping your application). For example:</p> 
238<pre> 
239if (!mBluetoothAdapter.isEnabled()) {
240    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
241    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
242}
243</pre> 
244 
245<p>A dialog will appear requesting user permission to enable Bluetooth, as shown
246in Figure 1. If the user responds "Yes," the system will begin to enable Bluetooth
247and focus will return to your application once the process completes (or fails).</p> 
248
249<p>The {@code REQUEST_ENABLE_BT} constant passed to {@link
250android.app.Activity#startActivityForResult(Intent,int) startActivityForResult()} is a locally
251defined integer (which must be greater than 0), that the system passes back to you in your
252{@link
253android.app.Activity#onActivityResult(int,int,Intent) onActivityResult()} implementation as the
254<code>requestCode</code> parameter.</p>
255
256<p>If enabling Bluetooth succeeds, your activity receives the {@link
257android.app.Activity#RESULT_OK} result code in the {@link
258android.app.Activity#onActivityResult(int,int,Intent) onActivityResult()}
259callback. If Bluetooth was not enabled
260due to an error (or the user responded "No") then the result code is {@link
261android.app.Activity#RESULT_CANCELED}.</p>
262</li> 
263</ol> 
264 
265<p>Optionally, your application can also listen for the
266{@link android.bluetooth.BluetoothAdapter#ACTION_STATE_CHANGED} broadcast Intent, which
267the system will broadcast whenever the Bluetooth state has changed. This broadcast contains
268the extra fields {@link android.bluetooth.BluetoothAdapter#EXTRA_STATE} and {@link
269android.bluetooth.BluetoothAdapter#EXTRA_PREVIOUS_STATE}, containing the new and old
270Bluetooth states, respectively. Possible values for these extra fields are
271{@link android.bluetooth.BluetoothAdapter#STATE_TURNING_ON}, {@link
272android.bluetooth.BluetoothAdapter#STATE_ON}, {@link
273android.bluetooth.BluetoothAdapter#STATE_TURNING_OFF}, and {@link
274android.bluetooth.BluetoothAdapter#STATE_OFF}. Listening for this
275broadcast can be useful to detect changes made to the Bluetooth state while your
276app is running.</p> 
277 
278<p class="note"><strong>Tip:</strong> Enabling discoverability will automatically
279enable Bluetooth. If you plan to consistently enable device discoverability before
280performing Bluetooth activity, you can skip
281step 2 above. Read about <a href="#EnablingDiscoverability">enabling discoverability</a>,
282below.</p> 
283 
284 
285<h2 id="FindingDevices">Finding Devices</h2> 
286 
287<p>Using the {@link android.bluetooth.BluetoothAdapter}, you can find remote Bluetooth
288devices either through device discovery or by querying the list of paired (bonded)
289devices.</p> 
290 
291<p>Device discovery is a scanning procedure that searches the local area for
292Bluetooth enabled devices and then requesting some information about each one
293(this is sometimes referred to as "discovering," "inquiring" or "scanning").
294However, a Bluetooth device within the local area will respond to a discovery
295request only if it is currently enabled to be discoverable. If a device is
296discoverable, it will respond to the discovery request by sharing some
297information, such as the device name, class, and its unique MAC address. Using
298this information, the device performing discovery can then choose to initiate a
299connection to the discovered device.</p> 
300 
301<p>Once a connection is made with a remote device for the first time, a pairing
302request is automatically presented to the user. When a device is
303paired, the basic information about that device (such as the device name, class,
304and MAC address) is saved and can be read using the Bluetooth APIs. Using the
305known MAC address for a remote device, a connection can be initiated with it at
306any time without performing discovery (assuming the device is within range).</p> 
307 
308<p>Remember there is a difference between being paired and being connected. To
309be paired means that two devices are aware of each other's existence, have a
310shared link-key that can be used for authentication, and are capable of
311establishing an encrypted connection with each other. To be connected means that
312the devices currently share an RFCOMM channel and are able to transmit data with
313each other. The current Android Bluetooth API's require devices to be paired
314before an RFCOMM connection can be established. (Pairing is automatically performed
315when you initiate an encrypted connection with the Bluetooth APIs.)</p> 
316 
317<p>The following sections describe how to find devices that have been paired, or
318discover new devices using device discovery.</p> 
319 
320<p class="note"><strong>Note:</strong> Android-powered devices are not
321discoverable by default. A user can make
322the device discoverable for a limited time through the system settings, or an
323application can request that the user enable discoverability without leaving the
324application. How to <a href="#EnablingDiscoverability">enable discoverability</a> 
325is discussed below.</p> 
326 
327 
328<h3 id="QueryingPairedDevices">Querying paired devices</h3> 
329 
330<p>Before performing device discovery, its worth querying the set
331of paired devices to see if the desired device is already known. To do so,
332call {@link android.bluetooth.BluetoothAdapter#getBondedDevices()}. This
333will return a Set of {@link android.bluetooth.BluetoothDevice}s representing
334paired devices. For example, you can query all paired devices and then
335show the name of each device to the user, using an ArrayAdapter:</p> 
336<pre> 
337Set&lt;BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
338// If there are paired devices
339if (pairedDevices.size() > 0) {
340    // Loop through paired devices
341    for (BluetoothDevice device : pairedDevices) {
342        // Add the name and address to an array adapter to show in a ListView
343        mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
344    }
345}
346</pre> 
347 
348<p>All that's needed from the {@link android.bluetooth.BluetoothDevice} object
349in order to initiate a connection is the MAC address. In this example, it's saved
350as a part of an ArrayAdapter that's shown to the user. The MAC address can later
351be extracted in order to initiate the connection. You can learn more about creating
352a connection in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p> 
353 
354 
355<h3 id="DiscoveringDevices">Discovering devices</h3> 
356 
357<p>To start discovering devices, simply call {@link
358android.bluetooth.BluetoothAdapter#startDiscovery()}. The
359process is asynchronous and the method will immediately return with a boolean
360indicating whether discovery has successfully started. The discovery process
361usually involves an inquiry scan of about 12 seconds, followed by a page scan of
362each found device to retrieve its Bluetooth name.</p> 
363 
364<p>Your application must register a BroadcastReceiver for the
365{@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent in
366order to receive information about each
367device discovered. For each device, the system will broadcast the
368{@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent. This
369Intent carries the extra fields
370{@link android.bluetooth.BluetoothDevice#EXTRA_DEVICE} and
371{@link android.bluetooth.BluetoothDevice#EXTRA_CLASS}, containing a
372{@link android.bluetooth.BluetoothDevice} and a {@link
373android.bluetooth.BluetoothClass}, respectively. For example, here's how you can
374register to handle the broadcast when devices are discovered:</p> 
375<pre> 
376// Create a BroadcastReceiver for ACTION_FOUND
377private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
378    public void onReceive(Context context, Intent intent) {
379        String action = intent.getAction();
380        // When discovery finds a device
381        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
382            // Get the BluetoothDevice object from the Intent
383            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
384            // Add the name and address to an array adapter to show in a ListView
385            mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
386        }
387    }
388};
389// Register the BroadcastReceiver
390IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
391registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
392</pre> 
393 
394<p>All that's needed from the {@link android.bluetooth.BluetoothDevice} object
395in order to initiate a
396connection is the MAC address. In this example, it's saved as a part of an
397ArrayAdapter that's shown to the user. The MAC address can later be extracted in
398order to initiate the connection. You can learn more about creating a connection
399in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p> 
400 
401<p class="caution"><strong>Caution:</strong> Performing device discovery is
402a heavy procedure for the Bluetooth
403adapter and will consume a lot of its resources. Once you have found a device to
404connect, be certain that you always stop discovery with
405{@link android.bluetooth.BluetoothAdapter#cancelDiscovery()} before
406attempting a connection. Also, if you
407already hold a connection with a device, then performing discovery can
408significantly reduce the bandwidth available for the connection, so you should
409not perform discovery while connected.</p> 
410 
411<h4 id="EnablingDiscoverability">Enabling discoverability</h4> 
412 
413<p>If you would like to make the local device discoverable to other devices,
414call {@link android.app.Activity#startActivityForResult(Intent,int)} with the
415{@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_DISCOVERABLE} action
416Intent. This will issue a request to enable discoverable mode through the system
417settings (without stopping your application). By default, the device will become
418discoverable for 120 seconds. You can define a different duration by adding the
419{@link android.bluetooth.BluetoothAdapter#EXTRA_DISCOVERABLE_DURATION} Intent
420extra. The maximum duration an app can set is 3600 seconds, and a value of 0
421means the device is always discoverable. Any value below 0 or above 3600 is
422automatically set to 120 secs). For example, this snippet sets the duration to
423300:</p> 
424
425<pre>Intent discoverableIntent = new
426Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
427discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
428startActivity(discoverableIntent);
429</pre> 
430 
431<div class="figure" style="width:200px"> 
432<img src="{@docRoot}images/bt_enable_discoverable.png" /> 
433<strong>Figure 2:</strong> The enabling discoverability dialog.
434</div> 
435 
436<p>A dialog will be displayed, requesting user permission to make the device
437discoverable, as shown in Figure 2. If the user responds "Yes," then the device
438will become discoverable for the specified amount of time. Your activity will
439then receive a call to the {@link android.app.Activity#onActivityResult(int,int,Intent)
440onActivityResult())} callback, with the result code equal to the duration that the device
441is discoverable. If the user responded "No" or if an error occurred, the result code will
442be {@link android.app.Activity#RESULT_CANCELED}.</p> 
443 
444<p class="note"><strong>Note:</strong> If Bluetooth has not been enabled on the device,
445then enabling device discoverability will automatically enable Bluetooth.</p> 
446 
447<p>The device will silently remain in discoverable mode for the allotted time.
448If you would like to be notified when the discoverable mode has changed, you can
449register a BroadcastReceiver for the {@link
450android.bluetooth.BluetoothAdapter#ACTION_SCAN_MODE_CHANGED}
451Intent. This will contain the extra fields {@link
452android.bluetooth.BluetoothAdapter#EXTRA_SCAN_MODE} and
453{@link android.bluetooth.BluetoothAdapter#EXTRA_PREVIOUS_SCAN_MODE}, which tell you the
454new and old scan mode, respectively. Possible values for each are
455{@link android.bluetooth.BluetoothAdapter#SCAN_MODE_CONNECTABLE_DISCOVERABLE},
456{@link android.bluetooth.BluetoothAdapter#SCAN_MODE_CONNECTABLE}, or {@link
457android.bluetooth.BluetoothAdapter#SCAN_MODE_NONE},
458which indicate that the device is either in discoverable mode, not in
459discoverable mode but still able to receive connections, or not in discoverable
460mode and unable to receive connections, respectively.</p> 
461 
462<p>You do not need to enable device discoverability if you will be initiating
463the connection to a remote device. Enabling discoverability is only necessary when
464you want your application to host a server socket that will accept incoming
465connections, because the remote devices must be able to discover the device
466before it can initiate the connection.</p> 
467 
468 
469 
470<h2 id="ConnectingDevices">Connecting Devices</h2> 
471 
472<p>In order to create a connection between your application on two devices, you
473must implement both the server-side and client-side mechanisms, because one
474device must open a server socket and the other one must initiate the connection
475(using the server device's MAC address to initiate a connection). The server and
476client are considered connected to each other when they each have a connected
477{@link android.bluetooth.BluetoothSocket} on the same RFCOMM channel. At this
478point, each device can obtain input and output streams and data transfer can
479begin, which is discussed in the section about <a
480href="#ManagingAConnection">Managing a Connection</a>. This section describes how
481to initiate the connection between two devices.</p> 
482 
483<p>The server device and the client device each obtain the required {@link
484android.bluetooth.BluetoothSocket} in different ways. The server will receive it
485when an incoming connection is accepted. The client will receive it when it
486opens an RFCOMM channel to the server.</p> 
487 
488<div class="figure" style="width:200px"> 
489<img src="{@docRoot}images/bt_pairing_request.png" /> 
490<strong>Figure 3:</strong> The Bluetooth pairing dialog.
491</div> 
492 
493<p>One implementation technique is to automatically prepare each device as a
494server, so that each one has a server socket open and listening for connections.
495Then either device can initiate a connection with the other and become the
496client. Alternatively, one device can explicitly "host" the connection and open
497a server socket on demand and the other device can simply initiate the
498connection.</p> 
499 
500<p class="note"><strong>Note:</strong> If the two devices have not been previously paired,
501then the Android framework will automatically show a pairing request notification or
502dialog to the user during the connection procedure, as shown in Figure 3. So
503when attempting to connect devices,
504your application does not need to be concerned about whether or not the devices are
505paired. Your RFCOMM connection attempt will block until the user has successfully paired,
506or will fail if the user rejects pairing, or if pairing fails or times out. </p> 
507 
508 
509<h3 id="ConnectingAsAServer">Connecting as a server</h3> 
510 
511<p>When you want to connect two devices, one must act as a server by holding an
512open {@link android.bluetooth.BluetoothServerSocket}. The purpose of the server
513socket is to listen for incoming connection requests and when one is accepted,
514provide a connected {@link android.bluetooth.BluetoothSocket}. When the {@link
515android.bluetooth.BluetoothSocket} is acquired from the {@link
516android.bluetooth.BluetoothServerSocket},
517the {@link android.bluetooth.BluetoothServerSocket} can (and should) be
518discarded, unless you want to accept more connections.</p> 
519 
520<div class="sidebox-wrapper"> 
521<div class="sidebox"> 
522<h2>About UUID</h2> 
523 
524<p>A Universally Unique Identifier (UUID) is a standardized 128-bit format for a string
525ID used to uniquely identify information. The point of a UUID is that it's big
526enough that you can select any random and it won't clash. In this case, it's
527used to uniquely identify your application's Bluetooth service. To get a UUID to
528use with your application, you can use one of the many random UUID generators on
529the web, then initialize a {@link java.util.UUID} with {@link
530java.util.UUID#fromString(String)}.</p> 
531</div> 
532</div> 
533 
534<p>Here's the basic procedure to set up a server socket and accept a
535connection:</p> 
536 
537<ol> 
538<li>Get a {@link android.bluetooth.BluetoothServerSocket} by calling the
539{@link
540android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String,
541UUID)}.
542<p>The string is an identifiable name of your service, which the system will
543automatically write to a new Service Discovery Protocol (SDP) database entry on
544the device (the name is arbitrary and can simply be your application name). The
545UUID is also included in the SDP entry and will be the basis for the connection
546agreement with the client device. That is, when the client attempts to connect
547with this device, it will carry a UUID that uniquely identifies the service with
548which it wants to connect. These UUIDs must match in order for the connection to
549be accepted (in the next step).</p> 
550</li> 
551 
552<li>Start listening for connection requests by calling
553{@link android.bluetooth.BluetoothServerSocket#accept()}.
554<p>This is a blocking call. It will return when either a connection has been
555accepted or an exception has occurred. A connection is accepted only when a
556remote device has sent a connection request with a UUID matching the one
557registered with this listening server socket. When successful, {@link
558android.bluetooth.BluetoothServerSocket#accept()} will
559return a connected {@link android.bluetooth.BluetoothSocket}.</p> 
560</li> 
561 
562<li>Unless you want to accept additional connections, call
563{@link android.bluetooth.BluetoothServerSocket#close()}.
564<p>This releases the server socket and all its resources, but does <em>not</em> close the
565connected {@link android.bluetooth.BluetoothSocket} that's been returned by {@link
566android.bluetooth.BluetoothServerSocket#accept()}. Unlike TCP/IP, RFCOMM only allows one
567connected client per channel at a time, so in most cases it makes sense to call {@link
568android.bluetooth.BluetoothServerSocket#close()} on the {@link
569android.bluetooth.BluetoothServerSocket} immediately after accepting a connected
570socket.</p> 
571</li> 
572</ol> 
573 
574<p>The {@link android.bluetooth.BluetoothServerSocket#accept()} call should not
575be executed in the main activity UI thread because it is a blocking call and
576will prevent any other interaction with the application. It usually makes
577sense to do all work with a {@link android.bluetooth.BluetoothServerSocket} or {@link
578android.bluetooth.BluetoothSocket} in a new
579thread managed by your application. To abort a blocked call such as {@link
580android.bluetooth.BluetoothServerSocket#accept()}, call {@link
581android.bluetooth.BluetoothServerSocket#close()} on the {@link
582android.bluetooth.BluetoothServerSocket} (or {@link
583android.bluetooth.BluetoothSocket}) from another thread and the blocked call will
584immediately return. Note that all methods on a {@link
585android.bluetooth.BluetoothServerSocket} or {@link android.bluetooth.BluetoothSocket}
586are thread-safe.</p> 
587 
588<h4>Example</h4> 
589 
590<p>Here's a simplified thread for the server component that accepts incoming
591connections:</p> 
592<pre> 
593private class AcceptThread extends Thread {
594    private final BluetoothServerSocket mmServerSocket;
595 
596    public AcceptThread() {
597        // Use a temporary object that is later assigned to mmServerSocket,
598        // because mmServerSocket is final
599        BluetoothServerSocket tmp = null;
600        try {
601            // MY_UUID is the app's UUID string, also used by the client code
602            tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
603        } catch (IOException e) { }
604        mmServerSocket = tmp;
605    }
606 
607    public void run() {
608        BluetoothSocket socket = null;
609        // Keep listening until exception occurs or a socket is returned
610        while (true) {
611            try {
612                socket = mmServerSocket.accept();
613            } catch (IOException e) {
614                break;
615            }
616            // If a connection was accepted
617            if (socket != null) {
618                // Do work to manage the connection (in a separate thread)
619                manageConnectedSocket(socket);
620                mmServerSocket.close();
621                break;
622            }
623        }
624    }
625 
626    /** Will cancel the listening socket, and cause the thread to finish */
627    public void cancel() {
628        try {
629            mmServerSocket.close();
630        } catch (IOException e) { }
631    }
632}
633</pre> 
634 
635<p>In this example, only one incoming connection is desired, so as soon as a
636connection is accepted and the {@link android.bluetooth.BluetoothSocket} is
637acquired, the application
638sends the acquired {@link android.bluetooth.BluetoothSocket} to a separate
639thread, closes the
640{@link android.bluetooth.BluetoothServerSocket} and breaks the loop.</p> 
641 
642<p>Note that when {@link android.bluetooth.BluetoothServerSocket#accept()}
643returns the {@link android.bluetooth.BluetoothSocket}, the socket is already
644connected, so you should <em>not</em> call {@link
645android.bluetooth.BluetoothSocket#connect()} (as you do from the
646client-side).</p> 
647 
648<p><code>manageConnectedSocket()</code> is a fictional method in the application
649that will
650initiate the thread for transferring data, which is discussed in the section
651about <a href="#ManagingAConnection">Managing a Connection</a>.</p> 
652 
653<p>You should usually close your {@link android.bluetooth.BluetoothServerSocket}
654as soon as you are done listening for incoming connections. In this example, {@link
655android.bluetooth.BluetoothServerSocket#close()} is called as soon
656as the {@link android.bluetooth.BluetoothSocket} is acquired. You may also want
657to provide a public method in your thread that can close the private {@link
658android.bluetooth.BluetoothSocket} in the event that you need to stop listening on the
659server socket.</p> 
660 
661 
662<h3 id="ConnectingAsAClient">Connecting as a client</h3> 
663 
664<p>In order to initiate a connection with a remote device (a device holding an
665open
666server socket), you must first obtain a {@link
667android.bluetooth.BluetoothDevice} object that represents the remote device.
668(Getting a {@link android.bluetooth.BluetoothDevice} is covered in the above
669section about <a
670href="#FindingDevices">Finding Devices</a>.) You must then use the
671{@link android.bluetooth.BluetoothDevice} to acquire a {@link
672android.bluetooth.BluetoothSocket} and initiate the connection.</p> 
673 
674<p>Here's the basic procedure:</p> 
675 
676<ol> 
677<li>Using the {@link android.bluetooth.BluetoothDevice}, get a {@link
678android.bluetooth.BluetoothSocket} by calling {@link
679android.bluetooth.BluetoothDevice#createRfcommSocketToServiceRecord(UUID)}.
680<p>This initializes a {@link android.bluetooth.BluetoothSocket} that will
681connect to the {@link android.bluetooth.BluetoothDevice}. The UUID passed here
682must match the UUID used by the server device when it opened its
683{@link android.bluetooth.BluetoothServerSocket} (with {@link
684android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String,
685UUID)}). Using the same UUID is simply a matter of hard-coding the UUID string
686into your application and then referencing it from both the server and client
687code.</p> 
688</li> 
689 
690<li>Initiate the connection by calling {@link
691android.bluetooth.BluetoothSocket#connect()}.
692<p>Upon this call, the system will perform an SDP lookup on the remote device in
693order to match the UUID. If the lookup is successful and the remote device
694accepts the connection, it will share the RFCOMM channel to use during the
695connection and {@link
696android.bluetooth.BluetoothSocket#connect()} will return. This method is a
697blocking call. If, for
698any reason, the connection fails or the {@link
699android.bluetooth.BluetoothSocket#connect()} method times out (after about
70012 seconds), then it will throw an exception.</p> 
701<p>Because {@link
702android.bluetooth.BluetoothSocket#connect()} is a blocking call, this connection
703procedure should always be performed in a thread separate from the main activity
704thread.</p> 
705<p class="note">Note: You should always ensure that the device is not performing
706device discovery when you call {@link
707android.bluetooth.BluetoothSocket#connect()}. If discovery is in progress, then
708the
709connection attempt will be significantly slowed and is more likely to fail.</p> 
710</li> 
711</ol> 
712 
713<h4>Example</h4> 
714 
715<p>Here is a basic example of a thread that initiates a Bluetooth
716connection:</p> 
717<pre> 
718private class ConnectThread extends Thread {
719    private final BluetoothSocket mmSocket;
720    private final BluetoothDevice mmDevice;
721 
722    public ConnectThread(BluetoothDevice device) {
723        // Use a temporary object that is later assigned to mmSocket,
724        // because mmSocket is final
725        BluetoothSocket tmp = null;
726        mmDevice = device;
727 
728        // Get a BluetoothSocket to connect with the given BluetoothDevice
729        try {
730            // MY_UUID is the app's UUID string, also used by the server code
731            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
732        } catch (IOException e) { }
733        mmSocket = tmp;
734    }
735 
736    public void run() {
737        // Cancel discovery because it will slow down the connection
738        mBluetoothAdapter.cancelDiscovery();
739 
740        try {
741            // Connect the device through the socket. This will block
742            // until it succeeds or throws an exception
743            mmSocket.connect();
744        } catch (IOException connectException) {
745            // Unable to connect; close the socket and get out
746            try {
747                mmSocket.close();
748            } catch (IOException closeException) { }
749            return;
750        }
751 
752        // Do work to manage the connection (in a separate thread)
753        manageConnectedSocket(mmSocket);
754    }
755 
756    /** Will cancel an in-progress connection, and close the socket */
757    public void cancel() {
758        try {
759            mmSocket.close();
760        } catch (IOException e) { }
761    }
762}
763</pre> 
764 
765<p>Notice that {@link android.bluetooth.BluetoothAdapter#cancelDiscovery()} is called
766before the connection is made. You should always do this before connecting and it is safe
767to call without actually checking whether it is running or not (but if you do want to
768check, call {@link android.bluetooth.BluetoothAdapter#isDiscovering()}).</p> 
769 
770<p><code>manageConnectedSocket()</code> is a fictional method in the application
771that will initiate the thread for transferring data, which is discussed in the section
772about <a href="#ManagingAConnection">Managing a Connection</a>.</p> 
773 
774<p>When you're done with your {@link android.bluetooth.BluetoothSocket}, always
775call {@link android.bluetooth.BluetoothSocket#close()} to clean up.
776Doing so will immediately close the connected socket and clean up all internal
777resources.</p> 
778 
779 
780<h2 id="ManagingAConnection">Managing a Connection</h2> 
781 
782<p>When you have successfully connected two (or more) devices, each one will
783have a connected {@link android.bluetooth.BluetoothSocket}. This is where the fun
784begins because you can share data between devices. Using the {@link
785android.bluetooth.BluetoothSocket}, the general procedure to transfer arbitrary data is
786simple:</p> 
787<ol> 
788<li>Get the {@link java.io.InputStream} and {@link java.io.OutputStream} that
789handle transmissions through the socket, via {@link
790android.bluetooth.BluetoothSocket#getInputStream()} and
791{@link android.bluetooth.BluetoothSocket#getOutputStream}, respectively.</li> 
792 
793<li>Read and write data to the streams with {@link
794java.io.InputStream#read(byte[])} and {@link java.io.OutputStream#write(byte[])}.</li> 
795</ol> 
796 
797<p>That's it.</p> 
798 
799<p>There are, of course, implementation details to consider. First and foremost,
800you should use a dedicated thread for all stream reading and writing. This is
801important because both {@link java.io.InputStream#read(byte[])} and {@link
802java.io.OutputStream#write(byte[])} methods are blocking calls. {@link
803java.io.InputStream#read(byte[])} will block until there is something to read
804from the stream. {@link java.io.OutputStream#write(byte[])} does not usually
805block, but can block for flow control if the remote device is not calling {@link
806java.io.InputStream#read(byte[])} quickly enough and the intermediate buffers are full.
807So, your main loop in the thread should be dedicated to reading from the {@link
808java.io.InputStream}. A separate public method in the thread can be used to initiate
809writes to the {@link java.io.OutputStream}.</p> 
810 
811<h4>Example</h4> 
812 
813<p>Here's an example of how this might look:</p> 
814<pre> 
815private class ConnectedThread extends Thread {
816    private final BluetoothSocket mmSocket;
817    private final InputStream mmInStream;
818    private final OutputStream mmOutStream;
819 
820    public ConnectedThread(BluetoothSocket socket) {
821        mmSocket = socket;
822        InputStream tmpIn = null;
823        OutputStream tmpOut = null;
824 
825        // Get the input and output streams, using temp objects because
826        // member streams are final
827        try {
828            tmpIn = socket.getInputStream();
829            tmpOut = socket.getOutputStream();
830        } catch (IOException e) { }
831 
832        mmInStream = tmpIn;
833        mmOutStream = tmpOut;
834    }
835 
836    public void run() {
837        byte[] buffer = new byte[1024];  // buffer store for the stream
838        int bytes; // bytes returned from read()
839 
840        // Keep listening to the InputStream until an exception occurs
841        while (true) {
842            try {
843                // Read from the InputStream
844                bytes = mmInStream.read(buffer);
845                // Send the obtained bytes to the UI activity
846                mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
847                        .sendToTarget();
848            } catch (IOException e) {
849                break;
850            }
851        }
852    }
853 
854    /* Call this from the main activity to send data to the remote device */
855    public void write(byte[] bytes) {
856        try {
857            mmOutStream.write(bytes);
858        } catch (IOException e) { }
859    }
860 
861    /* Call this from the main activity to shutdown the connection */
862    public void cancel() {
863        try {
864            mmSocket.close();
865        } catch (IOException e) { }
866    }
867}
868</pre> 
869 
870<p>The constructor acquires the necessary streams and once executed, the thread
871will wait for data to come through the InputStream. When {@link
872java.io.InputStream#read(byte[])} returns with
873bytes from the stream, the data is sent to the main activity using a member
874Handler from the parent class. Then it goes back and waits for more bytes from
875the stream.</p> 
876 
877<p>Sending outgoing data is as simple as calling the thread's
878<code>write()</code> method from the main activity and passing in the bytes to
879be sent. This method then simply calls {@link
880java.io.OutputStream#write(byte[])} to send the data to the remote device.</p> 
881 
882<p>The thread's <code>cancel()</code> method is important so that the connection
883can be
884terminated at any time by closing the {@link android.bluetooth.BluetoothSocket}.
885This should always be called when you're done using the Bluetooth
886connection.</p> 
887 
888<div class="special"> 
889<p>For a  demonstration of using the Bluetooth APIs, see the <a
890href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat sample app</a>.</p> 
891</div> 
892
893<h2 id="Profiles">Working with Profiles</h2> 
894
895<p>Starting in Android 3.0, the Bluetooth API includes support for working with
896Bluetooth profiles. A <em>Bluetooth profile</em> is a wireless interface
897specification for Bluetooth-based communication between devices. An example
898is the Hands-Free profile. For a mobile phone to connect to a wireless headset,
899both devices must support the Hands-Free profile. </p> 
900
901<p>You can implement the interface {@link android.bluetooth.BluetoothProfile} to write
902your own classes to support a particular Bluetooth profile. The Android
903Bluetooth API provides implementations for the following Bluetooth
904profiles:</p> 
905<ul> 
906
907  <li><strong>Headset</strong>. The Headset profile provides support for
908Bluetooth headsets to be used with mobile phones. Android provides the {@link
909android.bluetooth.BluetoothHeadset} class, which is a proxy for controlling the
910Bluetooth Headset Service via interprocess communication (<a
911href="{@docRoot}guide/components/processes-and-threads.html#IPC">IPC</a
912>). This includes both  Bluetooth Headset and Hands-Free (v1.5) profiles. The
913{@link android.bluetooth.BluetoothHeadset} class includes support for AT commands.
914For more discussion of this topic, see <a href="#AT-Commands">Vendor-specific AT commands</a></li>
915
916  <li><strong>A2DP</strong>. The Advanced Audio Distribution Profile (A2DP)
917profile defines how high quality audio can be streamed from one device to
918another over a Bluetooth connection. Android provides the {@link
919android.bluetooth.BluetoothA2dp} class, which is a proxy for controlling
920the Bluetooth A2DP  Service via IPC.</li> 
921
922 <li><strong>Health Device</strong>. Android 4.0 (API level 14) introduces
923support for the Bluetooth Health Device Profile (HDP). This lets you create
924applications that use Bluetooth to communicate with health devices that support
925Bluetooth, such as heart-rate monitors, blood meters, thermometers, scales, and
926so on. For a list of supported devices and their corresponding device data
927specialization codes, refer to <strong>Bluetooth Assigned Numbers</strong> at <a
928href="http://www.bluetooth.org">www.bluetooth.org</a>. Note that these values
929are also referenced in the ISO/IEEE 11073-20601 [7] specification as
930MDC_DEV_SPEC_PROFILE_* in the Nomenclature Codes Annex. For more discussion of
931HDP, see <a href="#HDP">Health Device Profile</a>.</li> 
932
933</ul> 
934
935<p>Here are the basic steps for working with a profile:</p> 
936<ol> 
937
938  <li>Get the default adapter, as described in
939    <a href="{@docRoot}guide/topics/connectivity/bluetooth.html#SettingUp">Setting Up
940      Bluetooth</a>.</li> 
941
942  <li>Use {@link
943android.bluetooth.BluetoothAdapter#getProfileProxy(android.content.Context,
944android.bluetooth.BluetoothProfile.ServiceListener, int) getProfileProxy()} to
945establish a connection to the profile proxy object associated with the profile.
946In the example below, the profile proxy object is an instance of {@link
947android.bluetooth.BluetoothHeadset}. </li> 
948
949  <li>Set up a  {@link android.bluetooth.BluetoothProfile.ServiceListener}. This
950listener notifies {@link android.bluetooth.BluetoothProfile} IPC clients when
951they have been connected to or disconnected from the service.</li> 
952
953  <li>In {@link
954android.bluetooth.BluetoothProfile.ServiceListener#onServiceConnected(int,
955android.bluetooth.BluetoothProfile) onServiceConnected()}, get a handle
956to the profile proxy object.</li> 
957
958  <li>Once you have the profile proxy object, you can use it to monitor the
959state of the connection and perform other operations that are relevant to that
960profile.</li> 
961</ol> 
962
963<p> For example, this code snippet shows how to connect to a {@link
964android.bluetooth.BluetoothHeadset} proxy object so that you can control the
965Headset profile:</p> 
966
967<pre>BluetoothHeadset mBluetoothHeadset;
968 
969// Get the default adapter
970BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
971 
972// Establish connection to the proxy.
973mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
974 
975private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
976    public void onServiceConnected(int profile, BluetoothProfile proxy) {
977        if (profile == BluetoothProfile.HEADSET) {
978            mBluetoothHeadset = (BluetoothHeadset) proxy;
979        }
980    }
981    public void onServiceDisconnected(int profile) {
982        if (profile == BluetoothProfile.HEADSET) {
983            mBluetoothHeadset = null;
984        }
985    }
986};
987 
988// ... call functions on mBluetoothHeadset
989 
990// Close proxy connection after use.
991mBluetoothAdapter.closeProfileProxy(mBluetoothHeadset);
992</pre> 
993
994
995
996<h3 id="AT-Commands">Vendor-specific AT commands</h3> 
997
998<p>Starting in Android 3.0, applications can register to receive system
999broadcasts of pre-defined vendor-specific AT commands sent by headsets (such as
1000a Plantronics +XEVENT command). For example, an application could receive
1001broadcasts that indicate a connected device's battery level and could notify the
1002user or take other action as needed. Create a broadcast receiver for the {@link
1003android.bluetooth.BluetoothHeadset#ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intent
1004to handle vendor-specific AT commands for the headset.</p>
1005
1006<h3 id="HDP">Health Device Profile</h3>
1007
1008<p>Android 4.0 (API level 14) introduces support for the Bluetooth Health Device
1009Profile (HDP). This lets you create applications that use Bluetooth to
1010communicate with health devices that support Bluetooth, such as heart-rate
1011monitors, blood meters, thermometers, and scales. The Bluetooth Health API
1012includes the classes {@link android.bluetooth.BluetoothHealth}, {@link
1013android.bluetooth.BluetoothHealthCallback}, and {@link
1014android.bluetooth.BluetoothHealthAppConfiguration}, which are described in <a
1015href="#TheBasics">The Basics</a>. </p>
1016
1017<p>In using the Bluetooth Health API, it's helpful to understand these key HDP concepts:</p>
1018<table>
1019  <tr>
1020    <th>Concept</th>
1021    <th>Description</th>
1022  </tr>
1023  <tr>
1024    <td><strong>Source</strong></td>
1025
1026    <td>A role defined in HDP. A <em>source</em> is a  health device that
1027transmits medical data (weight scale, glucose meter, thermometer, etc.) to a
1028smart device such as an Android phone or tablet. </td>
1029  </tr>
1030  <tr>
1031    <td><strong>Sink</strong></td>
1032
1033    <td>A role defined in HDP. In HDP, a <em>sink</em> is the smart device that
1034receives the medical data. In an Android HDP application, the sink is
1035represented by a {@link android.bluetooth.BluetoothHealthAppConfiguration}
1036object.</td>
1037  </tr>
1038  <tr>
1039    <td><strong>Registration</strong></td>
1040    <td>Refers to registering a sink for a particular health device.</td>
1041  </tr>
1042  <tr>
1043    <td><strong>Connection</strong></td>
1044
1045    <td>Refers to opening a channel between a health device and a smart device
1046such as an Android phone or tablet.</td>
1047  </tr>
1048</table>
1049
1050<h4>Creating an HDP Application</h4>
1051
1052<p>Here are the basic steps involved in creating an Android HDP application:</p>
1053<ol>
1054
1055  <li>Get a reference to the {@link android.bluetooth.BluetoothHealth} proxy
1056object. <p>Similar to regular headset and A2DP profile devices, you must call
1057{@link android.bluetooth.BluetoothAdapter#getProfileProxy getProfileProxy()}
1058with a {@link android.bluetooth.BluetoothProfile.ServiceListener} and the {@link
1059android.bluetooth.BluetoothProfile.ServiceListener#HEALTH} profile type to
1060establish a connection with the profile proxy object.</p> </li>
1061
1062  <li>Create a {@link android.bluetooth.BluetoothHealthCallback} and register an
1063application configuration 
1064({@link android.bluetooth.BluetoothHealthAppConfiguration})
1065that acts as a health
1066sink.</li>
1067
1068  <li>Establish a connection to a health device.  Some devices will initiate the
1069connection.  It is unnecessary to carry out this step for those devices.</li>
1070
1071  <li>When connected successfully to a health device, read/write to the health
1072device using the file descriptor. <p>The received data needs to be interpreted
1073using a health manager which implements the IEEE 11073-xxxxx
1074specifications.</p></li>
1075
1076  <li>When done, close the health channel and unregister the application.  The
1077channel also closes when there is extended inactivity.</li>
1078</ol>
1079
1080<p>For a complete code sample that illustrates these steps, see <a
1081href="{@docRoot}resources/samples/BluetoothHDP/index.html">Bluetooth HDP (Health
1082Device Profile)</a>. </p>
1083