最近项目中用到传统蓝牙连接设备通讯,折腾了一周把基本功能实现了,这里简单记录一下。
蓝牙设备:HC-05蓝牙模块
主要功能:-首次手动配对;-自动连接;-连接超时或异常处理;-中断监听;-中断后检测重新连接
测试版本:Android 6.0
实现经典蓝牙功能的基本逻辑:
整个蓝牙功能逻辑如上图所示,其中比较关键的是蓝牙自动连接和断开后重新连接。关于蓝牙自动连接,本文采用的是首次配对后,利用SharedPreferences将目标蓝牙设备的MAC地址存入,等开始扫描时,采用扫描到的设备MAC地址(与SharedPreferences文件中的MAC地址是否匹配)+设备名双重检测方式判断当前设备是否为目标蓝牙设备,从而进行蓝牙自动连接,该部分核心代码如下:
if (device.getBondState() == BluetoothDevice.BOND_BONDED) {//已配对设备进行操作
if (device.getName().substring(0, 3).equals("Spe")) {
Tools.saveTempInfos(context,
"BluetoothAddress", "mac_address", device.getAddress());
messageListence.OnReceived(device.getAddress());
} else {
messageListence.OnReceived(BLUETOOTH_EXCEPTION);
}
} else {
System.out.println("设备未配对!");
}
连接超时或异常处理,该部分也是蓝牙连接的一个重要部分,因为超时或者异常均会影响用户体验,这里参考了https://blog.csdn.net/vic_torsun/article/details/79650865一文,解决了该问题,代码如下:
try {
socket = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
System.out.println(socket.isConnected());
socket.connect();
System.out.println(socket.isConnected());
os = socket.getOutputStream();
is = socket.getInputStream();
} catch (IOException e) {
Toast.makeText(context, "1.连接失败!", Toast.LENGTH_SHORT).show();
try {
socket = (BluetoothSocket) device.getClass().
getMethod("createRfcommSocket", new Class[]{int.class}).invoke(device, 1);
socket.connect();
} catch (Exception e1) {
try {
socket.close();
} catch (IOException e2) {
e2.printStackTrace();
}
Toast.makeText(context, "未搜索到蓝牙设备或蓝牙设备未打开!",
Toast.LENGTH_SHORT).show();
}
return;
} catch (Exception e) {
e.printStackTrace();
}
断后重新连接则需要设置实时监听,利用广播进行蓝牙状态监听,同时在广播中设置接口将对应的信息返回到广播接收者,实现逻辑很简单:断开——>监听断开——>尝试重新连接,其中需要加入心跳监测,这里利用的是Handler+Runnable的方式定时进行监测,具体代码如下:
private Handler blueHandler = new Handler();
private Runnable blueRunnable = new Runnable() {
@Override
public void run() {
System.out.println("定时Handler!");
if (IsConnect == false) {
bluetoothTools.cancelDiscovering();
System.out.println("设备未连接!");
bluetoothTools.startDiscovery();
} else {
System.out.println("设备连接正常!");
}
blueHandler.postDelayed(this, Heart_BEAT_RATE);
}
};
在连接成功后和断开连接后,分别重置监听器,这样可以避免监听过程中发生连接冲突,从而导致异常,中断后重新连接的部分代码:
else if (message.equals(BTReceiver.ACTION_ACL_DISCONNECTED)) {
IsConnect = false;
blueHandler.removeCallbacks(blueRunnable);
blueHandler.postDelayed(blueRunnable, Heart_BEAT_RATE);
}
本文仅将思路和一些代码片段写下来记录一下,希望有用!