From f2793150f3b3b36ae7425667f670b341a8b3d6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E5=87=A4=E5=90=89?= Date: Fri, 20 Jun 2025 10:22:35 +0800 Subject: [PATCH] =?UTF-8?q?feta:=E5=A2=9E=E5=8A=A0=E8=93=9D=E7=89=99?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=E8=B0=83=E7=94=A8=E9=99=90?= =?UTF-8?q?=E5=88=B6=EF=BC=8C=E6=9B=B4=E6=94=B9=E8=93=9D=E7=89=99=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E5=88=97=E8=A1=A8=E6=8E=A8=E9=80=81=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E4=B8=BA=E6=9C=89=E5=8F=98=E5=8C=96=E6=97=B6=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 +- .../com/iflytop/profilometer/api/ble/BleApi.java | 75 +++++++++++--------- .../profilometer/api/ws/BleWebsocketManager.java | 82 +++++++++++----------- .../profilometer/core/bluetooth/BleManager.java | 39 +++++----- 4 files changed, 105 insertions(+), 95 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a3e3c2c..33db359 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,9 +14,9 @@ android { minSdk 26 targetSdk 35 // 指定应用内部版本号 - versionCode 30 + versionCode 31 // 指定展示给用户的版本号 - versionName "1.1.30" + versionName "1.1.31" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/com/iflytop/profilometer/api/ble/BleApi.java b/app/src/main/java/com/iflytop/profilometer/api/ble/BleApi.java index eacb8ad..c277a37 100644 --- a/app/src/main/java/com/iflytop/profilometer/api/ble/BleApi.java +++ b/app/src/main/java/com/iflytop/profilometer/api/ble/BleApi.java @@ -1,10 +1,8 @@ package com.iflytop.profilometer.api.ble; -import android.bluetooth.BluetoothGatt; import android.content.Context; import android.util.Log; -import com.iflytop.profilometer.api.ws.BleWebsocketManager; import com.iflytop.profilometer.common.constant.LogTag; import com.iflytop.profilometer.common.result.Result; import com.iflytop.profilometer.core.bluetooth.BleDeviceDriver; @@ -12,24 +10,37 @@ import com.iflytop.profilometer.core.bluetooth.BleManager; import com.iflytop.profilometer.core.bluetooth.BlePingManager; import com.iflytop.profilometer.core.system.SystemService; +import java.util.concurrent.atomic.AtomicBoolean; + /** * 蓝牙接口 */ public class BleApi { - private static final String TAG = "BleApi"; private final Context context; public BleApi(Context context) { this.context = context.getApplicationContext(); } + // 最小调用间隔(毫秒),根据你的需求自由调整 + private static final long MIN_START_INTERVAL_MS = 3000; + // 上次调用时间 + private static volatile long lastStartTime = 0; + + private final AtomicBoolean isConnecting = new AtomicBoolean(false); + /** * 开始获取蓝牙设备列表 */ public String start() { + long now = System.currentTimeMillis(); + if (now - lastStartTime < MIN_START_INTERVAL_MS) { + Log.w(LogTag.PROFILOMENTER, "start 调用过于频繁,忽略本次请求"); + return Result.failed("操作过于频繁,请慢一点"); + } + lastStartTime = now; try { BleManager.getInstance().startScan(); - BleWebsocketManager.getInstance().startWsPush(); return Result.success(); } catch (Exception e) { Log.e(LogTag.PROFILOMENTER, "开始获取蓝牙列表失败", e); @@ -42,7 +53,6 @@ public class BleApi { */ public String stop() { try { - BleWebsocketManager.getInstance().stopWsPush(); BleManager.getInstance().stopScan(); return Result.success(); } catch (Exception e) { @@ -55,25 +65,32 @@ public class BleApi { * 链接蓝牙设备 */ public String connect(String mac) { - try { - BleWebsocketManager.getInstance().stopWsPush(); - BleManager.getInstance().stopScan();//连接后停止扫描 - boolean connect = BleManager.getInstance().connectToDeviceSync(mac); - if (connect) { - BleDeviceDriver bleDeviceDriver = SystemService.getInstance().getBleDeviceDriver(); - bleDeviceDriver.stopSampling(); - BlePingManager.getInstance().startPing(); - return Result.success(); - } else { - throw new RuntimeException(); + // 如果已经有一次连接在进行,就立刻返回 + if (!isConnecting.compareAndSet(false, true)) { + Log.w(LogTag.PROFILOMENTER, "已有连接操作进行中,忽略本次请求"); + return Result.failed("连接中,请稍后再试"); + } + for (int i = 0; i < 2; i++) { + try { + boolean connect = BleManager.getInstance().connectToDeviceSync(mac); + if (connect) { + BleDeviceDriver bleDeviceDriver = SystemService.getInstance().getBleDeviceDriver(); + bleDeviceDriver.stopSampling(); + BlePingManager.getInstance().startPing(); + return Result.success(); + } else { + throw new RuntimeException(); + } + } catch (Exception e) { + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + Log.e(LogTag.PROFILOMENTER, "链接蓝牙设备失败,第" + (i + 1) + "次", e); } - } catch (Exception e) { - BleWebsocketManager.getInstance().startWsPush();//链接失败后继续扫描并推送 - BleManager.getInstance().startScan(); - BlePingManager.getInstance().stopPing(); - Log.e(LogTag.PROFILOMENTER, "链接蓝牙设备失败", e); - return Result.failed("链接蓝牙设备失败"); } + return Result.failed("链接蓝牙设备失败"); } /** @@ -82,17 +99,11 @@ public class BleApi { public String disconnect() { try { BleDeviceDriver bleDeviceDriver = SystemService.getInstance().getBleDeviceDriver(); - bleDeviceDriver.stopSampling(); - - BleManager.getInstance().disconnect(); - BlePingManager.getInstance().stopPing(); - BleManager.getInstance().startScan();//断开连接后开始扫描 - BleWebsocketManager.getInstance().startWsPush(); + bleDeviceDriver.stopSampling();//停止采样 + BlePingManager.getInstance().stopPing();//停止发送ping + BleManager.getInstance().disconnect();//断开链接 return Result.success(); - } catch (Exception e) { - BleWebsocketManager.getInstance().stopWsPush();//断开连接失败 - BleManager.getInstance().stopScan(); - BlePingManager.getInstance().startPing(); + } catch (Exception e) {//断开连接失败 Log.e(LogTag.PROFILOMENTER, "断开蓝牙设备链接失败", e); return Result.failed("断开蓝牙设备链接失败"); } diff --git a/app/src/main/java/com/iflytop/profilometer/api/ws/BleWebsocketManager.java b/app/src/main/java/com/iflytop/profilometer/api/ws/BleWebsocketManager.java index 7ba46d2..dfd40a3 100644 --- a/app/src/main/java/com/iflytop/profilometer/api/ws/BleWebsocketManager.java +++ b/app/src/main/java/com/iflytop/profilometer/api/ws/BleWebsocketManager.java @@ -35,51 +35,53 @@ public class BleWebsocketManager { } - /** - * 开始定时任务 - */ +// /** +// * 开始定时任务 +// */ +// @SuppressLint("MissingPermission") +// public void startWsPush() { +// stopWsPush(); +// scheduledTask = scheduler.scheduleWithFixedDelay(this::pushBleList, 0, 50, TimeUnit.MILLISECONDS); +// } @SuppressLint("MissingPermission") - public void startWsPush() { - stopWsPush(); - scheduledTask = scheduler.scheduleWithFixedDelay(() -> { - List scannedDevices = BleManager.getInstance().getScannedDevices(); - scannedDevices.sort(Comparator.comparing(BluetoothDevice::getAddress)); - Map listMap = new HashMap<>(); - listMap.put("type", "ble-list"); - List> bleList = new ArrayList<>(); - BluetoothGatt gatt = BleManager.getInstance().getBluetoothGatt(); - if (gatt != null) { + public void pushBleList(){ + List scannedDevices = BleManager.getInstance().getScannedDevices(); + scannedDevices.sort(Comparator.comparing(BluetoothDevice::getAddress)); + Map listMap = new HashMap<>(); + listMap.put("type", "ble-list"); + List> bleList = new ArrayList<>(); + BluetoothGatt gatt = BleManager.getInstance().getBluetoothGatt(); + if (gatt != null) { + Map bleMap = new HashMap<>(); + BluetoothDevice gattDevice = gatt.getDevice(); + bleMap.put("mac", gattDevice.getAddress()); + bleMap.put("name", gattDevice.getName()); + bleMap.put("linked", true); + bleList.add(bleMap); + } + for (BluetoothDevice bluetoothDevice : scannedDevices) { + String mac = bluetoothDevice.getAddress(); + boolean exists = bleList.stream().anyMatch(map -> mac.equals(map.get("mac"))); + if (!exists) { Map bleMap = new HashMap<>(); - BluetoothDevice gattDevice = gatt.getDevice(); - bleMap.put("mac", gattDevice.getAddress()); - bleMap.put("name", gattDevice.getName()); - bleMap.put("linked", true); + bleMap.put("mac", mac); + bleMap.put("name", bluetoothDevice.getName() == null ? "未命名" : bluetoothDevice.getName()); + bleMap.put("linked", false); bleList.add(bleMap); } - for (BluetoothDevice bluetoothDevice : scannedDevices) { - String mac = bluetoothDevice.getAddress(); - boolean exists = bleList.stream().anyMatch(map -> mac.equals(map.get("mac"))); - if (!exists) { - Map bleMap = new HashMap<>(); - bleMap.put("mac", mac); - bleMap.put("name", bluetoothDevice.getName() == null ? "未命名" : bluetoothDevice.getName()); - bleMap.put("linked", false); - bleList.add(bleMap); - } - } - bleList.sort(Comparator.comparing(map -> (String) map.get("mac"))); - listMap.put("data", bleList); - WebSocketManager.send(JSONUtil.toJsonStr(listMap)); - }, 0, 100, TimeUnit.MILLISECONDS); - } - - /** - * 结束定时任务 - */ - public void stopWsPush() { - if (scheduledTask != null && !scheduledTask.isCancelled()) { - scheduledTask.cancel(false); } + bleList.sort(Comparator.comparing(map -> (String) map.get("mac"))); + listMap.put("data", bleList); + WebSocketManager.send(JSONUtil.toJsonStr(listMap)); } +// +// /** +// * 结束定时任务 +// */ +// public void stopWsPush() { +// if (scheduledTask != null && !scheduledTask.isCancelled()) { +// scheduledTask.cancel(false); +// } +// } } diff --git a/app/src/main/java/com/iflytop/profilometer/core/bluetooth/BleManager.java b/app/src/main/java/com/iflytop/profilometer/core/bluetooth/BleManager.java index 1f62828..06b62ed 100644 --- a/app/src/main/java/com/iflytop/profilometer/core/bluetooth/BleManager.java +++ b/app/src/main/java/com/iflytop/profilometer/core/bluetooth/BleManager.java @@ -30,6 +30,7 @@ import android.widget.Toast; import androidx.core.content.ContextCompat; +import com.iflytop.profilometer.api.ws.BleWebsocketManager; import com.iflytop.profilometer.common.constant.LogTag; import com.iflytop.profilometer.core.migration.channel.BleDeviceUartChannel; import com.iflytop.profilometer.core.system.DeviceState; @@ -53,7 +54,6 @@ import java.util.concurrent.atomic.AtomicBoolean; * - 低于 Android 12 的设备,BLUETOOTH_SCAN 和 BLUETOOTH_CONNECT 权限直接被视为已授予。 */ public class BleManager { - private static final String TAG = "BLEManager"; // 与设备通信所用的 UUID(请根据你的设备替换下列 UUID) public static final UUID SERVICE_UUID = UUID.fromString("6E8F0001-B5A3-F393-E0A9-E50E24DCCA9E"); @@ -102,7 +102,8 @@ public class BleManager { for (BluetoothDevice device : toRemove) { deviceLastSeenMap.remove(device); scannedDevices.remove(device); - Log.d(TAG, "移除超时设备: " + device.getName() + " - " + device.getAddress()); + BleWebsocketManager.getInstance().pushBleList(); + Log.d(LogTag.PROFILOMENTER, "移除超时设备: " + device.getName() + " - " + device.getAddress()); } } cleanupHandler.postDelayed(this, CLEANUP_INTERVAL); @@ -136,6 +137,7 @@ public class BleManager { if (bluetoothManager != null) { bluetoothAdapter = bluetoothManager.getAdapter(); } + cleanupHandler.postDelayed(cleanupRunnable, CLEANUP_INTERVAL); } /** @@ -244,8 +246,8 @@ public class BleManager { return; } // 清空之前的数据 - scannedDevices.clear(); - deviceLastSeenMap.clear(); +// scannedDevices.clear(); +// deviceLastSeenMap.clear(); // 定义扫描回调 scanCallback = new ScanCallback() { @@ -263,15 +265,14 @@ public class BleManager { String storedMac = prefs.getString("mac_address", null); if (storedMac != null && storedMac.equals(address)) { if (!isConnected()) { - stopScan(); connectToDeviceSync(address); BlePingManager.getInstance().startPing(); } - return; } if (!scannedDevices.contains(device)) { scannedDevices.add(device); - Log.d(TAG, "设备 " + device.getName() + "," + device.getAddress() + " ,已添加至列表"); + BleWebsocketManager.getInstance().pushBleList(); + Log.d(LogTag.PROFILOMENTER, "设备 " + device.getName() + "," + device.getAddress() + " ,已添加至列表"); } } } @@ -296,7 +297,8 @@ public class BleManager { } if (!scannedDevices.contains(device)) { scannedDevices.add(device); - Log.d(TAG, "设备 " + device.getName() + "," + device.getAddress() + " ,已添加至列表 (batch)"); + BleWebsocketManager.getInstance().pushBleList(); + Log.d(LogTag.PROFILOMENTER, "设备 " + device.getName() + "," + device.getAddress() + " ,已添加至列表 (batch)"); } } } @@ -315,7 +317,7 @@ public class BleManager { .build(); bluetoothLeScanner.startScan(null, settings, scanCallback); - cleanupHandler.postDelayed(cleanupRunnable, CLEANUP_INTERVAL); + Log.i(LogTag.PROFILOMENTER, "开始扫描蓝牙列表"); } @@ -336,7 +338,6 @@ public class BleManager { bluetoothLeScanner.stopScan(scanCallback); scanCallback = null; } - cleanupHandler.removeCallbacks(cleanupRunnable); Log.i(LogTag.PROFILOMENTER, "结束扫描蓝牙列表"); } @@ -375,7 +376,7 @@ public class BleManager { if (bluetoothGatt != null) { BluetoothDevice connectedDevice = bluetoothGatt.getDevice(); if (connectedDevice != null && connectedDevice.getAddress().equals(macAddress)) { - Log.d(TAG, "设备已连接,无需重复连接: " + connectedDevice.getName()); + Log.d(LogTag.PROFILOMENTER, "设备已连接,无需重复连接: " + connectedDevice.getName()); return true; } else { disconnect(); @@ -392,11 +393,11 @@ public class BleManager { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { - Log.d(TAG, "设备已连接,开始发现服务"); + Log.d(LogTag.PROFILOMENTER, "设备已连接,开始发现服务"); // 等待服务发现回调决定成功与否 gatt.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { - Log.d(TAG, "设备已断开连接"); + Log.d(LogTag.PROFILOMENTER, "设备已断开连接"); disconnect(); if (status != BluetoothGatt.GATT_SUCCESS) { Log.e(LogTag.PROFILOMENTER, "连接失败,错误码:" + status); @@ -413,7 +414,7 @@ public class BleManager { @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { - Log.d(TAG, "服务发现成功,目标服务存在"); + Log.d(LogTag.PROFILOMENTER, "服务发现成功,目标服务存在"); // 获取目标服务 BluetoothGattService service = gatt.getService(SERVICE_UUID); if (service != null) { @@ -467,6 +468,7 @@ public class BleManager { try { BluetoothDevice device = bluetoothAdapter.getRemoteDevice(macAddress); bluetoothGatt = device.connectGatt(context, USE_AUTO_CONNECT, syncGattCallback); + BleWebsocketManager.getInstance().pushBleList(); } catch (IllegalArgumentException e) { Log.e(LogTag.PROFILOMENTER, "无效的 MAC 地址: " + macAddress, e); return false; @@ -498,9 +500,6 @@ public class BleManager { SharedPreferences.Editor editor = prefs.edit(); editor.putString("mac_address", macAddress); editor.apply(); - - // 连接成功后,移除定时清理任务 - cleanupHandler.removeCallbacks(cleanupRunnable); return true; } else { return false; @@ -559,10 +558,8 @@ public class BleManager { SharedPreferences.Editor editor = prefs.edit(); editor.remove("mac_address"); editor.apply(); - - // 断开时取消定时清理任务,防止任务悬挂 - cleanupHandler.removeCallbacks(cleanupRunnable); - Log.d(TAG, "当前蓝牙设备已断开连接"); + BleWebsocketManager.getInstance().pushBleList(); + Log.d(LogTag.PROFILOMENTER, "当前蓝牙设备已断开连接"); } catch (Exception e) { e.printStackTrace(); }