From cd500b67a9a38201d36445b9a8bc0a79076e4840 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Mon, 27 Jul 2026 09:45:29 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B5=8B=E8=AF=95=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yunqiinnovation/ble_service/BleService.kt | 82 ++++++++++++++++++- .../ble_service/BleServicePlugin.kt | 8 ++ .../ble_service/lib/ble_service.dart | 35 ++++++++ 3 files changed, 124 insertions(+), 1 deletion(-) diff --git a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt index 7a25dba49..dd9ceda0f 100644 --- a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt +++ b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt @@ -197,6 +197,11 @@ object BleService { private var maxMtu = 517 // 最大MTU值 (512 + 5字节头部) private var isWaitingForWriteCallback = false // 是否正在等待写入回调 + // 连接参数(由 GATT 隐藏回调 onConnectionUpdated 更新,-1 表示尚未拿到) + @Volatile private var connInterval = -1 // 单位 1.25ms + @Volatile private var connLatency = -1 // 从机延迟(可跳过的连接事件数) + @Volatile private var connTimeout = -1 // 监督超时,单位 10ms + // 通知注册串行化相关变量 private val notificationSetupQueue: ArrayDeque = ArrayDeque() private var isDescriptorWriteInProgress = false @@ -899,6 +904,28 @@ object BleService { */ private val gattCallback = object : BluetoothGattCallback() { + /** + * 连接参数更新回调,用于获取真实的连接间隔。 + * + * 注意:BluetoothGattCallback#onConnectionUpdated 在 SDK 中标记为 @hide, + * 编译期不可见,所以这里【不能加 override】;只要方法签名与父类完全一致, + * 运行时 JVM 虚方法分派仍会调用到这里(与 ota 插件 BleManager 的做法一致)。 + * + * interval 单位 1.25ms,timeout 单位 10ms,status=0 表示更新成功。 + */ + fun onConnectionUpdated(g: BluetoothGatt, interval: Int, latency: Int, timeout: Int, status: Int) { + if (status == BluetoothGatt.GATT_SUCCESS) { + connInterval = interval + connLatency = latency + connTimeout = timeout + } + Log.i( + TAG, + "连接参数更新: interval=$interval (${String.format("%.2f", interval * 1.25)}ms), " + + "latency=$latency, timeout=$timeout (${timeout * 10}ms), status=$status" + ) + } + override fun onConnectionStateChange(g: BluetoothGatt, status: Int, newState: Int) { when { status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED -> { @@ -912,6 +939,9 @@ object BleService { newState == BluetoothProfile.STATE_DISCONNECTED -> { updateConnectionState(BleConst.STATE_DISCONNECTED) Log.d(TAG, "监听到已断开连接") + connInterval = -1 + connLatency = -1 + connTimeout = -1 disconnectGatt() val pairedUuid = companionManager?.getPairedUuid() @@ -1040,7 +1070,10 @@ object BleService { } // 在服务发现完成后,请求最大MTU //requestMaxMtu(g) - + + // 服务发现完成后打印一次当前连接参数(连接间隔等) + Handler(Looper.getMainLooper()).postDelayed({ logConnectionParams() }, 1500) + } override fun onCharacteristicChanged(g: BluetoothGatt, c: BluetoothGattCharacteristic) { @@ -2073,6 +2106,53 @@ object BleService { } ?: false } + /** + * 获取当前连接参数(连接间隔/从机延迟/监督超时) + * 值来自 GATT 隐藏回调 onConnectionUpdated,未拿到时各项为 -1。 + */ + fun getConnectionParams(): Map { + return mapOf( + "interval" to connInterval, // 原始值,单位 1.25ms + "intervalMs" to if (connInterval < 0) -1.0 else connInterval * 1.25, + "latency" to connLatency, + "timeout" to connTimeout, // 原始值,单位 10ms + "timeoutMs" to if (connTimeout < 0) -1 else connTimeout * 10, + "connected" to isConnected() + ) + } + + /** + * 打印当前连接参数到日志 + */ + fun logConnectionParams() { + if (connInterval < 0) { + Log.i(TAG, "连接参数: 尚未收到 onConnectionUpdated 回调(未连接,或系统未上报连接参数更新)") + } else { + Log.i( + TAG, + "当前连接参数: interval=$connInterval (${String.format("%.2f", connInterval * 1.25)}ms), " + + "latency=$connLatency, timeout=$connTimeout (${connTimeout * 10}ms)" + ) + } + } + + /** + * 主动请求连接优先级,会触发一次连接参数协商,随后由 onConnectionUpdated 打印新的连接间隔。 + * @param priority BluetoothGatt.CONNECTION_PRIORITY_HIGH(1) / BALANCED(0) / LOW_POWER(2) + */ + fun requestConnectionPriority(priority: Int): Boolean { + return bluetoothGatt?.let { gatt -> + try { + val result = gatt.requestConnectionPriority(priority) + Log.i(TAG, "请求连接优先级 priority=$priority: $result") + result + } catch (e: Exception) { + Log.e(TAG, "请求连接优先级异常: ${e.message}", e) + false + } + } ?: false + } + fun startWakeupVoiceUpgrade(bytes: ByteArray): Boolean { return wakeupVoicesUpgradeSender.startWakeupVoiceUpgrade(bytes) } diff --git a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleServicePlugin.kt b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleServicePlugin.kt index 40bd526a3..6e88739a7 100644 --- a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleServicePlugin.kt +++ b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleServicePlugin.kt @@ -206,6 +206,14 @@ class BleServicePlugin : FlutterPlugin, MethodCallHandler, ActivityAware, val success = BleService.setVoiceWakeupStatus(enabled) result.success(success) } + "getConnectionParams" -> { + BleService.logConnectionParams() + result.success(BleService.getConnectionParams()) + } + "requestConnectionPriority" -> { + val priority = call.argument("priority") ?: 0 + result.success(BleService.requestConnectionPriority(priority)) + } "openEncoder" -> { val success = BleService.openEncoder() result.success(success) diff --git a/local_plugins/ble_service/lib/ble_service.dart b/local_plugins/ble_service/lib/ble_service.dart index f869dda0f..3c29f3be7 100644 --- a/local_plugins/ble_service/lib/ble_service.dart +++ b/local_plugins/ble_service/lib/ble_service.dart @@ -218,6 +218,41 @@ class BleService { } } + /// 获取当前 BLE 连接参数(连接间隔等),并在 native 侧打印一次 + /// 返回 {'interval'(1.25ms单位), 'intervalMs', 'latency', 'timeout'(10ms单位), 'timeoutMs', 'connected'} + /// 尚未拿到连接参数时各项为 -1。仅 Android 支持,iOS 系统不暴露连接间隔,返回空 Map。 + Future> getConnectionParams() async { + try { + final result = + await _methodChannel.invokeMethod('getConnectionParams'); + if (result == null) return {}; + return { + 'interval': (result['interval'] as num?)?.toInt() ?? -1, + 'intervalMs': (result['intervalMs'] as num?)?.toDouble() ?? -1.0, + 'latency': (result['latency'] as num?)?.toInt() ?? -1, + 'timeout': (result['timeout'] as num?)?.toInt() ?? -1, + 'timeoutMs': (result['timeoutMs'] as num?)?.toInt() ?? -1, + 'connected': result['connected'] == true, + }; + } catch (e) { + print('获取连接参数失败: $e'); + return {}; + } + } + + /// 主动请求连接优先级,触发一次连接参数协商 + /// [priority] 0=BALANCED, 1=HIGH(最小连接间隔), 2=LOW_POWER。仅 Android 有效。 + Future requestConnectionPriority(int priority) async { + try { + final result = await _methodChannel + .invokeMethod('requestConnectionPriority', {'priority': priority}); + return result ?? false; + } catch (e) { + print('请求连接优先级失败: $e'); + return false; + } + } + /// 启动BLE后台服务 Future startBleService(Map config) async {