【android bluetooth 协议分析 15】【SPP详解 1】【SPP 介绍】

发布于:2025-06-08 ⋅ 阅读:(25) ⋅ 点赞:(0)

1. 什么是 SPP(Serial Port Profile)

SPP 是一种经典蓝牙协议(基于 RFCOMM),用于模拟串口通信。

  • 应用场景:设备间简单的数据传输,如串口打印机、蓝牙 OBD 车载诊断仪、蓝牙扫描枪、蓝牙调试工具、车载系统认证通信等。

  • 特点:基于 RFCOMM 传输,应用层可读写类似串口的数据。


2. SPP 通信整体流程

阶段 Client 端 Server 端
1. UUID 协议识别 使用固定的 SPP UUID(00001101-0000-1000-8000-00805F9B34FB)或自定义 UUID 注册并广播 UUID 到 SDP(服务发现协议)中
2. Socket 创建 使用 createRfcommSocketToServiceRecord(UUID) 创建 RFCOMM socket 使用 listenUsingRfcommWithServiceRecord(name, UUID) 创建监听 socket
3. 连接建立 调用 connect() 主动连接 调用 accept() 等待连接
4. 数据传输 使用 InputStream / OutputStream 收发数据 同样使用流进行读写
5. 关闭连接 调用 close() 关闭连接 同上

3. Server 与 Client 示例代码

1. Server 端代码

public class BluetoothSppServer extends Thread {
    private final BluetoothServerSocket serverSocket;
    private static final UUID SPP_UUID =
        UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    public BluetoothSppServer(BluetoothAdapter adapter) throws IOException {
        serverSocket = adapter.listenUsingRfcommWithServiceRecord("SPP_SERVER", SPP_UUID);
    }

    public void run() {
        BluetoothSocket socket;
        while (true) {
            try {
                socket = serverSocket.accept();  // 阻塞等待连接
            } catch (IOException e) {
                break;
            }

            if (socket != null) {
                new SppConnectionHandler(socket).start();  // 启动数据处理线程
            }
        }
    }

    public void cancel() throws IOException {
        serverSocket.close();
    }
}

2. Client 端代码

public class BluetoothSppClient extends Thread {
    private final BluetoothSocket socket;
    private static final UUID SPP_UUID =
        UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    public BluetoothSppClient(BluetoothDevice device) throws IOException {
        socket = device.createRfcommSocketToServiceRecord(SPP_UUID);
    }

    public void run() {
        try {
            socket.connect();  // 主动连接
            OutputStream out = socket.getOutputStream();
            InputStream in = socket.getInputStream();

            out.write("Hello Server!".getBytes());
            byte[] buffer = new byte[1024];
            int bytes = in.read(buffer);
            String response = new String(buffer, 0, bytes);
            Log.d("SPPClient", "Received: " + response);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void cancel() throws IOException {
        socket.close();
    }
}


4. SPP 在车机中的应用场景

应用场景 是否使用 SPP 说明
车载蓝牙调试端口 开发人员通过串口协议调试 ECU 等设备
蓝牙 OBD 读码器 车机与 OBD 通信获取车辆状态信息
CarPlay 蓝牙认证 ✅(使用相同 API) 虽不使用标准 SPP 协议,但使用 RFCOMM 套接字建立 iAP2 通道
蓝牙打印机 一些车载小票打印应用
远程诊断工具(带蓝牙) 蓝牙串口传输指令和日志数据

5. CarPlay 与 SPP 的联系和区别

虽然 CarPlay 并不严格遵循 Bluetooth SIG 定义的 SPP profile,但其 iAP2 over Bluetooth 的认证阶段仍然使用 listenUsingRfcommWithServiceRecordcreateRfcommSocketToServiceRecord 进行连接,因此其流程与 SPP 本质上相同,只是:

项目 SPP CarPlay
使用 UUID 标准 UUID (00001101...) Apple 自定义 iAP2 UUID
协议内容 串口透明数据 Apple 私有 iAP2 协议帧
应用层数据 任意串口数据 MFi 授权认证帧等
是否公开 ❌ 私有

因此我们可以说:

CarPlay 使用的是“SPP 风格”的 Bluetooth RFCOMM 通道,但走的是 Apple 私有协议(iAP2)


6. 总结

项目 内容
listenUsingRfcommWithServiceRecord Server 端使用,注册服务并等待连接(通过 SDP 广播 UUID)
createRfcommSocketToServiceRecord Client 端使用,连接指定 UUID 的服务
SPP 场景 串口调试、OBD 读码器、蓝牙打印、CarPlay 认证等
CarPlay 与 SPP 区别 协议不同,机制类似,使用相同的 Android API
是否可以使用 SPP 做调试通道? ✅ 非常适合,Android 支持良好,使用简单

网站公告

今日签到

点亮在社区的每一天
去签到