【android bluetooth 协议分析 15】【SPP详解 1】【SPP 介绍】
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 的认证阶段仍然使用 listenUsingRfcommWithServiceRecord
与 createRfcommSocketToServiceRecord
进行连接,因此其流程与 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 支持良好,使用简单 |