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