基础:
这篇文档描述了怎么使用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) { }
}
}