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

如何检测安卓设备蓝牙即将关闭状态,实现断连前发送消息?

看来你找错了监听的广播类型啦!ACTION_BOND_STATE_CHANGED确实只关注配对设备的绑定状态变化,根本不会管本机蓝牙的开关状态。要监听本机蓝牙即将关闭的通知,你得用**BluetoothAdapter.ACTION_STATE_CHANGED**这个广播才行——它专门负责通知本机蓝牙适配器的状态变化,包括开启、正在开启、关闭、正在关闭这几个关键状态。

核心思路

你需要重点关注BluetoothAdapter.STATE_TURNING_OFF这个状态,这就是本机蓝牙即将关闭的信号,此时蓝牙还没完全断开连接,正是给已连接设备发送最后一条消息的黄金时机。而STATE_OFF是蓝牙已经完全关闭的状态,这时候再操作就来不及了。

修改后的代码实现

下面是调整后的完整代码,我保留了你原来的设备发现、配对状态监听逻辑,同时新增了本机蓝牙状态的处理:

class YourBluetoothManager(
    private val application: Application,
    private val deviceListener: ((List<BluetoothDevice>) -> Unit)?
) {
    // 已连接设备的Socket管理(需要你自己维护,用于发送最后消息)
    private val connectedDeviceSockets = mutableMapOf<BluetoothDevice, BluetoothSocket>()

    private val mBTReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            when (intent.action) {
                // 处理本机蓝牙状态变化(核心逻辑)
                BluetoothAdapter.ACTION_STATE_CHANGED -> {
                    val currentState = intent.getIntExtra(
                        BluetoothAdapter.EXTRA_STATE,
                        BluetoothAdapter.ERROR
                    )
                    when (currentState) {
                        BluetoothAdapter.STATE_TURNING_OFF -> {
                            Log.d("MESSAGE", "本机蓝牙即将关闭,准备发送最后消息")
                            // 执行给已连接设备发送最后消息的逻辑
                            sendFinalMessageToConnectedDevices()
                        }
                        BluetoothAdapter.STATE_OFF -> {
                            Log.d("MESSAGE", "本机蓝牙已完全关闭")
                            // 清空已连接设备的Socket缓存
                            connectedDeviceSockets.clear()
                        }
                        BluetoothAdapter.STATE_ON -> {
                            Log.d("MESSAGE", "本机蓝牙已开启")
                            fetchDevices()
                            deviceListener?.invoke(devices)
                        }
                    }
                }
                // 处理设备发现(保留你原有的逻辑)
                BluetoothDevice.ACTION_FOUND -> {
                    val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
                    if (device != null) {
                        fetchDevices()
                        deviceListener?.invoke(devices)
                    }
                }
                // 处理配对状态变化(保留你原有的逻辑)
                BluetoothDevice.ACTION_BOND_STATE_CHANGED -> {
                    val previousState = intent.getIntExtra(
                        BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE,
                        BluetoothAdapter.ERROR
                    )
                    val currentBondState = intent.getIntExtra(
                        BluetoothDevice.EXTRA_BOND_STATE,
                        BluetoothAdapter.ERROR
                    )
                    // 可根据需要处理配对成功/失败等逻辑
                }
                // 处理设备断开连接(可选,用于补充监听)
                BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
                    val disconnectedDevice = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
                    Log.d("MESSAGE", "设备 ${disconnectedDevice?.name} 已断开连接")
                    connectedDeviceSockets.remove(disconnectedDevice)
                }
            }
        }
    }

    init {
        fetchDevices()
        // 注册广播,添加所有需要监听的Action
        val intentFilter = IntentFilter().apply {
            addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
            addAction(BluetoothDevice.ACTION_FOUND)
            addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
            addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)
        }
        application.registerReceiver(mBTReceiver, intentFilter)
    }

    // 务必在组件销毁时注销广播,避免内存泄漏
    fun destroy() {
        application.unregisterReceiver(mBTReceiver)
    }

    private fun fetchDevices() {
        // 你的设备获取逻辑(比如获取已配对设备)
    }

    private fun sendFinalMessageToConnectedDevices() {
        // 遍历所有已连接的设备Socket,发送最后消息
        connectedDeviceSockets.forEach { (device, socket) ->
            try {
                val outputStream = socket.outputStream
                val finalMessage = "Goodbye!".toByteArray()
                outputStream.write(finalMessage)
                outputStream.flush()
                Log.d("MESSAGE", "已给设备 ${device.name} 发送最后消息")
            } catch (e: IOException) {
                Log.e("MESSAGE", "发送最后消息失败: ${e.message}")
            }
        }
    }

    // 假设你有一个方法用于记录已连接设备的Socket
    fun addConnectedDeviceSocket(device: BluetoothDevice, socket: BluetoothSocket) {
        connectedDeviceSockets[device] = socket
    }
}

关键注意事项

  1. 权限申请:Android 12及以上需要申请BLUETOOTH_CONNECT权限,Android 11及以下需要BLUETOOTH权限,记得在Manifest中声明并动态申请。
  2. 广播注销:动态注册的广播一定要在不需要的时候(比如Activity的onDestroy或Service的onDestroy)注销,否则会引发内存泄漏。
  3. 已连接设备管理:你需要自己维护已连接设备的BluetoothSocket实例,这样才能在STATE_TURNING_OFF状态下快速找到目标设备并发送消息。
  4. 消息发送时机:STATE_TURNING_OFF是唯一能确保蓝牙还未完全断开的状态,一旦进入STATE_OFF或触发ACTION_ACL_DISCONNECTED,连接已经中断,无法再发送数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:26:40