第二章 经典蓝牙与BLE蓝牙选型:协议栈对比、功耗场景、Android版本兼容性、API差异
在Android蓝牙开发中,首先需要明确选型:使用经典蓝牙(Classic Bluetooth / BR/EDR)还是低功耗蓝牙(BLE / Bluetooth Low Energy)。两者虽共享“蓝牙”名称,但其协议栈、功耗特征、适用场景及Android API均存在根本差异。本章将从协议栈分层出发,对比功耗特性,梳理Android版本兼容性,并给出API差异与选型建议。
2.1 协议栈分层对比
经典蓝牙遵循BR/EDR规范,BLE遵循LE规范。两者在L2CAP层开始分化,上层协议完全不同。
| 协议层 | 经典蓝牙(BR/EDR) | BLE |
|---|---|---|
| 射频 | 79个1MHz信道,跳频79个 | 40个2MHz信道,跳频37个+3个广播信道 |
| 链路层 | Baseband + LMP | Link Layer(状态机:待机、广播、扫描、发起、连接) |
| HCI | HCI(Host Controller Interface) | HCI(相同标准,但命令集不同) |
| L2CAP | L2CAP(面向连接,支持重传) | L2CAP(基于BLE固定信道,无重传) |
| 核心上层协议 | SDP + RFCOMM(串口仿真)+ GAP | ATT + GATT + GAP + L2CAP(面向属性) |
| Profile | SPP、HSP、A2DP、AVRCP等 | HID-over-GATT、Blood Pressure、Heart Rate等 |
关键差异:经典蓝牙使用RFCOMM提供虚拟串口通道,适用于双向流式数据传输;BLE基于属性协议(ATT),采用客户端-服务器模型,数据以“服务+特征值”结构化,适合周期性小数据交换。
2.2 功耗场景与选型建议
功耗是选型的首要考虑因素。经典蓝牙设计用于持续稳定连接,例如音频流(A2DP)或文件传输(OPP),典型工作电流为数十mA。BLE则针对低占空比、低功耗设计,一次连接传输几个字节后即可断开,待机电流可低至μA级。
| 应用场景 | 推荐方案 | 典型电流 | 数据量特点 |
|---|---|---|---|
| 无线耳机、音箱(实时音频) | 经典蓝牙(A2DP) | 20~50 mA | 持续流式数据 |
| 心率带、温度计(传感器) | BLE | 1~15 mA(广播/连接) | 小数据包,低频次 |
| 文件传输(Android快传) | 经典蓝牙(OPP) | 20~40 mA | 大文件,传输时持续 |
| 室内定位信标(Beacon) | BLE广播 | 0.1~0.5 mA(广播) | 仅发送ID,不连接 |
| 蓝牙键盘/鼠标(HID) | BLE(HID-over-GATT) | 1~5 mA | 交互式小数据 |
选型口诀:需要持续数据流 → 经典蓝牙;需低功耗、小数据、周期性 → BLE;低延迟、指令型 → BLE(GATT Write)。
2.3 Android版本兼容性
BLE从Android 4.3(API 18)开始提供官方支持;经典蓝牙自Android 1.0起就存在。但随着系统升级,权限与扫描方式变化较大,需特别注意。
| Android版本 | API Level | BLE支持 | 经典蓝牙变化 |
|---|---|---|---|
| 4.3 (Jelly Bean) | 18 | 引入BluetoothGatt、BluetoothLeScanner | 无重大变化 |
| 6.0 (Marshmallow) | 23 | 扫描需要ACCESS_FINE_LOCATION | 同上 |
| 10 (Q) | 29 | 扫描需ACCESS_FINE_LOCATION + 动态权限 | 新增广播接收器限制 |
| 12 (Snow Cone) | 31 | 新增BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限(无需定位) | 需SCAN/CONNECT权限 |
| 13+ | 33+ | 细化运行时权限,兼容NEARBY_DEVICES | 与BLE权限统一 |
注意:Android 10及以上,经典蓝牙扫描(startDiscovery)同样需要ACCESS_FINE_LOCATION。Android 12后,使用BLE扫描可以单独请求BLUETOOTH_SCAN,不再强制定位权限,但经典蓝牙发现仍可能需要定位权限(因Wi-Fi/蓝牙联合扫描)。
2.4 API差异速查
经典蓝牙与BLE在核心API上差异显著,开发时必须区分使用。
| 操作 | 经典蓝牙(BR/EDR) | BLE |
|---|---|---|
| 获取适配器 | BluetoothAdapter.getDefaultAdapter() | 相同 |
| 扫描设备 | startDiscovery()/cancelDiscovery() | BluetoothLeScanner.startScan() |
| 发现结果回调 | BroadcastReceiver 监听 ACTION_FOUND | ScanCallback 接口 |
| 发起连接 | BluetoothDevice.createRfcommSocketToServiceRecord() | device.connectGatt() |
| 数据收发 | InputStream/OutputStream (基于RFCOMM) | BluetoothGatt.read/writeCharacteristic() + 回调 |
| 服务发现 | BluetoothDevice.fetchUuidsWithSdp() 或手动SDP查询 | BluetoothGatt.discoverServices() |
| 广播(Beacon) | 不支持主动广播 | BluetoothLeAdvertiser.startAdvertising() (Android 5.0+) |
// 经典蓝牙 —— 通过RFCOMM收发数据
BluetoothDevice device = adapter.getRemoteDevice(address);
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(MY_UUID);
socket.connect();
OutputStream os = socket.getOutputStream();
os.write(data);
InputStream is = socket.getInputStream();
int bytes = is.read(buffer);
// BLE —— 通过GATT读写特征值
BluetoothGatt gatt = device.connectGatt(context, false, gattCallback);
gatt.discoverServices();
// 在onServicesDiscovered回调中操作
BluetoothGattService service = gatt.getService(SERVICE_UUID);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(CHAR_UUID);
gatt.readCharacteristic(characteristic);
// 或 gatt.writeCharacteristic(characteristic);
2.5 常见错误与调试建议
- 经典蓝牙连接超时:确保配对已完成,UUID匹配,且在异步线程中调用connect()。
- BLE扫描不到设备:检查权限(Android 12+需BLUETOOTH_SCAN),确认设备在广播;部分设备需要先启动扫描过滤。
- GATT错误133:通常为连接参数协商失败,尝试设置连接间隔为30ms~50ms(Peripheral端需支持)。
- 经典蓝牙与BLE干扰:两者共用同一射频,同时启用可能降低性能;建议场景分离。
调试技巧:使用Android Studio的“Bluetooth HCI snoop log”工具(开发者选项 → 启用蓝牙HCI信息收集日志),抓取hci_log,配合Wireshark分析协议层问题。
2.6 协议栈选型结构图
下图展示经典蓝牙(左侧)与BLE(右侧)的协议栈层次对比,并标注关键分界点。
2.7 性能与稳定性优化要点
- 经典蓝牙:避免在主线程进行RFCOMM连接,使用AsyncTask或线程池;合理设置SO_TIMEOUT防止死等。
- BLE:控制连接间隔(Connection Interval)在30~50ms以平衡功耗与响应;批量读写时使用Reliable Write或Queued Write。
- 共存场景:避免同时大量经典蓝牙和BLE扫描,可先暂停经典发现再启动BLE扫描。
- 内存管理:及时释放BluetoothSocket和BluetoothGatt对象,防止泄漏。
总结:经典蓝牙与BLE并非替代关系,而是互补。优先根据通信场景选型:
• 音频、文件传输 → 经典蓝牙
• 传感器、信标、遥控 → BLE
• 若需要两者共存(如同时接听蓝牙耳机和接收心率数据),则需分开管理连接与扫描周期,避免射频冲突。
• 音频、文件传输 → 经典蓝牙
• 传感器、信标、遥控 → BLE
• 若需要两者共存(如同时接听蓝牙耳机和接收心率数据),则需分开管理连接与扫描周期,避免射频冲突。