You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GATT服务器关闭时通知客户端并更新其状态栏?

解决GATT服务器关闭时客户端状态不更新的问题

问题根源

直接调用mGattServer.close()会让服务器立即终止所有连接,但不会主动向客户端发送断开通知,导致客户端的BluetoothGattCallback无法触发onConnectionStateChange回调,状态栏也就无法更新。另外你之前的disconnectFromGattServer函数没有等待异步断开操作完成就直接关闭服务器,所以没起到作用。

解决方案

1. 完善服务器端断开逻辑,等待所有客户端断开后再关闭服务器

修改stopServer和断开连接的逻辑,通过GattServerCallback跟踪连接状态,确保所有客户端断开后再关闭服务器:

// 新增变量跟踪当前连接的客户端数量
private var connectedClientCount = 0

// 在GattServerCallback中更新连接计数
private val gattServerCallback = object : GattServerCallback() {
    override fun onConnectionStateChange(device: BluetoothDevice, status: Int, newState: Int) {
        super.onConnectionStateChange(device, status, newState)
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            connectedClientCount++
            devicesArrayList.add(device)
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            connectedClientCount--
            devicesArrayList.remove(device)
            // 当最后一个客户端断开时,关闭服务器
            if (connectedClientCount == 0) {
                mGattServer?.close()
                mGattServer = null
            }
        }
    }
}

// 修改disconnectFromGattServer函数,遍历副本避免并发修改问题
fun disconnectFromGattServer() {
    val devicesCopy = ArrayList(devicesArrayList)
    devicesCopy.forEach { device ->
        mGattServer?.cancelConnection(device)
    }
}

// 修改stopServer函数,先触发断开所有连接,等待回调中完成服务器关闭
fun stopServer() {
    mGattServer?.let {
        disconnectFromGattServer()
    }
}

2. 客户端侧增加容错检测

即使服务器端处理完善,也可能存在网络异常导致客户端收不到断开通知的情况,客户端可以定期检测连接状态:

// 客户端的BluetoothGattCallback中增加连接状态跟踪
private var isConnected = false

private val gattCallback = object : BluetoothGattCallback() {
    override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
        super.onConnectionStateChange(gatt, status, newState)
        isConnected = newState == BluetoothProfile.STATE_CONNECTED
        // 更新状态栏
        updateStatusBar(isConnected)
    }

    override fun onCharacteristicRead(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
        super.onCharacteristicRead(gatt, characteristic, status)
        if (status != BluetoothGatt.GATT_SUCCESS && isConnected) {
            // 读取失败,判定连接已断开
            isConnected = false
            updateStatusBar(false)
        }
    }
}

// 定期检测连接状态,每隔5秒尝试读取特征值验证连接
private val connectionCheckTimer = Timer().scheduleAtFixedRate(object : TimerTask() {
    override fun run() {
        runOnUiThread {
            if (isConnected && gatt != null) {
                gatt.readCharacteristic(yourTargetCharacteristic)
            }
        }
    }
}, 0, 5000)

3. 优化Activity的onDestroy逻辑

确保在销毁时正确触发断开流程,避免直接强制关闭:

override fun onDestroy() {
    super.onDestroy()
    if (preference_BluetoothMode == "Server") {
        bluetoothService?.stopServer()
    } else {
        bluetoothService?.disconnect()
        // 客户端记得关闭Gatt资源
        bluetoothService?.closeGatt()
    }
}

关键注意点

  • cancelConnection是异步操作,必须等待所有客户端的onConnectionStateChange回调触发后再关闭服务器。
  • 遍历连接设备时要使用副本,避免并发修改devicesArrayList导致异常。
  • 客户端侧增加主动检测,弥补被动回调的不足,提升状态更新的可靠性。

内容的提问来源于stack exchange,提问作者Renzo Sampietro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 05:08:27