上一篇
安卓开发两个蓝牙传输数据包
- 行业动态
- 2025-04-23
- 2668
安卓蓝牙传输需先配对设备,创建BluetoothSocket连接,通过输入输出流收发数据
蓝牙通信基础准备
权限配置
在 AndroidManifest.xml
中添加必要权限:
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
蓝牙适配器初始化
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { // 设备不支持蓝牙 return; } if (!bluetoothAdapter.isEnabled()) { // 请求用户开启蓝牙 Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }
设备配对与连接
获取已配对设备
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
创建蓝牙连接
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(targetAddress); BluetoothSocket socket = device.createRfcommSocketToServiceRecord(MY_UUID); socket.connect(); // 需在子线程执行
数据包传输实现
定义数据包协议
字段名 | 类型 | 说明 |
---|---|---|
Message Type | 1 byte | 标识数据类型(如0x01) |
Length | 2 bytes | 数据体长度 |
Data | N bytes | 实际数据内容 |
Checksum | 1 byte | 校验和(可选) |
发送数据包
private void sendPacket(BluetoothSocket socket, byte[] data) { byte[] packet = new byte[4 + data.length]; packet[0] = 0x01; // 消息类型 System.arraycopy(intToBytes(data.length), 0, packet, 1, 2); // 长度字段 System.arraycopy(data, 0, packet, 3, data.length); // 数据体 packet[3 + data.length] = calculateChecksum(packet); // 校验和 OutputStream outStream = socket.getOutputStream(); outStream.write(packet); }
接收数据包
private void receivePacket(BluetoothSocket socket) { InputStream inStream = socket.getInputStream(); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inStream.read(buffer)) != -1) { // 处理粘包问题 int offset = 0; while (offset + 4 <= bytesRead) { int length = bytesToInt(buffer, offset + 1); if (offset + 4 + length <= bytesRead) { byte[] data = Arrays.copyOfRange(buffer, offset + 4, offset + 4 + length); // 校验数据完整性 if (validateChecksum(buffer, offset, length + 4)) { handleData(data); // 业务处理 } offset += 4 + length; } else { break; // 等待更多数据 } } } }
关键问题处理
问题类型 | 解决方案 |
---|---|
线程阻塞 | 使用 Thread 或 AsyncTask 处理蓝牙连接和数据传输 |
数据粘包 | 通过长度字段识别完整数据包,不足时缓存等待 |
连接不稳定 | 增加重连机制,设置读取超时时间 |
权限拒绝 | Android 6.0+ 动态申请定位权限(BLUETOOTH_CONNECT 需要定位权限) |
代码示例
// 工具方法:整数转字节数组(大端) private byte[] intToBytes(int value) { return new byte[] { (byte)(value >> 8 & 0xFF), (byte)(value & 0xFF) }; } // 工具方法:字节数组转整数(大端) private int bytesToInt(byte[] bytes) { return (bytes[0] << 8) + (bytes[1] & 0xFF); }
问题与解答
Q1:如何优化蓝牙数据传输效率?
A1:
- 启用蓝牙缓存:调用
socket.setSendBufferSize()
增大发送缓冲区 - 批量发送:合并多个小数据包为一个大数据包
- 压缩数据:对文本类数据启用Zlib压缩
- 减少校验频率:仅对关键数据包启用校验和
Q2:如何处理大数据量传输(如文件)?
A2:
- 分片传输:将文件分割为固定大小数据块(如4KB)
- 进度反馈:每个数据包添加序号和总包数
- 断点续传:记录已传输的文件偏移量
- 示例协议扩展:
| 新增字段 | 类型 | 说明 |
|————-|———|————————–|
| File ID | 4 bytes | 文件唯一标识 |
| Block Index | 2 bytes | 当前分块序号 |
| Total Blocks| 2 bytes | 总分块数 |