当前位置:首页 > 行业动态 > 正文

安卓开发两个蓝牙传输数据包

安卓蓝牙传输需先配对设备,创建BluetoothSocket连接,通过输入输出流收发数据

蓝牙通信基础准备

权限配置

AndroidManifest.xml 中添加必要权限:

安卓开发两个蓝牙传输数据包  第1张

<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; // 等待更多数据
            }
        }
    }
}

关键问题处理

问题类型 解决方案
线程阻塞 使用 ThreadAsyncTask 处理蓝牙连接和数据传输
数据粘包 通过长度字段识别完整数据包,不足时缓存等待
连接不稳定 增加重连机制,设置读取超时时间
权限拒绝 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

  1. 启用蓝牙缓存:调用 socket.setSendBufferSize() 增大发送缓冲区
  2. 批量发送:合并多个小数据包为一个大数据包
  3. 压缩数据:对文本类数据启用Zlib压缩
  4. 减少校验频率:仅对关键数据包启用校验和

Q2:如何处理大数据量传输(如文件)?

A2

  1. 分片传输:将文件分割为固定大小数据块(如4KB)
  2. 进度反馈:每个数据包添加序号和总包数
  3. 断点续传:记录已传输的文件偏移量
  4. 示例协议扩展:
    | 新增字段 | 类型 | 说明 |
    |————-|———|————————–|
    | File ID | 4 bytes | 文件唯一标识 |
    | Block Index | 2 bytes | 当前分块序号 |
    | Total Blocks| 2 bytes | 总分块数 |
0