<span style="color: rgba(0, 0, 0, 0.870588); font-family: Roboto, sans-serif; font-size: 28px; line-height: 32px; background-color: rgb(255, 255, 255);">The Basics</span>
基础API:
BluetoothAdapter 该类代表着本地蓝牙的适配器。
作用:
1、它是蓝牙间交互的入口点,利用它可以搜索其它的蓝牙设备,搜索与本机蓝牙已绑定(配对)的蓝牙设备,
2、利用MAC地址可以实例化一个蓝牙设备对象
3、创建一个服务端的Socket来监听与其它蓝牙设备通讯。
BluetoothDevice 该类表示远程蓝牙设备。
作用:
1、通过BluetoothSocket与其它绑定的设备进行通信;
2、查询该蓝牙设备的名称、地址、类以及绑定状态
BluetoothSocket 该类代表着蓝牙Socket接口
作用:
1、蓝牙设备间进行输入流、输出流数据交互的连接点
BluetoothServerSocket 该类表示开放的服务端Socket
作用:
1、监听所有客户端Socket的请求
Bluetooth Permissions
如果你想在你的应用程序中使用蓝牙功能你必须定义相关的权限声明,有两种权限需要声明BLUETOOTH_ADMIN和BLUETOOTH。如果你想你的应用程序开启的时候就会被其它设备发现,你必须声明BlUETOOTH_ADMIN权限,声明BLUETOOTH_ADMIN权限的话,还必须声明BLUETOOTH权限。
Setting Up Bluetooth
在你的应用程序通过蓝牙进行数据交互之前,你必须保证你的设备支持蓝牙功能,如果支持的话,还要确保蓝牙功能是启用的。
1、检查设备是否支持蓝牙功能:
可以通过BlueToothAdapter是否为null来判断该设备是否支持蓝牙功能。如果为null的话则表示不支持,如果不为null的话,则表示支持蓝牙设备。
<span style="font-size:18px;">BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}</span>
2、启用蓝牙功能:
可以通过BlueToothAdapter的IsEnabled方法判断来呀是否启用,如果没有启用的话,可以通过系统隐式的Intent打开启用蓝牙的界面。
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
Finding Devices
通过BlueToothAdpter可以搜索附近的蓝牙设备以及已经和该设备已经绑定的蓝牙设备。
1、搜索附近的蓝牙设备:
// 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
2、搜索与该设备已绑定的蓝牙设备
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());
}
}
3、该蓝牙设备与其它蓝牙设备的配对
BlueToothAdapter.cancelDiscovery();
blueToothAddress=item.getBluetoothAddress();
BluetoothDevice device = blueToothAdapter().getRemoteDevice(BluetoothMsg.BlueToothAddress);
if (device.getBondState() ==BluetoothDevice.BOND_NONE) {
try {
//利用反射方法调用BluetoothDevice.createBond(BluetoothDevice remoteDevice);
Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
createBondMethod.invoke(device);
} catch (IllegalArgumentException e)
Connecting Devices
Connecting as a server(服务端)如果你想通过蓝牙连接两台设备,你必须保证其中的一个持有一个开放的BlueToorthServerSocket,这样做的目的是让这个开放的BlueToothServerSocket来监听其它Socket的发送的请求。考虑性能问题,所以创建BlueToothServerSocket必须在线程中操作。另外,当服务端接受到一个请求后,就要重新开一个线程来处理接收到的数据以及发送信息到客户端。
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
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) { }
}
}
Connecting as a client
创建一个请求的客户端,和服务端一样,请求连接的操作需要在线程里进行,以及连接成功后重新开启一个线程处理消息的接收和发送。
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) { }
}
}
Managing a Connection
下面的线程就是处理消息的: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) { }
}
}