blob: 1fc22fe524dddde5594a4bdb27cf9b513ad31253 [file] [log] [blame]
Nick Pellybd022f42009-08-14 18:33:38 -07001/*
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
Nick Pellyde893f52009-09-08 13:15:33 -070019import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
Nick Pellybd022f42009-08-14 18:33:38 -070021import 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 *
Nick Pelly45e27042009-08-19 11:00:00 -070032 * <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.
Nick Pellybd022f42009-08-14 18:33:38 -070039 */
40public final class BluetoothAdapter {
41 private static final String TAG = "BluetoothAdapter";
42
Nick Pellyde893f52009-09-08 13:15:33 -070043 /**
Nick Pellyb24e11b2009-09-08 17:40:43 -070044 * Sentinel error value for this class. Guaranteed to not equal any other
45 * integer constant in this class. Provided as a convenience for functions
46 * that require a sentinel error value, for example:
47 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
48 * BluetoothAdapter.ERROR)</code>
49 */
Nick Pelly005b2282009-09-10 10:21:56 -070050 public static final int ERROR = Integer.MIN_VALUE;
Nick Pellyb24e11b2009-09-08 17:40:43 -070051
52 /**
Nick Pellyde893f52009-09-08 13:15:33 -070053 * Broadcast Action: The state of the local Bluetooth adapter has been
54 * changed.
55 * <p>For example, Bluetooth has been turned on or off.
Nick Pelly005b2282009-09-10 10:21:56 -070056 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -070057 * #EXTRA_PREVIOUS_STATE} containing the new and old states
58 * respectively.
59 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
60 */
61 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
62 public static final String ACTION_STATE_CHANGED =
Nick Pelly005b2282009-09-10 10:21:56 -070063 "android.bluetooth.adapter.action.STATE_CHANGED";
Nick Pellybd022f42009-08-14 18:33:38 -070064
Nick Pellyde893f52009-09-08 13:15:33 -070065 /**
66 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
67 * intents to request the current power state. Possible values are:
68 * {@link #STATE_OFF},
69 * {@link #STATE_TURNING_ON},
70 * {@link #STATE_ON},
71 * {@link #STATE_TURNING_OFF},
72 */
73 public static final String EXTRA_STATE =
Nick Pelly005b2282009-09-10 10:21:56 -070074 "android.bluetooth.adapter.extra.STATE";
Nick Pellyde893f52009-09-08 13:15:33 -070075 /**
76 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
77 * intents to request the previous power state. Possible values are:
78 * {@link #STATE_OFF},
79 * {@link #STATE_TURNING_ON},
80 * {@link #STATE_ON},
81 * {@link #STATE_TURNING_OFF},
82 */
83 public static final String EXTRA_PREVIOUS_STATE =
Nick Pelly005b2282009-09-10 10:21:56 -070084 "android.bluetooth.adapter.extra.PREVIOUS_STATE";
Nick Pellybd022f42009-08-14 18:33:38 -070085
Nick Pellyde893f52009-09-08 13:15:33 -070086 /**
87 * Indicates the local Bluetooth adapter is off.
88 */
Nick Pelly005b2282009-09-10 10:21:56 -070089 public static final int STATE_OFF = 10;
Nick Pellyde893f52009-09-08 13:15:33 -070090 /**
91 * Indicates the local Bluetooth adapter is turning on. However local
92 * clients should wait for {@link #STATE_ON} before attempting to
93 * use the adapter.
94 */
Nick Pelly005b2282009-09-10 10:21:56 -070095 public static final int STATE_TURNING_ON = 11;
Nick Pellyde893f52009-09-08 13:15:33 -070096 /**
97 * Indicates the local Bluetooth adapter is on, and ready for use.
98 */
Nick Pelly005b2282009-09-10 10:21:56 -070099 public static final int STATE_ON = 12;
Nick Pellyde893f52009-09-08 13:15:33 -0700100 /**
101 * Indicates the local Bluetooth adapter is turning off. Local clients
102 * should immediately attempt graceful disconnection of any remote links.
103 */
Nick Pelly005b2282009-09-10 10:21:56 -0700104 public static final int STATE_TURNING_OFF = 13;
Nick Pellyde893f52009-09-08 13:15:33 -0700105
106 /**
107 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
108 * has changed.
Nick Pelly005b2282009-09-10 10:21:56 -0700109 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700110 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
111 * respectively.
112 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
113 */
114 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
115 public static final String ACTION_SCAN_MODE_CHANGED =
Nick Pelly005b2282009-09-10 10:21:56 -0700116 "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
Nick Pellyde893f52009-09-08 13:15:33 -0700117
118 /**
119 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
120 * intents to request the current scan mode. Possible values are:
121 * {@link #SCAN_MODE_NONE},
122 * {@link #SCAN_MODE_CONNECTABLE},
123 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
124 */
Nick Pelly005b2282009-09-10 10:21:56 -0700125 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700126 /**
127 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
128 * intents to request the previous scan mode. Possible values are:
129 * {@link #SCAN_MODE_NONE},
130 * {@link #SCAN_MODE_CONNECTABLE},
131 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
132 */
133 public static final String EXTRA_PREVIOUS_SCAN_MODE =
Nick Pelly005b2282009-09-10 10:21:56 -0700134 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700135
136 /**
137 * Indicates that both inquiry scan and page scan are disabled on the local
138 * Bluetooth adapter. Therefore this device is neither discoverable
139 * nor connectable from remote Bluetooth devices.
140 */
Nick Pelly005b2282009-09-10 10:21:56 -0700141 public static final int SCAN_MODE_NONE = 20;
Nick Pellyde893f52009-09-08 13:15:33 -0700142 /**
143 * Indicates that inquiry scan is disabled, but page scan is enabled on the
144 * local Bluetooth adapter. Therefore this device is not discoverable from
145 * remote Bluetooth devices, but is connectable from remote devices that
146 * have previously discovered this device.
147 */
Nick Pelly005b2282009-09-10 10:21:56 -0700148 public static final int SCAN_MODE_CONNECTABLE = 21;
Nick Pellyde893f52009-09-08 13:15:33 -0700149 /**
150 * Indicates that both inquiry scan and page scan are enabled on the local
151 * Bluetooth adapter. Therefore this device is both discoverable and
152 * connectable from remote Bluetooth devices.
153 */
Nick Pelly005b2282009-09-10 10:21:56 -0700154 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
Nick Pellybd022f42009-08-14 18:33:38 -0700155
Nick Pelly005b2282009-09-10 10:21:56 -0700156
157 /**
158 * Broadcast Action: The local Bluetooth adapter has started the remote
159 * device discovery process.
160 * <p>This usually involves an inquiry scan of about 12 seconds, followed
161 * by a page scan of each new device to retrieve its Bluetooth name.
162 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
163 * remote Bluetooth devices are found.
164 * <p>Device discovery is a heavyweight procedure. New connections to
165 * remote Bluetooth devices should not be attempted while discovery is in
166 * progress, and existing connections will experience limited bandwidth
167 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
168 * discovery.
169 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
170 */
171 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
172 public static final String ACTION_DISCOVERY_STARTED =
173 "android.bluetooth.adapter.action.DISCOVERY_STARTED";
174 /**
175 * Broadcast Action: The local Bluetooth adapter has finished the device
176 * discovery process.
177 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
178 */
179 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
180 public static final String ACTION_DISCOVERY_FINISHED =
181 "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
182
183 /**
184 * Broadcast Action: The local Bluetooth adapter has changed its friendly
185 * Bluetooth name.
186 * <p>This name is visible to remote Bluetooth devices.
187 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
188 * the name.
189 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
190 */
191 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
192 public static final String ACTION_LOCAL_NAME_CHANGED =
193 "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
194 /**
195 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
196 * intents to request the local Bluetooth name.
197 */
198 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
199
200 private static final int ADDRESS_LENGTH = 17;
Nick Pellybd022f42009-08-14 18:33:38 -0700201
202 private final IBluetooth mService;
203
204 /**
205 * Do not use this constructor. Use Context.getSystemService() instead.
206 * @hide
207 */
208 public BluetoothAdapter(IBluetooth service) {
209 if (service == null) {
210 throw new IllegalArgumentException("service is null");
211 }
212 mService = service;
213 }
214
215 /**
Nick Pelly45e27042009-08-19 11:00:00 -0700216 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
217 * address.
218 * <p>Valid Bluetooth hardware addresses must be upper case, in a format
Nick Pelly005b2282009-09-10 10:21:56 -0700219 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
220 * available to validate a Bluetooth address.
Nick Pelly45e27042009-08-19 11:00:00 -0700221 * <p>A {@link BluetoothDevice} will always be returned for a valid
222 * hardware address, even if this adapter has never seen that device.
Nick Pellyde893f52009-09-08 13:15:33 -0700223 *
Nick Pellybd022f42009-08-14 18:33:38 -0700224 * @param address valid Bluetooth MAC address
Nick Pelly45e27042009-08-19 11:00:00 -0700225 * @throws IllegalArgumentException if address is invalid
Nick Pellybd022f42009-08-14 18:33:38 -0700226 */
227 public BluetoothDevice getRemoteDevice(String address) {
228 return new BluetoothDevice(address);
229 }
230
231 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700232 * Return true if Bluetooth is currently enabled and ready for use.
233 * <p>Equivalent to:
234 * <code>getBluetoothState() == STATE_ON</code>
235 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -0700236 *
Nick Pellyde893f52009-09-08 13:15:33 -0700237 * @return true if the local adapter is turned on
Nick Pellybd022f42009-08-14 18:33:38 -0700238 */
239 public boolean isEnabled() {
240 try {
241 return mService.isEnabled();
242 } catch (RemoteException e) {Log.e(TAG, "", e);}
243 return false;
244 }
245
246 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700247 * Get the current state of the local Bluetooth adapter.
248 * <p>Possible return values are
249 * {@link #STATE_OFF},
250 * {@link #STATE_TURNING_ON},
251 * {@link #STATE_ON},
252 * {@link #STATE_TURNING_OFF}.
253 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -0700254 *
Nick Pellyde893f52009-09-08 13:15:33 -0700255 * @return current state of Bluetooth adapter
Nick Pellybd022f42009-08-14 18:33:38 -0700256 */
Nick Pellyde893f52009-09-08 13:15:33 -0700257 public int getState() {
Nick Pellybd022f42009-08-14 18:33:38 -0700258 try {
259 return mService.getBluetoothState();
260 } catch (RemoteException e) {Log.e(TAG, "", e);}
Nick Pellyde893f52009-09-08 13:15:33 -0700261 return STATE_OFF;
Nick Pellybd022f42009-08-14 18:33:38 -0700262 }
263
264 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700265 * Turn on the local Bluetooth adapter.
266 * <p>This powers on the underlying Bluetooth hardware, and starts all
267 * Bluetooth system services.
268 * <p>This is an asynchronous call: it will return immediatley, and
269 * clients should listen for {@link #ACTION_STATE_CHANGED}
270 * to be notified of subsequent adapter state changes. If this call returns
271 * true, then the adapter state will immediately transition from {@link
272 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
273 * later transition to either {@link #STATE_OFF} or {@link
274 * #STATE_ON}. If this call returns false then there was an
275 * immediate problem that will prevent the adapter from being turned on -
276 * such as Airplane mode, or the adapter is already turned on.
277 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
278 *
279 * @return true to indicate adapter startup has begun, or false on
280 * immediate error
Nick Pellybd022f42009-08-14 18:33:38 -0700281 */
282 public boolean enable() {
283 try {
284 return mService.enable();
285 } catch (RemoteException e) {Log.e(TAG, "", e);}
286 return false;
287 }
288
289 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700290 * Turn off the local Bluetooth adapter.
291 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
292 * system services, and powers down the underlying Bluetooth hardware.
293 * <p>This is an asynchronous call: it will return immediatley, and
294 * clients should listen for {@link #ACTION_STATE_CHANGED}
295 * to be notified of subsequent adapter state changes. If this call returns
296 * true, then the adapter state will immediately transition from {@link
297 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
298 * later transition to either {@link #STATE_OFF} or {@link
299 * #STATE_ON}. If this call returns false then there was an
300 * immediate problem that will prevent the adapter from being turned off -
301 * such as the adapter already being turned off.
302 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
Nick Pellybd022f42009-08-14 18:33:38 -0700303 *
Nick Pellyde893f52009-09-08 13:15:33 -0700304 * @return true to indicate adapter shutdown has begun, or false on
305 * immediate error
Nick Pellybd022f42009-08-14 18:33:38 -0700306 */
307 public boolean disable() {
308 try {
309 return mService.disable(true);
310 } catch (RemoteException e) {Log.e(TAG, "", e);}
311 return false;
312 }
313
Nick Pellyde893f52009-09-08 13:15:33 -0700314 /**
315 * Returns the hardware address of the local Bluetooth adapter.
316 * <p>For example, "00:11:22:AA:BB:CC".
317 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
318 *
319 * @return Bluetooth hardware address as string
320 */
Nick Pellybd022f42009-08-14 18:33:38 -0700321 public String getAddress() {
322 try {
323 return mService.getAddress();
324 } catch (RemoteException e) {Log.e(TAG, "", e);}
325 return null;
326 }
327
328 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700329 * Get the friendly Bluetooth name of the local Bluetooth adapter.
330 * <p>This name is visible to remote Bluetooth devices.
331 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -0700332 *
Nick Pellyde893f52009-09-08 13:15:33 -0700333 * @return the Bluetooth name, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -0700334 */
335 public String getName() {
336 try {
337 return mService.getName();
338 } catch (RemoteException e) {Log.e(TAG, "", e);}
339 return null;
340 }
341
342 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700343 * Set the friendly Bluetooth name of the local Bluetoth adapter.
344 * <p>This name is visible to remote Bluetooth devices.
345 * <p>Valid Bluetooth names are a maximum of 248 UTF-8 characters, however
346 * many remote devices can only display the first 40 characters, and some
347 * may be limited to just 20.
348 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
Nick Pellybd022f42009-08-14 18:33:38 -0700349 *
Nick Pellyde893f52009-09-08 13:15:33 -0700350 * @param name a valid Bluetooth name
351 * @return true if the name was set, false otherwise
Nick Pellybd022f42009-08-14 18:33:38 -0700352 */
353 public boolean setName(String name) {
354 try {
355 return mService.setName(name);
356 } catch (RemoteException e) {Log.e(TAG, "", e);}
357 return false;
358 }
359
360 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700361 * Get the current Bluetooth scan mode of the local Bluetooth adaper.
362 * <p>The Bluetooth scan mode determines if the local adapter is
363 * connectable and/or discoverable from remote Bluetooth devices.
364 * <p>Possible values are:
365 * {@link #SCAN_MODE_NONE},
366 * {@link #SCAN_MODE_CONNECTABLE},
367 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
368 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
369 *
370 * @return scan mode
Nick Pellybd022f42009-08-14 18:33:38 -0700371 */
372 public int getScanMode() {
373 try {
374 return mService.getScanMode();
375 } catch (RemoteException e) {Log.e(TAG, "", e);}
Nick Pellyde893f52009-09-08 13:15:33 -0700376 return SCAN_MODE_NONE;
Nick Pellybd022f42009-08-14 18:33:38 -0700377 }
378
379 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700380 * Set the Bluetooth scan mode of the local Bluetooth adapter.
381 * <p>The Bluetooth scan mode determines if the local adapter is
382 * connectable and/or discoverable from remote Bluetooth devices.
383 * <p>For privacy reasons, it is recommended to limit the duration of time
384 * that the local adapter remains in a discoverable scan mode. For example,
385 * 2 minutes is a generous time to allow a remote Bluetooth device to
386 * initiate and complete its discovery process.
387 * <p>Valid scan mode values are:
388 * {@link #SCAN_MODE_NONE},
389 * {@link #SCAN_MODE_CONNECTABLE},
390 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
391 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
392 *
393 * @param mode valid scan mode
394 * @return true if the scan mode was set, false otherwise
Nick Pellybd022f42009-08-14 18:33:38 -0700395 */
Nick Pellyde893f52009-09-08 13:15:33 -0700396 public boolean setScanMode(int mode) {
Nick Pellybd022f42009-08-14 18:33:38 -0700397 try {
Nick Pellyde893f52009-09-08 13:15:33 -0700398 return mService.setScanMode(mode);
Nick Pellybd022f42009-08-14 18:33:38 -0700399 } catch (RemoteException e) {Log.e(TAG, "", e);}
Nick Pellyde893f52009-09-08 13:15:33 -0700400 return false;
Nick Pellybd022f42009-08-14 18:33:38 -0700401 }
402
Nick Pelly45e27042009-08-19 11:00:00 -0700403 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -0700404 public int getDiscoverableTimeout() {
405 try {
406 return mService.getDiscoverableTimeout();
407 } catch (RemoteException e) {Log.e(TAG, "", e);}
408 return -1;
409 }
410
Nick Pelly45e27042009-08-19 11:00:00 -0700411 /** @hide */
Nick Pellybd022f42009-08-14 18:33:38 -0700412 public void setDiscoverableTimeout(int timeout) {
413 try {
414 mService.setDiscoverableTimeout(timeout);
415 } catch (RemoteException e) {Log.e(TAG, "", e);}
416 }
417
Nick Pelly005b2282009-09-10 10:21:56 -0700418 /**
419 * Start the remote device discovery process.
420 * <p>The discovery process usually involves an inquiry scan of about 12
421 * seconds, followed by a page scan of each new device to retrieve its
422 * Bluetooth name.
423 * <p>This is an asynchronous call, it will return immediately. Register
424 * for {@link #ACTION_DISCOVERY_STARTED} and {@link
425 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
426 * discovery starts and completes. Register for {@link
427 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
428 * are found.
429 * <p>Device discovery is a heavyweight procedure. New connections to
430 * remote Bluetooth devices should not be attempted while discovery is in
431 * progress, and existing connections will experience limited bandwidth
432 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
433 * discovery.
434 * <p>Device discovery will only find remote devices that are currently
435 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
436 * not discoverable by default, and need to be entered into a special mode.
437 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
438 *
439 * @return true on success, false on error
440 */
Nick Pellybd022f42009-08-14 18:33:38 -0700441 public boolean startDiscovery() {
442 try {
443 return mService.startDiscovery();
444 } catch (RemoteException e) {Log.e(TAG, "", e);}
445 return false;
446 }
447
Nick Pelly005b2282009-09-10 10:21:56 -0700448 /**
449 * Cancel the current device discovery process.
450 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
451 *
452 * @return true on success, false on error
453 */
454 public boolean cancelDiscovery() {
Nick Pellybd022f42009-08-14 18:33:38 -0700455 try {
456 mService.cancelDiscovery();
457 } catch (RemoteException e) {Log.e(TAG, "", e);}
Nick Pelly005b2282009-09-10 10:21:56 -0700458 return false;
Nick Pellybd022f42009-08-14 18:33:38 -0700459 }
460
Nick Pelly005b2282009-09-10 10:21:56 -0700461 /**
462 * Return true if the local Bluetooth adapter is currently in the device
463 * discovery process.
464 * <p>Device discovery is a heavyweight procedure. New connections to
465 * remote Bluetooth devices should not be attempted while discovery is in
466 * progress, and existing connections will experience limited bandwidth
467 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
468 * discovery.
469 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
470 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
471 * starts or completes.
472 *
473 * @return true if discovering
474 */
Nick Pellybd022f42009-08-14 18:33:38 -0700475 public boolean isDiscovering() {
476 try {
477 return mService.isDiscovering();
478 } catch (RemoteException e) {Log.e(TAG, "", e);}
479 return false;
480 }
481
482 /**
Nick Pelly005b2282009-09-10 10:21:56 -0700483 * Return the set of {@link BluetoothDevice} objects that are bonded
484 * (paired) to the local adapter.
Nick Pellybd022f42009-08-14 18:33:38 -0700485 *
Nick Pelly005b2282009-09-10 10:21:56 -0700486 * @return unmodifiable set of {@link BluetoothDevice}, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -0700487 */
488 public Set<BluetoothDevice> getBondedDevices() {
489 try {
490 return toDeviceSet(mService.listBonds());
491 } catch (RemoteException e) {Log.e(TAG, "", e);}
492 return null;
493 }
494
495 /**
Nick Pelly45e27042009-08-19 11:00:00 -0700496 * Create a listening, secure RFCOMM Bluetooth socket.
497 * <p>A remote device connecting to this socket will be authenticated and
Nick Pellybd022f42009-08-14 18:33:38 -0700498 * communication on this socket will be encrypted.
Nick Pelly45e27042009-08-19 11:00:00 -0700499 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
500 * connections to listening {@link BluetoothServerSocket}.
501 * <p>Valid RFCOMM channels are in range 1 to 30.
Nick Pellycf440592009-09-08 10:12:06 -0700502 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pelly45e27042009-08-19 11:00:00 -0700503 * @param channel RFCOMM channel to listen on
504 * @return a listening RFCOMM BluetoothServerSocket
505 * @throws IOException on error, for example Bluetooth not available, or
506 * insufficient permissions, or channel in use.
Nick Pellybd022f42009-08-14 18:33:38 -0700507 */
Nick Pelly45e27042009-08-19 11:00:00 -0700508 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
Nick Pellybd022f42009-08-14 18:33:38 -0700509 BluetoothServerSocket socket = new BluetoothServerSocket(
Nick Pelly45e27042009-08-19 11:00:00 -0700510 BluetoothSocket.TYPE_RFCOMM, true, true, channel);
Nick Pellybd022f42009-08-14 18:33:38 -0700511 try {
Nick Pelly71c3c782009-09-02 11:51:35 -0700512 socket.mSocket.bindListen();
Nick Pellybd022f42009-08-14 18:33:38 -0700513 } catch (IOException e) {
514 try {
515 socket.close();
516 } catch (IOException e2) { }
517 throw e;
518 }
519 return socket;
520 }
521
522 /**
523 * Construct an unencrypted, unauthenticated, RFCOMM server socket.
524 * Call #accept to retrieve connections to this socket.
525 * @return An RFCOMM BluetoothServerSocket
526 * @throws IOException On error, for example Bluetooth not available, or
527 * insufficient permissions.
Nick Pelly45e27042009-08-19 11:00:00 -0700528 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700529 */
530 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
531 BluetoothServerSocket socket = new BluetoothServerSocket(
532 BluetoothSocket.TYPE_RFCOMM, false, false, port);
533 try {
Nick Pelly71c3c782009-09-02 11:51:35 -0700534 socket.mSocket.bindListen();
Nick Pellybd022f42009-08-14 18:33:38 -0700535 } catch (IOException e) {
536 try {
537 socket.close();
538 } catch (IOException e2) { }
539 throw e;
540 }
541 return socket;
542 }
543
544 /**
545 * Construct a SCO server socket.
546 * Call #accept to retrieve connections to this socket.
547 * @return A SCO BluetoothServerSocket
548 * @throws IOException On error, for example Bluetooth not available, or
549 * insufficient permissions.
Nick Pelly45e27042009-08-19 11:00:00 -0700550 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -0700551 */
552 public static BluetoothServerSocket listenUsingScoOn() throws IOException {
553 BluetoothServerSocket socket = new BluetoothServerSocket(
554 BluetoothSocket.TYPE_SCO, false, false, -1);
555 try {
Nick Pelly71c3c782009-09-02 11:51:35 -0700556 socket.mSocket.bindListen();
Nick Pellybd022f42009-08-14 18:33:38 -0700557 } catch (IOException e) {
558 try {
559 socket.close();
560 } catch (IOException e2) { }
561 throw e;
562 }
563 return socket;
564 }
565
566 private Set<BluetoothDevice> toDeviceSet(String[] addresses) {
567 Set<BluetoothDevice> devices = new HashSet<BluetoothDevice>(addresses.length);
568 for (int i = 0; i < addresses.length; i++) {
569 devices.add(getRemoteDevice(addresses[i]));
570 }
571 return Collections.unmodifiableSet(devices);
572 }
Nick Pelly005b2282009-09-10 10:21:56 -0700573
574 /**
575 * Validate a Bluetooth address, such as "00:43:A8:23:10:F0"
Nick Pelly55e66f12009-09-18 11:37:06 -0700576 * <p>Alphabetic characters must be uppercase to be valid.
Nick Pelly005b2282009-09-10 10:21:56 -0700577 *
578 * @param address Bluetooth address as string
579 * @return true if the address is valid, false otherwise
580 */
581 public static boolean checkBluetoothAddress(String address) {
582 if (address == null || address.length() != ADDRESS_LENGTH) {
583 return false;
584 }
585 for (int i = 0; i < ADDRESS_LENGTH; i++) {
586 char c = address.charAt(i);
587 switch (i % 3) {
588 case 0:
589 case 1:
Nick Pelly55e66f12009-09-18 11:37:06 -0700590 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
591 // hex character, OK
592 break;
Nick Pelly005b2282009-09-10 10:21:56 -0700593 }
594 return false;
595 case 2:
596 if (c == ':') {
597 break; // OK
598 }
599 return false;
600 }
601 }
602 return true;
603 }
Nick Pellybd022f42009-08-14 18:33:38 -0700604}