android蓝牙开发

最近在做一个蓝牙音箱的项目,该项目用到两个蓝牙,一个音频蓝牙(3.0)模块用来传音频,一个ble蓝牙(4.0)模块用来透传数据。项目做完,赶紧记录一下。

扫描蓝牙

扫描蓝牙有以下两种方式:

1
2
mBluetoothAdapter.startDiscovery();
mBluetoothAdapter.startLeScan();

第一种能扫描出所有蓝牙设备,扫描结果通过广播的方式回调。第二种方式只能扫描出BLE设备,扫描结果通过接口回调。注意除了给应用添加蓝牙权限,还需要额外添加位置权限

1
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

否则在6.0以上的手机上运行搜索不到蓝牙设备。

连接蓝牙

连接蓝牙之前,需要先检查应用权限及打开蓝牙。
音频蓝牙连接步骤:

BLE蓝牙连接步骤:

由于这里同时使用到了两种蓝牙设备,为了简化连接操作,在每次连接时,软件优先去连接音频蓝牙,当音频蓝牙连接成功后,再自动去连ble蓝牙,再统一在广播里处理连接结果,这样就能做到只连接一次就可以同时连上两个蓝牙。关于蓝牙连接的状态,有如下需要注意的:

  • 音频蓝牙一旦被连接上,其他手机将不再搜索得到
  • ble蓝牙一旦被连接上,其他手机将不再搜索得到,但是调用了mBluetoothGatt.disconnect()后,其他手机可以搜索到(经测试,在华为P9上调用了disconnect后其他手机也搜索不到,必须到设置里取消配对后才可以搜索到)
  • 音频蓝牙只要被连接过,之后上电会自动被连接
  • ble蓝牙只能通过代码连接才可以进行通信,在系统的设置里连接不能进行通信

由于有时候音频蓝牙会自动连接,这个时候在应用里是扫描不到的,所有需要判断手机当前是否已连接上音频蓝牙,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private BluetoothProfile.ServiceListener mConnectedListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceDisconnected(int profile) {

}
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
try {
if (profile == BluetoothProfile.A2DP) {
a2dp = (BluetoothA2dp) proxy;
List<BluetoothDevice> connectedDevices = proxy.getConnectedDevices();
for (BluetoothDevice device : connectedDevices) {
if (mName.replace("z", "").equals(device.getName())) {
connectBleDevice();
return;
}
}
showToast(getString(R.string.connect_failed));
}
} catch (Exception e) {
e.printStackTrace();
}
}
};