Browse Source

feta:增加蓝牙相关接口调用限制,更改蓝牙设备列表推送方式为有变化时推送

develop
白凤吉 2 months ago
parent
commit
f2793150f3
  1. 4
      app/build.gradle
  2. 75
      app/src/main/java/com/iflytop/profilometer/api/ble/BleApi.java
  3. 82
      app/src/main/java/com/iflytop/profilometer/api/ws/BleWebsocketManager.java
  4. 39
      app/src/main/java/com/iflytop/profilometer/core/bluetooth/BleManager.java

4
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"
}

75
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("断开蓝牙设备链接失败");
}

82
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<BluetoothDevice> scannedDevices = BleManager.getInstance().getScannedDevices();
scannedDevices.sort(Comparator.comparing(BluetoothDevice::getAddress));
Map<String, Object> listMap = new HashMap<>();
listMap.put("type", "ble-list");
List<Map<String, Object>> bleList = new ArrayList<>();
BluetoothGatt gatt = BleManager.getInstance().getBluetoothGatt();
if (gatt != null) {
public void pushBleList(){
List<BluetoothDevice> scannedDevices = BleManager.getInstance().getScannedDevices();
scannedDevices.sort(Comparator.comparing(BluetoothDevice::getAddress));
Map<String, Object> listMap = new HashMap<>();
listMap.put("type", "ble-list");
List<Map<String, Object>> bleList = new ArrayList<>();
BluetoothGatt gatt = BleManager.getInstance().getBluetoothGatt();
if (gatt != null) {
Map<String, Object> 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<String, Object> 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<String, Object> 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);
// }
// }
}

39
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();
}

Loading…
Cancel
Save