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

Android Studio蓝牙开发:如何实现向已配对设备发送蓝牙消息?

核心实现逻辑

蓝牙配对仅完成设备授权,要传输数据必须建立RFCOMM套接字连接,以下是适配现有代码的完整修改方案:

1. 补充全局成员变量

在MainActivity现有成员变量区域新增以下内容:

// 已选中的待连接配对设备
private BluetoothDevice selectedDevice;
// 蓝牙传输套接字
private BluetoothSocket bluetoothSocket;
// 通用串口通信UUID,适配绝大多数蓝牙串口、安卓配对设备
private final static UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

2. 绑定已配对目标设备

2.1 修改配对完成广播分支

替换现有receiverChange中BOND_BONDED的逻辑:

if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
    // 新增:自动保存配对完成的设备
    selectedDevice = device;
    Log.d("BroadcastReceiver", "BOND_BONDED");
    Toast.makeText(MainActivity.this, "设备已就绪,可发送消息", Toast.LENGTH_SHORT).show();
}

2.2 优化设备点击逻辑

替换现有onItemClick方法,已配对设备直接选中,无需重复配对:

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    bluetoothAdapter.cancelDiscovery();
    BluetoothDevice clickedDevice = deviceListBluetooth.get(position);
    String[] device = deviceList.get(position).split("\n");
    String deviceName = device[0];

    // 新增:判断是否已配对,直接选中
    if (clickedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
        selectedDevice = clickedDevice;
        Toast.makeText(this, "已选中已配对设备", Toast.LENGTH_SHORT).show();
        return;
    }

    // 原有配对逻辑
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
        Log.d("Bluetooth Adapter", "Trying to pair with " + deviceName);
        clickedDevice.createBond();
    }
}

3. 补全sendButtonOnClick核心发送逻辑

蓝牙连接、传输为耗时操作,必须放在子线程执行,替换该方法完整逻辑:

public void sendButtonOnClick(View view) {
    // 前置合法性校验
    if (selectedDevice == null) {
        Toast.makeText(this, "请先选择已配对的设备", Toast.LENGTH_SHORT).show();
        return;
    }
    String sendContent = messageEditText.getText().toString().trim();
    if (sendContent.isEmpty()) {
        Toast.makeText(this, "请输入要发送的文本", Toast.LENGTH_SHORT).show();
        return;
    }

    new Thread(() -> {
        try {
            // 建立RFCOMM通道连接
            bluetoothSocket = selectedDevice.createRfcommSocketToServiceRecord(SERIAL_UUID);
            bluetoothSocket.connect();

            // 写入文本数据
            OutputStream outputStream = bluetoothSocket.getOutputStream();
            outputStream.write(sendContent.getBytes(StandardCharsets.UTF_8));
            outputStream.flush();

            // 切回主线程更新UI
            runOnUiThread(() -> {
                Toast.makeText(MainActivity.this, "消息发送成功", Toast.LENGTH_SHORT).show();
                messageEditText.setText("");
            });
        } catch (IOException e) {
            e.printStackTrace();
            // 连接失败时释放旧套接字资源
            try {
                if (bluetoothSocket != null) bluetoothSocket.close();
            } catch (IOException closeException) {
                closeException.printStackTrace();
            }
            runOnUiThread(() -> Toast.makeText(MainActivity.this, "发送失败,请检查设备连接", Toast.LENGTH_SHORT).show());
        }
    }).start();
}

4. 补充资源释放逻辑

修改现有onDestroy方法,避免套接字泄漏:

@Override
protected void onDestroy() {
    // 新增:关闭蓝牙套接字
    try {
        if (bluetoothSocket != null) bluetoothSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    unregisterReceiver(receiver);
    unregisterReceiver(receiverChange);
    super.onDestroy();
}

5. 权限要求

确保AndroidManifest.xml中已声明以下权限,Android 12(API 31)及以上需动态申请BLUETOOTH_CONNECT权限,否则会抛出运行时异常:

  • BLUETOOTH
  • BLUETOOTH_ADMIN
  • BLUETOOTH_CONNECT(API 31+)
  • BLUETOOTH_SCAN(API 31+)

6. 修复原有逻辑BUG

现有蓝牙开关按钮逻辑写反:

  • 原bluetoothOnOnClick方法错误调用bluetoothAdapter.disable()
  • 原bluetoothOffOnClick方法错误调用bluetoothAdapter.enable()
    需互换两个方法内的蓝牙开关调用,否则点击开关会出现反向效果。

兼容提示:若标准UUID连接失败,可通过反射调用设备隐藏的createRfcommSocket接口作为 fallback 方案适配老旧设备,仅建议作为异常兜底使用。

内容的提问来源于stack exchange,提问作者Daniëlle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 15:06:08