BluetoothAdapter.java revision de893f550301a60274e87aa8168225e7a7a42184
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.RemoteException; 22import android.util.Log; 23 24import java.io.IOException; 25import java.util.Collections; 26import java.util.Set; 27import java.util.HashSet; 28 29/** 30 * Represents the local Bluetooth adapter. 31 * 32 * <p>Use {@link android.content.Context#getSystemService} with {@link 33 * android.content.Context#BLUETOOTH_SERVICE} to get the default local 34 * Bluetooth adapter. On most Android devices there is only one local 35 * Bluetotoh adapter. 36 * 37 * <p>Use the {@link BluetoothDevice} class for operations on remote Bluetooth 38 * devices. 39 * 40 * <p>TODO: unhide more of this class 41 */ 42public final class BluetoothAdapter { 43 private static final String TAG = "BluetoothAdapter"; 44 45 /** 46 * Broadcast Action: The state of the local Bluetooth adapter has been 47 * changed. 48 * <p>For example, Bluetooth has been turned on or off. 49 * <p>Contains the extra fields {@link #EXTRA_STATE} and {@link 50 * #EXTRA_PREVIOUS_STATE} containing the new and old states 51 * respectively. 52 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 53 */ 54 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 55 public static final String ACTION_STATE_CHANGED = 56 "android.bluetooth.intent.action.STATE_CHANGED"; 57 58 /** 59 * Used as an int extra field in {@link #ACTION_STATE_CHANGED} 60 * intents to request the current power state. Possible values are: 61 * {@link #STATE_OFF}, 62 * {@link #STATE_TURNING_ON}, 63 * {@link #STATE_ON}, 64 * {@link #STATE_TURNING_OFF}, 65 */ 66 public static final String EXTRA_STATE = 67 "android.bluetooth.intent.extra.STATE"; 68 /** 69 * Used as an int extra field in {@link #ACTION_STATE_CHANGED} 70 * intents to request the previous power state. Possible values are: 71 * {@link #STATE_OFF}, 72 * {@link #STATE_TURNING_ON}, 73 * {@link #STATE_ON}, 74 * {@link #STATE_TURNING_OFF}, 75 */ 76 public static final String EXTRA_PREVIOUS_STATE = 77 "android.bluetooth.intent.extra.PREVIOUS_STATE"; 78 79 /** 80 * Indicates the local Bluetooth adapter is off. 81 */ 82 public static final int STATE_OFF = 40; 83 /** 84 * Indicates the local Bluetooth adapter is turning on. However local 85 * clients should wait for {@link #STATE_ON} before attempting to 86 * use the adapter. 87 */ 88 public static final int STATE_TURNING_ON = 41; 89 /** 90 * Indicates the local Bluetooth adapter is on, and ready for use. 91 */ 92 public static final int STATE_ON = 42; 93 /** 94 * Indicates the local Bluetooth adapter is turning off. Local clients 95 * should immediately attempt graceful disconnection of any remote links. 96 */ 97 public static final int STATE_TURNING_OFF = 43; 98 99 /** 100 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter 101 * has changed. 102 * <p>Contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link 103 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes 104 * respectively. 105 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 106 */ 107 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 108 public static final String ACTION_SCAN_MODE_CHANGED = 109 "android.bluetooth.intent.action.SCAN_MODE_CHANGED"; 110 111 /** 112 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED} 113 * intents to request the current scan mode. Possible values are: 114 * {@link #SCAN_MODE_NONE}, 115 * {@link #SCAN_MODE_CONNECTABLE}, 116 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}, 117 */ 118 public static final String EXTRA_SCAN_MODE = "android.bluetooth.intent.extra.SCAN_MODE"; 119 /** 120 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED} 121 * intents to request the previous scan mode. Possible values are: 122 * {@link #SCAN_MODE_NONE}, 123 * {@link #SCAN_MODE_CONNECTABLE}, 124 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}, 125 */ 126 public static final String EXTRA_PREVIOUS_SCAN_MODE = 127 "android.bluetooth.intent.extra.PREVIOUS_SCAN_MODE"; 128 129 /** 130 * Indicates that both inquiry scan and page scan are disabled on the local 131 * Bluetooth adapter. Therefore this device is neither discoverable 132 * nor connectable from remote Bluetooth devices. 133 */ 134 public static final int SCAN_MODE_NONE = 50; 135 /** 136 * Indicates that inquiry scan is disabled, but page scan is enabled on the 137 * local Bluetooth adapter. Therefore this device is not discoverable from 138 * remote Bluetooth devices, but is connectable from remote devices that 139 * have previously discovered this device. 140 */ 141 public static final int SCAN_MODE_CONNECTABLE = 51; 142 /** 143 * Indicates that both inquiry scan and page scan are enabled on the local 144 * Bluetooth adapter. Therefore this device is both discoverable and 145 * connectable from remote Bluetooth devices. 146 */ 147 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 53; 148 149 /** The user will be prompted to enter a pin 150 * @hide */ 151 public static final int PAIRING_VARIANT_PIN = 0; 152 /** The user will be prompted to enter a passkey 153 * @hide */ 154 public static final int PAIRING_VARIANT_PASSKEY = 1; 155 /** The user will be prompted to confirm the passkey displayed on the screen 156 * @hide */ 157 public static final int PAIRING_VARIANT_CONFIRMATION = 2; 158 159 private final IBluetooth mService; 160 161 /** 162 * Do not use this constructor. Use Context.getSystemService() instead. 163 * @hide 164 */ 165 public BluetoothAdapter(IBluetooth service) { 166 if (service == null) { 167 throw new IllegalArgumentException("service is null"); 168 } 169 mService = service; 170 } 171 172 /** 173 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware 174 * address. 175 * <p>Valid Bluetooth hardware addresses must be upper case, in a format 176 * such as "00:11:22:33:AA:BB". 177 * <p>A {@link BluetoothDevice} will always be returned for a valid 178 * hardware address, even if this adapter has never seen that device. 179 * 180 * @param address valid Bluetooth MAC address 181 * @throws IllegalArgumentException if address is invalid 182 */ 183 public BluetoothDevice getRemoteDevice(String address) { 184 return new BluetoothDevice(address); 185 } 186 187 /** 188 * Return true if Bluetooth is currently enabled and ready for use. 189 * <p>Equivalent to: 190 * <code>getBluetoothState() == STATE_ON</code> 191 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 192 * 193 * @return true if the local adapter is turned on 194 */ 195 public boolean isEnabled() { 196 try { 197 return mService.isEnabled(); 198 } catch (RemoteException e) {Log.e(TAG, "", e);} 199 return false; 200 } 201 202 /** 203 * Get the current state of the local Bluetooth adapter. 204 * <p>Possible return values are 205 * {@link #STATE_OFF}, 206 * {@link #STATE_TURNING_ON}, 207 * {@link #STATE_ON}, 208 * {@link #STATE_TURNING_OFF}. 209 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 210 * 211 * @return current state of Bluetooth adapter 212 */ 213 public int getState() { 214 try { 215 return mService.getBluetoothState(); 216 } catch (RemoteException e) {Log.e(TAG, "", e);} 217 return STATE_OFF; 218 } 219 220 /** 221 * Turn on the local Bluetooth adapter. 222 * <p>This powers on the underlying Bluetooth hardware, and starts all 223 * Bluetooth system services. 224 * <p>This is an asynchronous call: it will return immediatley, and 225 * clients should listen for {@link #ACTION_STATE_CHANGED} 226 * to be notified of subsequent adapter state changes. If this call returns 227 * true, then the adapter state will immediately transition from {@link 228 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time 229 * later transition to either {@link #STATE_OFF} or {@link 230 * #STATE_ON}. If this call returns false then there was an 231 * immediate problem that will prevent the adapter from being turned on - 232 * such as Airplane mode, or the adapter is already turned on. 233 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 234 * 235 * @return true to indicate adapter startup has begun, or false on 236 * immediate error 237 */ 238 public boolean enable() { 239 try { 240 return mService.enable(); 241 } catch (RemoteException e) {Log.e(TAG, "", e);} 242 return false; 243 } 244 245 /** 246 * Turn off the local Bluetooth adapter. 247 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth 248 * system services, and powers down the underlying Bluetooth hardware. 249 * <p>This is an asynchronous call: it will return immediatley, and 250 * clients should listen for {@link #ACTION_STATE_CHANGED} 251 * to be notified of subsequent adapter state changes. If this call returns 252 * true, then the adapter state will immediately transition from {@link 253 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time 254 * later transition to either {@link #STATE_OFF} or {@link 255 * #STATE_ON}. If this call returns false then there was an 256 * immediate problem that will prevent the adapter from being turned off - 257 * such as the adapter already being turned off. 258 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 259 * 260 * @return true to indicate adapter shutdown has begun, or false on 261 * immediate error 262 */ 263 public boolean disable() { 264 try { 265 return mService.disable(true); 266 } catch (RemoteException e) {Log.e(TAG, "", e);} 267 return false; 268 } 269 270 /** 271 * Returns the hardware address of the local Bluetooth adapter. 272 * <p>For example, "00:11:22:AA:BB:CC". 273 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 274 * 275 * @return Bluetooth hardware address as string 276 */ 277 public String getAddress() { 278 try { 279 return mService.getAddress(); 280 } catch (RemoteException e) {Log.e(TAG, "", e);} 281 return null; 282 } 283 284 /** 285 * Get the friendly Bluetooth name of the local Bluetooth adapter. 286 * <p>This name is visible to remote Bluetooth devices. 287 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 288 * 289 * @return the Bluetooth name, or null on error 290 */ 291 public String getName() { 292 try { 293 return mService.getName(); 294 } catch (RemoteException e) {Log.e(TAG, "", e);} 295 return null; 296 } 297 298 /** 299 * Set the friendly Bluetooth name of the local Bluetoth adapter. 300 * <p>This name is visible to remote Bluetooth devices. 301 * <p>Valid Bluetooth names are a maximum of 248 UTF-8 characters, however 302 * many remote devices can only display the first 40 characters, and some 303 * may be limited to just 20. 304 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 305 * 306 * @param name a valid Bluetooth name 307 * @return true if the name was set, false otherwise 308 */ 309 public boolean setName(String name) { 310 try { 311 return mService.setName(name); 312 } catch (RemoteException e) {Log.e(TAG, "", e);} 313 return false; 314 } 315 316 /** 317 * Get the current Bluetooth scan mode of the local Bluetooth adaper. 318 * <p>The Bluetooth scan mode determines if the local adapter is 319 * connectable and/or discoverable from remote Bluetooth devices. 320 * <p>Possible values are: 321 * {@link #SCAN_MODE_NONE}, 322 * {@link #SCAN_MODE_CONNECTABLE}, 323 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. 324 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 325 * 326 * @return scan mode 327 */ 328 public int getScanMode() { 329 try { 330 return mService.getScanMode(); 331 } catch (RemoteException e) {Log.e(TAG, "", e);} 332 return SCAN_MODE_NONE; 333 } 334 335 /** 336 * Set the Bluetooth scan mode of the local Bluetooth adapter. 337 * <p>The Bluetooth scan mode determines if the local adapter is 338 * connectable and/or discoverable from remote Bluetooth devices. 339 * <p>For privacy reasons, it is recommended to limit the duration of time 340 * that the local adapter remains in a discoverable scan mode. For example, 341 * 2 minutes is a generous time to allow a remote Bluetooth device to 342 * initiate and complete its discovery process. 343 * <p>Valid scan mode values are: 344 * {@link #SCAN_MODE_NONE}, 345 * {@link #SCAN_MODE_CONNECTABLE}, 346 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. 347 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 348 * 349 * @param mode valid scan mode 350 * @return true if the scan mode was set, false otherwise 351 */ 352 public boolean setScanMode(int mode) { 353 try { 354 return mService.setScanMode(mode); 355 } catch (RemoteException e) {Log.e(TAG, "", e);} 356 return false; 357 } 358 359 /** @hide */ 360 public int getDiscoverableTimeout() { 361 try { 362 return mService.getDiscoverableTimeout(); 363 } catch (RemoteException e) {Log.e(TAG, "", e);} 364 return -1; 365 } 366 367 /** @hide */ 368 public void setDiscoverableTimeout(int timeout) { 369 try { 370 mService.setDiscoverableTimeout(timeout); 371 } catch (RemoteException e) {Log.e(TAG, "", e);} 372 } 373 374 /** @hide */ 375 public boolean startDiscovery() { 376 try { 377 return mService.startDiscovery(); 378 } catch (RemoteException e) {Log.e(TAG, "", e);} 379 return false; 380 } 381 382 /** @hide */ 383 public void cancelDiscovery() { 384 try { 385 mService.cancelDiscovery(); 386 } catch (RemoteException e) {Log.e(TAG, "", e);} 387 } 388 389 /** @hide */ 390 public boolean isDiscovering() { 391 try { 392 return mService.isDiscovering(); 393 } catch (RemoteException e) {Log.e(TAG, "", e);} 394 return false; 395 } 396 397 /** 398 * List remote devices that are bonded (paired) to the local adapter. 399 * 400 * Bonding (pairing) is the process by which the user enters a pin code for 401 * the device, which generates a shared link key, allowing for 402 * authentication and encryption of future connections. In Android we 403 * require bonding before RFCOMM or SCO connections can be made to a remote 404 * device. 405 * 406 * This function lists which remote devices we have a link key for. It does 407 * not cause any RF transmission, and does not check if the remote device 408 * still has it's link key with us. If the other side no longer has its 409 * link key then the RFCOMM or SCO connection attempt will result in an 410 * error. 411 * 412 * This function does not check if the remote device is in range. 413 * 414 * Remote devices that have an in-progress bonding attempt are not 415 * returned. 416 * 417 * @return unmodifiable set of bonded devices, or null on error 418 * @hide 419 */ 420 public Set<BluetoothDevice> getBondedDevices() { 421 try { 422 return toDeviceSet(mService.listBonds()); 423 } catch (RemoteException e) {Log.e(TAG, "", e);} 424 return null; 425 } 426 427 /** 428 * Create a listening, secure RFCOMM Bluetooth socket. 429 * <p>A remote device connecting to this socket will be authenticated and 430 * communication on this socket will be encrypted. 431 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 432 * connections to listening {@link BluetoothServerSocket}. 433 * <p>Valid RFCOMM channels are in range 1 to 30. 434 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 435 * @param channel RFCOMM channel to listen on 436 * @return a listening RFCOMM BluetoothServerSocket 437 * @throws IOException on error, for example Bluetooth not available, or 438 * insufficient permissions, or channel in use. 439 */ 440 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException { 441 BluetoothServerSocket socket = new BluetoothServerSocket( 442 BluetoothSocket.TYPE_RFCOMM, true, true, channel); 443 try { 444 socket.mSocket.bindListen(); 445 } catch (IOException e) { 446 try { 447 socket.close(); 448 } catch (IOException e2) { } 449 throw e; 450 } 451 return socket; 452 } 453 454 /** 455 * Construct an unencrypted, unauthenticated, RFCOMM server socket. 456 * Call #accept to retrieve connections to this socket. 457 * @return An RFCOMM BluetoothServerSocket 458 * @throws IOException On error, for example Bluetooth not available, or 459 * insufficient permissions. 460 * @hide 461 */ 462 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException { 463 BluetoothServerSocket socket = new BluetoothServerSocket( 464 BluetoothSocket.TYPE_RFCOMM, false, false, port); 465 try { 466 socket.mSocket.bindListen(); 467 } catch (IOException e) { 468 try { 469 socket.close(); 470 } catch (IOException e2) { } 471 throw e; 472 } 473 return socket; 474 } 475 476 /** 477 * Construct a SCO server socket. 478 * Call #accept to retrieve connections to this socket. 479 * @return A SCO BluetoothServerSocket 480 * @throws IOException On error, for example Bluetooth not available, or 481 * insufficient permissions. 482 * @hide 483 */ 484 public static BluetoothServerSocket listenUsingScoOn() throws IOException { 485 BluetoothServerSocket socket = new BluetoothServerSocket( 486 BluetoothSocket.TYPE_SCO, false, false, -1); 487 try { 488 socket.mSocket.bindListen(); 489 } catch (IOException e) { 490 try { 491 socket.close(); 492 } catch (IOException e2) { } 493 throw e; 494 } 495 return socket; 496 } 497 498 private Set<BluetoothDevice> toDeviceSet(String[] addresses) { 499 Set<BluetoothDevice> devices = new HashSet<BluetoothDevice>(addresses.length); 500 for (int i = 0; i < addresses.length; i++) { 501 devices.add(getRemoteDevice(addresses[i])); 502 } 503 return Collections.unmodifiableSet(devices); 504 } 505} 506