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