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