前言
经过一个多月的时间蓝牙多设备连接的重构终于告一段落了,这次的重构不止是代码方面的完善,还结合了一些用户的使用场景,另外增加一些离线操作,使手机端对蓝牙的操作更加的便捷,对蓝牙设备的管理更加统一。
场景分析
支持的场景
- 多设备连接(一个血压计和一个厨房秤)—— 在饭点,使用同一个手机连接血压计和厨房秤,病人在测量血压,家人在做饭称量菜品。
- 把连接到的设备信息保存到本地——方便下次自动连接。
- 把蓝牙返回结果保存本地——方便在其他页面获取数据显示UI。
- 同种设备只能连接一个——保持连接设备的唯一性,防止找不到连接的设备。
- 可以在蓝牙列表扫描到所支持的设备,并连接、断开和删除蓝牙——对蓝牙设备进行管理,查看自己扫描到的设备,并查看蓝牙的连接状态。
- 启动 App 可以自动连接上一次已经连接过的设备——可以快速的使用设备。
暂不支持的场景
- 同时扫描多个同种设备——可能导致连接到了设备,而不知道连接的是哪个设备。
- 新旧设备替换——不能直接进行替换,需要在设备列表页面删除旧设备,之后关掉旧设备,重新扫描新设备。
场景实现
效果展示
多设备连接
现在一台手机可以连接多个设备,例如连接蓝牙耳机,智能手环等。既然手机可以连接多个设备,那么移动应用也是可以连接多个设备的(血压计、心率计等),下面就是移动应用 App 实现多设备连接的思路方法。
实现思路
关于蓝牙连接,主要是 BluetoothGatt 这个类型,每个蓝牙的连接都需要用独立且唯一的 BluetoothGatt 。开始的想法是每个蓝牙都重新创建一个 Service, 在新的 Service 内使用 BluetoothGatt 进行连接,然而这个方法是可以实现多设备连接,但是创建多个 Service 对手机消耗比较大。之后,想到把 BluetoothGatt 保存起来不就可以了么,那用什么保存呢,既可以临时保存多个,又可以按照需要获取相对应的 BluetoothGatt 。在 java 里面有个类型 Map(String, Object) ,它是以 key-value 的形式存储到 Map 中。可以根据当时的 Key 来取相应的 Value 值,而且在关掉进程时相应的变量也就释放了。
代码实现
private Map<String, BluetoothGatt> mBluetoothGattMap = new HashMap<>(); //临时保存 BluetoothGatt
private Map<String, BluetoothGattCharacteristic> mGattCharacteristicMap = new HashMap<>();// 临时保存蓝牙的特征值 Characteristic
private Map<String, BluetoothInfo> mBluetoothInfoMap = new HashMap<>();// 临时保存自己设置的蓝牙信息(deviceName、deviceType、startCMD、stopCMD 等)
private Map<BluetoothGatt, String> mDeviceTypeMap = new HashMap<>();// 临时存储 deviceType
private Map<String, GGBLEDeviceEntity> mConnectModelMap = new HashMap<>();// 临时存储 已连接的设备
//...
/**
* 连接设备
*
* @param deviceType 设备类型
* @return true 连接成功,false连接失败
*/
boolean connectBluetooth(Context context, String deviceType, String deviceAddress) {
//...
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceAddress);//根据 mac 地址获取蓝牙设备
//...
BluetoothGatt bluetoothGatt = device.connectGatt(this, false, mGattCallback);// 对蓝牙进行连接操作
//...
mBluetoothGattMap.put(deviceType, bluetoothGatt);//把 BluetoothGatt 已 key-value 的形式临时保存起来
return true;
}
设备自动连接
要有良好的用户操作体验,我们应该避免对一些无关的操作重复进行。例如我们第一次打开应用连接了蓝牙设备,以后再打开 App 不需要重复操作连接过程,用户就可以少打开一个页面,少点击两次按钮。减少用户重复操作,让用户直接进入正题,提高主功能的使用率。
实现思路
在 Android 中连接蓝牙的方法是