最近項目中用到傳統藍牙連接設備通訊,折騰了一週把基本功能實現了,這裏簡單記錄一下。
藍牙設備: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);
}
本文僅將思路和一些代碼片段寫下來記錄一下,希望有用!