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权限,否则会抛出运行时异常:
BLUETOOTHBLUETOOTH_ADMINBLUETOOTH_CONNECT(API 31+)BLUETOOTH_SCAN(API 31+)
6. 修复原有逻辑BUG
现有蓝牙开关按钮逻辑写反:
- 原
bluetoothOnOnClick方法错误调用bluetoothAdapter.disable() - 原
bluetoothOffOnClick方法错误调用bluetoothAdapter.enable()
需互换两个方法内的蓝牙开关调用,否则点击开关会出现反向效果。
兼容提示:若标准UUID连接失败,可通过反射调用设备隐藏的
createRfcommSocket接口作为 fallback 方案适配老旧设备,仅建议作为异常兜底使用。
内容的提问来源于stack exchange,提问作者Daniëlle
相关产品推荐
相关产品推荐

