BluetoothDevice.java revision e6ee3be1c254404dad842298f6f56c11cc6c7ac8
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.bluetooth; 18 19import android.annotation.SdkConstant; 20import android.annotation.SdkConstant.SdkConstantType; 21import android.os.IBinder; 22import android.os.Parcel; 23import android.os.Parcelable; 24import android.os.ParcelUuid; 25import android.os.RemoteException; 26import android.os.ServiceManager; 27import android.util.Log; 28 29import java.io.IOException; 30import java.io.UnsupportedEncodingException; 31import java.util.UUID; 32 33/** 34 * Represents a remote Bluetooth device. 35 * 36 * <p>Use {@link BluetoothAdapter#getRemoteDevice} to create a {@link 37 * BluetoothDevice}. 38 * 39 * <p>This class is really just a thin wrapper for a Bluetooth hardware 40 * address. Objects of this class are immutable. Operations on this class 41 * are performed on the remote Bluetooth hardware address, using the 42 * {@link BluetoothAdapter} that was used to create this {@link 43 * BluetoothDevice}. 44 */ 45public final class BluetoothDevice implements Parcelable { 46 private static final String TAG = "BluetoothDevice"; 47 48 /** 49 * Sentinel error value for this class. Guaranteed to not equal any other 50 * integer constant in this class. Provided as a convenience for functions 51 * that require a sentinel error value, for example: 52 * <p><code>Intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 53 * BluetoothDevice.ERROR)</code> 54 */ 55 public static final int ERROR = Integer.MIN_VALUE; 56 57 /** 58 * Broadcast Action: Remote device discovered. 59 * <p>Sent when a remote device is found during discovery. 60 * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link 61 * #EXTRA_CLASS}. Can contain the extra fields {@link #EXTRA_NAME} and/or 62 * {@link #EXTRA_RSSI} if they are available. 63 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 64 */ 65 // TODO: Change API to not broadcast RSSI if not available (incoming connection) 66 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 67 public static final String ACTION_FOUND = 68 "android.bluetooth.device.action.FOUND"; 69 70 /** 71 * Broadcast Action: Remote device disappeared. 72 * <p>Sent when a remote device that was found in the last discovery is not 73 * found in the current discovery. 74 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 75 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 76 * @hide 77 */ 78 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 79 public static final String ACTION_DISAPPEARED = 80 "android.bluetooth.device.action.DISAPPEARED"; 81 82 /** 83 * Broadcast Action: Bluetooth class of a remote device has changed. 84 * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link 85 * #EXTRA_CLASS}. 86 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 87 * @see {@link BluetoothClass} 88 */ 89 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 90 public static final String ACTION_CLASS_CHANGED = 91 "android.bluetooth.device.action.CLASS_CHANGED"; 92 93 /** 94 * Broadcast Action: Indicates a low level (ACL) connection has been 95 * established with a remote device. 96 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 97 * <p>ACL connections are managed automatically by the Android Bluetooth 98 * stack. 99 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 100 */ 101 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 102 public static final String ACTION_ACL_CONNECTED = 103 "android.bluetooth.device.action.ACL_CONNECTED"; 104 105 /** 106 * Broadcast Action: Indicates that a low level (ACL) disconnection has 107 * been requested for a remote device, and it will soon be disconnected. 108 * <p>This is useful for graceful disconnection. Applications should use 109 * this intent as a hint to immediately terminate higher level connections 110 * (RFCOMM, L2CAP, or profile connections) to the remote device. 111 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 112 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 113 */ 114 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 115 public static final String ACTION_ACL_DISCONNECT_REQUESTED = 116 "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED"; 117 118 /** 119 * Broadcast Action: Indicates a low level (ACL) disconnection from a 120 * remote device. 121 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 122 * <p>ACL connections are managed automatically by the Android Bluetooth 123 * stack. 124 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 125 */ 126 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 127 public static final String ACTION_ACL_DISCONNECTED = 128 "android.bluetooth.device.action.ACL_DISCONNECTED"; 129 130 /** 131 * Broadcast Action: Indicates the friendly name of a remote device has 132 * been retrieved for the first time, or changed since the last retrieval. 133 * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link 134 * #EXTRA_NAME}. 135 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 136 */ 137 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 138 public static final String ACTION_NAME_CHANGED = 139 "android.bluetooth.device.action.NAME_CHANGED"; 140 141 /** 142 * Broadcast Action: Indicates a change in the bond state of a remote 143 * device. For example, if a device is bonded (paired). 144 * <p>Always contains the extra fields {@link #EXTRA_DEVICE}, {@link 145 * #EXTRA_BOND_STATE} and {@link #EXTRA_PREVIOUS_BOND_STATE}. 146 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 147 */ 148 // Note: When EXTRA_BOND_STATE is BOND_NONE then this will also 149 // contain a hidden extra field EXTRA_REASON with the result code. 150 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 151 public static final String ACTION_BOND_STATE_CHANGED = 152 "android.bluetooth.device.action.BOND_STATE_CHANGED"; 153 154 /** 155 * Used as a Parcelable {@link BluetoothDevice} extra field in every intent 156 * broadcast by this class. It contains the {@link BluetoothDevice} that 157 * the intent applies to. 158 */ 159 public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE"; 160 161 /** 162 * Used as a String extra field in {@link #ACTION_NAME_CHANGED} and {@link 163 * #ACTION_FOUND} intents. It contains the friendly Bluetooth name. 164 */ 165 public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME"; 166 167 /** 168 * Used as an optional short extra field in {@link #ACTION_FOUND} intents. 169 * Contains the RSSI value of the remote device as reported by the 170 * Bluetooth hardware. 171 */ 172 public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI"; 173 174 /** 175 * Used as an Parcelable {@link BluetoothClass} extra field in {@link 176 * #ACTION_FOUND} and {@link #ACTION_CLASS_CHANGED} intents. 177 */ 178 public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS"; 179 180 /** 181 * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents. 182 * Contains the bond state of the remote device. 183 * <p>Possible values are: 184 * {@link #BOND_NONE}, 185 * {@link #BOND_BONDING}, 186 * {@link #BOND_BONDED}. 187 */ 188 public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE"; 189 /** 190 * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents. 191 * Contains the previous bond state of the remote device. 192 * <p>Possible values are: 193 * {@link #BOND_NONE}, 194 * {@link #BOND_BONDING}, 195 * {@link #BOND_BONDED}. 196 */ 197 public static final String EXTRA_PREVIOUS_BOND_STATE = 198 "android.bluetooth.device.extra.PREVIOUS_BOND_STATE"; 199 /** 200 * Indicates the remote device is not bonded (paired). 201 * <p>There is no shared link key with the remote device, so communication 202 * (if it is allowed at all) will be unauthenticated and unencrypted. 203 */ 204 public static final int BOND_NONE = 10; 205 /** 206 * Indicates bonding (pairing) is in progress with the remote device. 207 */ 208 public static final int BOND_BONDING = 11; 209 /** 210 * Indicates the remote device is bonded (paired). 211 * <p>A shared link keys exists locally for the remote device, so 212 * communication can be authenticated and encrypted. 213 * <p><i>Being bonded (paired) with a remote device does not necessarily 214 * mean the device is currently connected. It just means that the ponding 215 * procedure was compeleted at some earlier time, and the link key is still 216 * stored locally, ready to use on the next connection. 217 * </i> 218 */ 219 public static final int BOND_BONDED = 12; 220 221 /** @hide */ 222 public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON"; 223 /** @hide */ 224 public static final String EXTRA_PAIRING_VARIANT = 225 "android.bluetooth.device.extra.PAIRING_VARIANT"; 226 /** @hide */ 227 public static final String EXTRA_PASSKEY = "android.bluetooth.device.extra.PASSKEY"; 228 229 /** 230 * Broadcast Action: This intent is used to broadcast the {@link UUID} 231 * wrapped as a {@link android.os.ParcelUuid} of the remote device after it 232 * has been fetched. This intent is sent only when the UUIDs of the remote 233 * device are requested to be fetched using Service Discovery Protocol 234 * <p> Always contains the extra field {@link #EXTRA_DEVICE} 235 * <p> Always contains the extra filed {@link #EXTRA_UUID} 236 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 237 * @hide 238 */ 239 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 240 public static final String ACTION_UUID = 241 "android.bleutooth.device.action.UUID"; 242 243 /** 244 * Broadcast Action: Indicates a failure to retrieve the name of a remote 245 * device. 246 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 247 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 248 * @hide 249 */ 250 //TODO: is this actually useful? 251 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 252 public static final String ACTION_NAME_FAILED = 253 "android.bluetooth.device.action.NAME_FAILED"; 254 255 /** @hide */ 256 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 257 public static final String ACTION_PAIRING_REQUEST = 258 "android.bluetooth.device.action.PAIRING_REQUEST"; 259 /** @hide */ 260 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 261 public static final String ACTION_PAIRING_CANCEL = 262 "android.bluetooth.device.action.PAIRING_CANCEL"; 263 264 /** A bond attempt succeeded 265 * @hide */ 266 public static final int BOND_SUCCESS = 0; 267 /** A bond attempt failed because pins did not match, or remote device did 268 * not respond to pin request in time 269 * @hide */ 270 public static final int UNBOND_REASON_AUTH_FAILED = 1; 271 /** A bond attempt failed because the other side explicilty rejected 272 * bonding 273 * @hide */ 274 public static final int UNBOND_REASON_AUTH_REJECTED = 2; 275 /** A bond attempt failed because we canceled the bonding process 276 * @hide */ 277 public static final int UNBOND_REASON_AUTH_CANCELED = 3; 278 /** A bond attempt failed because we could not contact the remote device 279 * @hide */ 280 public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4; 281 /** A bond attempt failed because a discovery is in progress 282 * @hide */ 283 public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5; 284 /** A bond attempt failed because of authentication timeout 285 * @hide */ 286 public static final int UNBOND_REASON_AUTH_TIMEOUT = 6; 287 /** A bond attempt failed because of repeated attempts 288 * @hide */ 289 public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7; 290 /** A bond attempt failed because we received an Authentication Cancel 291 * by remote end 292 * @hide */ 293 public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8; 294 /** An existing bond was explicitly revoked 295 * @hide */ 296 public static final int UNBOND_REASON_REMOVED = 9; 297 298 /** The user will be prompted to enter a pin 299 * @hide */ 300 public static final int PAIRING_VARIANT_PIN = 0; 301 /** The user will be prompted to enter a passkey 302 * @hide */ 303 public static final int PAIRING_VARIANT_PASSKEY = 1; 304 /** The user will be prompted to confirm the passkey displayed on the screen 305 * @hide */ 306 public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; 307 /** The user will be prompted to accept or deny the incoming pairing request 308 * @hide */ 309 public static final int PAIRING_VARIANT_CONSENT = 3; 310 /** The user will be prompted to enter the passkey displayed on remote device 311 * @hide */ 312 public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4; 313 314 /** 315 * Used as an extra field in {@link #ACTION_UUID} intents, 316 * Contains the {@link android.os.ParcelUuid}s of the remote device which 317 * is a parcelable version of {@link UUID}. 318 * @hide 319 */ 320 public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID"; 321 322 /** 323 * Lazy initialization. Guaranteed final after first object constructed, or 324 * getService() called. 325 * TODO: Unify implementation of sService amongst BluetoothFoo API's 326 */ 327 private static IBluetooth sService; 328 329 private final String mAddress; 330 331 /*package*/ static IBluetooth getService() { 332 synchronized (BluetoothDevice.class) { 333 if (sService == null) { 334 IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE); 335 if (b == null) { 336 throw new RuntimeException("Bluetooth service not available"); 337 } 338 sService = IBluetooth.Stub.asInterface(b); 339 } 340 } 341 return sService; 342 } 343 344 /** 345 * Create a new BluetoothDevice 346 * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB", 347 * and is validated in this constructor. 348 * @param address valid Bluetooth MAC address 349 * @throws RuntimeException Bluetooth is not available on this platform 350 * @throws IllegalArgumentException address is invalid 351 * @hide 352 */ 353 /*package*/ BluetoothDevice(String address) { 354 getService(); // ensures sService is initialized 355 if (!BluetoothAdapter.checkBluetoothAddress(address)) { 356 throw new IllegalArgumentException(address + " is not a valid Bluetooth address"); 357 } 358 359 mAddress = address; 360 } 361 362 @Override 363 public boolean equals(Object o) { 364 if (o instanceof BluetoothDevice) { 365 return mAddress.equals(((BluetoothDevice)o).getAddress()); 366 } 367 return false; 368 } 369 370 @Override 371 public int hashCode() { 372 return mAddress.hashCode(); 373 } 374 375 /** 376 * Returns a string representation of this BluetoothDevice. 377 * <p>Currently this is the Bluetooth hardware address, for example 378 * "00:11:22:AA:BB:CC". However, you should always use {@link #getAddress} 379 * if you explicitly require the Bluetooth hardware address in case the 380 * {@link #toString} representation changes in the future. 381 * @return string representation of this BluetoothDevice 382 */ 383 @Override 384 public String toString() { 385 return mAddress; 386 } 387 388 public int describeContents() { 389 return 0; 390 } 391 392 public static final Parcelable.Creator<BluetoothDevice> CREATOR = 393 new Parcelable.Creator<BluetoothDevice>() { 394 public BluetoothDevice createFromParcel(Parcel in) { 395 return new BluetoothDevice(in.readString()); 396 } 397 public BluetoothDevice[] newArray(int size) { 398 return new BluetoothDevice[size]; 399 } 400 }; 401 402 public void writeToParcel(Parcel out, int flags) { 403 out.writeString(mAddress); 404 } 405 406 /** 407 * Returns the hardware address of this BluetoothDevice. 408 * <p> For example, "00:11:22:AA:BB:CC". 409 * @return Bluetooth hardware address as string 410 */ 411 public String getAddress() { 412 return mAddress; 413 } 414 415 /** 416 * Get the friendly Bluetooth name of the remote device. 417 * 418 * <p>The local adapter will automatically retrieve remote names when 419 * performing a device scan, and will cache them. This method just returns 420 * the name for this device from the cache. 421 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 422 * 423 * @return the Bluetooth name, or null if there was a problem. 424 */ 425 public String getName() { 426 try { 427 return sService.getRemoteName(mAddress); 428 } catch (RemoteException e) {Log.e(TAG, "", e);} 429 return null; 430 } 431 432 /** 433 * Start the bonding (pairing) process with the remote device. 434 * <p>This is an asynchronous call, it will return immediately. Register 435 * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when 436 * the bonding process completes, and its result. 437 * <p>Android system services will handle the necessary user interactions 438 * to confirm and complete the bonding process. 439 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 440 * 441 * @return false on immediate error, true if bonding will begin 442 * @hide 443 */ 444 public boolean createBond() { 445 try { 446 return sService.createBond(mAddress); 447 } catch (RemoteException e) {Log.e(TAG, "", e);} 448 return false; 449 } 450 451 /** 452 * Cancel an in-progress bonding request started with {@link #createBond}. 453 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 454 * 455 * @return true on sucess, false on error 456 * @hide 457 */ 458 public boolean cancelBondProcess() { 459 try { 460 return sService.cancelBondProcess(mAddress); 461 } catch (RemoteException e) {Log.e(TAG, "", e);} 462 return false; 463 } 464 465 /** 466 * Remove bond (pairing) with the remote device. 467 * <p>Delete the link key associated with the remote device, and 468 * immediately terminate connections to that device that require 469 * authentication and encryption. 470 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 471 * 472 * @return true on sucess, false on error 473 * @hide 474 */ 475 public boolean removeBond() { 476 try { 477 return sService.removeBond(mAddress); 478 } catch (RemoteException e) {Log.e(TAG, "", e);} 479 return false; 480 } 481 482 /** 483 * Get the bond state of the remote device. 484 * <p>Possible values for the bond state are: 485 * {@link #BOND_NONE}, 486 * {@link #BOND_BONDING}, 487 * {@link #BOND_BONDED}. 488 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 489 * 490 * @return the bond state 491 */ 492 public int getBondState() { 493 try { 494 return sService.getBondState(mAddress); 495 } catch (RemoteException e) {Log.e(TAG, "", e);} 496 return BOND_NONE; 497 } 498 499 /** 500 * Get the Bluetooth class of the remote device. 501 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 502 * 503 * @return Bluetooth class object, or null on error 504 */ 505 public BluetoothClass getBluetoothClass() { 506 try { 507 int classInt = sService.getRemoteClass(mAddress); 508 if (classInt == BluetoothClass.ERROR) return null; 509 return new BluetoothClass(classInt); 510 } catch (RemoteException e) {Log.e(TAG, "", e);} 511 return null; 512 } 513 514 /** 515 * Get trust state of a remote device. 516 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 517 * @hide 518 */ 519 public boolean getTrustState() { 520 try { 521 return sService.getTrustState(mAddress); 522 } catch (RemoteException e) { 523 Log.e(TAG, "", e); 524 } 525 return false; 526 } 527 528 /** 529 * Set trust state for a remote device. 530 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 531 * @param value the trust state value (true or false) 532 * @hide 533 */ 534 public boolean setTrust(boolean value) { 535 try { 536 return sService.setTrust(mAddress, value); 537 } catch (RemoteException e) { 538 Log.e(TAG, "", e); 539 } 540 return false; 541 } 542 543 /** @hide */ 544 public ParcelUuid[] getUuids() { 545 try { 546 return sService.getRemoteUuids(mAddress); 547 } catch (RemoteException e) {Log.e(TAG, "", e);} 548 return null; 549 } 550 551 /** 552 * Perform a SDP query on the remote device to get the UUIDs 553 * supported. This API is asynchronous and an Intent is sent, 554 * with the UUIDs supported by the remote end. If there is an error 555 * in getting the SDP records or if the process takes a long time, 556 * an Intent is sent with the UUIDs that is currently present in the 557 * cache. Clients should use the {@link getUuids} to get UUIDs 558 * is SDP is not to be performed. 559 * 560 * @return False if the sanity check fails, True if the process 561 * of initiating an ACL connection to the remote device 562 * was started. 563 * @hide 564 */ 565 public boolean fetchUuidsWithSdp() { 566 try { 567 return sService.fetchRemoteUuids(mAddress, null, null); 568 } catch (RemoteException e) {Log.e(TAG, "", e);} 569 return false; 570 } 571 572 /** @hide */ 573 public int getServiceChannel(ParcelUuid uuid) { 574 try { 575 return sService.getRemoteServiceChannel(mAddress, uuid); 576 } catch (RemoteException e) {Log.e(TAG, "", e);} 577 return BluetoothDevice.ERROR; 578 } 579 580 /** @hide */ 581 public boolean setPin(byte[] pin) { 582 try { 583 return sService.setPin(mAddress, pin); 584 } catch (RemoteException e) {Log.e(TAG, "", e);} 585 return false; 586 } 587 588 /** @hide */ 589 public boolean setPasskey(int passkey) { 590 try { 591 return sService.setPasskey(mAddress, passkey); 592 } catch (RemoteException e) {Log.e(TAG, "", e);} 593 return false; 594 } 595 596 /** @hide */ 597 public boolean setPairingConfirmation(boolean confirm) { 598 try { 599 return sService.setPairingConfirmation(mAddress, confirm); 600 } catch (RemoteException e) {Log.e(TAG, "", e);} 601 return false; 602 } 603 604 /** @hide */ 605 public boolean cancelPairingUserInput() { 606 try { 607 return sService.cancelPairingUserInput(mAddress); 608 } catch (RemoteException e) {Log.e(TAG, "", e);} 609 return false; 610 } 611 612 /** 613 * Create an RFCOMM {@link BluetoothSocket} ready to start a secure 614 * outgoing connection to this remote device on given channel. 615 * <p>The remote device will be authenticated and communication on this 616 * socket will be encrypted. 617 * <p>Use {@link BluetoothSocket#connect} to intiate the outgoing 618 * connection. 619 * <p>Valid RFCOMM channels are in range 1 to 30. 620 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 621 * 622 * @param channel RFCOMM channel to connect to 623 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 624 * @throws IOException on error, for example Bluetooth not available, or 625 * insufficient permissions 626 * @hide 627 */ 628 public BluetoothSocket createRfcommSocket(int channel) throws IOException { 629 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel, 630 null); 631 } 632 633 /** 634 * Create an RFCOMM {@link BluetoothSocket} ready to start a secure 635 * outgoing connection to this remote device using SDP lookup of uuid. 636 * <p>This is designed to be used with {@link 637 * BluetoothAdapter#listenUsingRfcommWithServiceRecord} for peer-peer 638 * Bluetooth applications. 639 * <p>Use {@link BluetoothSocket#connect} to intiate the outgoing 640 * connection. This will also perform an SDP lookup of the given uuid to 641 * determine which channel to connect to. 642 * <p>The remote device will be authenticated and communication on this 643 * socket will be encrypted. 644 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 645 * 646 * @param uuid service record uuid to lookup RFCOMM channel 647 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 648 * @throws IOException on error, for example Bluetooth not available, or 649 * insufficient permissions 650 */ 651 public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException { 652 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, -1, 653 new ParcelUuid(uuid)); 654 } 655 656 /** 657 * Construct an insecure RFCOMM socket ready to start an outgoing 658 * connection. 659 * Call #connect on the returned #BluetoothSocket to begin the connection. 660 * The remote device will not be authenticated and communication on this 661 * socket will not be encrypted. 662 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 663 * 664 * @param port remote port 665 * @return An RFCOMM BluetoothSocket 666 * @throws IOException On error, for example Bluetooth not available, or 667 * insufficient permissions. 668 * @hide 669 */ 670 public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException { 671 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port, 672 null); 673 } 674 675 /** 676 * Construct a SCO socket ready to start an outgoing connection. 677 * Call #connect on the returned #BluetoothSocket to begin the connection. 678 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 679 * 680 * @return a SCO BluetoothSocket 681 * @throws IOException on error, for example Bluetooth not available, or 682 * insufficient permissions. 683 * @hide 684 */ 685 public BluetoothSocket createScoSocket() throws IOException { 686 return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null); 687 } 688 689 /** 690 * Check that a pin is valid and convert to byte array. 691 * 692 * Bluetooth pin's are 1 to 16 bytes of UTF8 characters. 693 * @param pin pin as java String 694 * @return the pin code as a UTF8 byte array, or null if it is an invalid 695 * Bluetooth pin. 696 * @hide 697 */ 698 public static byte[] convertPinToBytes(String pin) { 699 if (pin == null) { 700 return null; 701 } 702 byte[] pinBytes; 703 try { 704 pinBytes = pin.getBytes("UTF8"); 705 } catch (UnsupportedEncodingException uee) { 706 Log.e(TAG, "UTF8 not supported?!?"); // this should not happen 707 return null; 708 } 709 if (pinBytes.length <= 0 || pinBytes.length > 16) { 710 return null; 711 } 712 return pinBytes; 713 } 714 715} 716