基础:

这篇文档描述了怎么使用Android Bluetooth APIs完成数据交换的四个主要的任务:创建Bluetooth,找到本地区域可用的蓝牙设备或匹配的蓝牙设备,连接设备,传输数据。

所有的Bluetooth APIs都在android.bluetooth包下。下面是创建蓝牙连接需要实现的类和接口:

BluetoothAdapter:

表示本地的蓝牙适配器。BluetoothAdapter是所有蓝牙交换的接入点。使用它,你可以发现其他的蓝牙设备,查找一些匹配的设备,用MAC地址来实例化一个BluetoothDevice。创建一个BluetoothServerSocket来监听其他设备,进而和它们进行通信。

BluetoothDevice:

表示远程的蓝牙设备。用它通过BluetoothSocket来请求与远程的设备进行连接。后者查询设备的基本信息,例如名称,地址,类或者结合的状态。

BluetoothSocket:

表示一个Bluetooth socket接口(与TCP socket相似)。它是一个连接点,运行设备通过InputStream和OutputStream的形式来交换数据。

BluetoothServiceSocket:

表示一个打开服务socket,用来监听收到的请求(与TCP server socket相似)。为了连接设备,一个设备必须打开服务socket。当一个远程的设备请求连接的时候,当连接被接收的时候,BluetoothServiceSocket返回一个BluetoothSocket。

BluetoothClass:

描述蓝牙设备的一般特征和性能。这是个只读的一系列属性。定义了主要和最小的设备类和服务。然而,它描述的设备属性和和服务是不完全可靠的,但是,在表示设备类型时,它是有用的。

BluetoothProfile:

一个代表蓝牙属性的接口。指基于无线蓝牙交流的无线接口规则。

BluetoothHeadset:

提供在手机手机上使用蓝牙耳机的支持。

BluetoothA2dp:

定义什么样的数据可以在蓝牙之间传递。

BluetoothProfiles.ServiceListener:

当蓝牙设备连接或者断开时,用它来通知BluetoothProfiles IPC客户端。它是一个接口。

蓝牙权限:

为了使用蓝牙,你必须在你的应用程序中声明权限。

<manifest ... >
 <uses-permission android:name="android.permission.BLUETOOTH" />
 ...
</manifest>

两种权限:BLUETOOTH和BLUETOOTH ADMIN.

当使用BLUETOOTH ADMIN时,一定要声明BLUETOOTH。

创建Bluetooth:

1.得到BluetoothAdaper。

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}

如何不为null,说明本机可用蓝牙设备。

2.使用Bluetooth。

if (mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent  = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
 startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

查看匹配的设备:

Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
 mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}

发现设备:

// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver  = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
 mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
 registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy

连接设备:

做为一个服务者:

public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
 tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) { }
 mmServerSocket = tmp;
}

public void run() {
BluetoothSocket socket  = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
 socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
 manageConnectedSocket(socket);
 mmServerSocket.close();
break;
}
}
}

/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
 mmServerSocket.close();
} catch (IOException e) { }
}
}

做为客户端:

private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;

public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp  = null;
 mmDevice = device;

// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
 tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
 mmSocket = tmp;
}

public void run() {
// Cancel discovery because it will slow down the connection
 mBluetoothAdapter.cancelDiscovery();

try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
 mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
 mmSocket.close();
} catch (IOException closeException) { }
return;
}

// Do work to manage the connection (in a separate thread)
 manageConnectedSocket(mmSocket);
}

/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
 mmSocket.close();
} catch (IOException e) { }
}
}

管理连接:

private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;

public ConnectedThread(BluetoothSocket socket) {
 mmSocket = socket;
InputStream tmpIn  = null;
OutputStream tmpOut  = null;

// Get the input and output streams, using temp objects because
// member streams are final
try {
 tmpIn = socket.getInputStream();
 tmpOut = socket.getOutputStream();
} catch (IOException e) { }

 mmInStream = tmpIn;
 mmOutStream = tmpOut;
}

public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()

// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
 bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
 mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}

/* Call this from the main Activity to send data to the remote device */
public void write(byte[] bytes) {
try {
 mmOutStream.write(bytes);
} catch (IOException e) { }
}

/* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
 mmSocket.close();
} catch (IOException e) { }
}
}