1. 蓝牙核心API演进史
Android 蓝牙 API 自 2009 年 Android 2.0(API 5)首次引入以来,经历了多次重大重构与废弃。理解各版本的关键变更节点与弃用标志,是实现向后兼容的根基。本章将从版本断代、关键 API 变更、以及官方标记体系三个维度,系统梳理演进脉络。
学习目标:掌握每个 Android 大版本中蓝牙 API 的增删改,能快速识别
@Deprecated、REMOVED等标记,并建立“最低兼容版本 + 运行时检测”的思维模型。
1.1 Android 版本断代与 API 级别对应
下表列出所有引入蓝牙 API 重大变更的 Android 版本,以及对应的 API Level 和版本代号。后文所有讨论均以 API Level 为准。
| Android 版本 | API Level | 代号 | 核心蓝牙变更 |
|---|---|---|---|
| 2.0 | 5 | Eclair | 首次引入 BluetoothAdapter、BluetoothDevice、BluetoothSocket |
| 4.0 | 14 | Ice Cream Sandwich | 增加 BluetoothHeadset 服务代理 |
| 4.2 | 17 | Jelly Bean MR1 | 新增 BluetoothHealth 和 BluetoothGatt(BLE 预览) |
| 5.0 | 21 | Lollipop | 正式发布 BluetoothLeScanner、ScanFilter,废弃 startLeScan() |
| 6.0 | 23 | Marshmallow | 运行时权限 ACCESS_FINE_LOCATION 强制用于 BLE 扫描 |
| 10 | 29 | Q | 新增 BluetoothLeAudio(LE Audio 基础),废弃 fetchUuidsWithSdp() |
| 12 | 31 | S | 新增 BluetoothLeScanner 的 startScan(ScanCallback) 强制需要 BLUETOOTH_SCAN 权限 |
| 14 | 34 | UpsideDownCake | 废弃 BluetoothAdapter.getDefaultAdapter(),推荐 BluetoothManager.getAdapter() |
1.2 关键 API 变更节点
以下按时间线列举对向后兼容影响最大的几个变更点。开发者必须为每个节点编写版本守卫代码。
- API 5 → API 17:仅经典蓝牙,无 BLE 支持。使用
BluetoothDevice.ACTION_FOUND进行设备发现。 - API 17 → API 21:BLE 扫描使用
BluetoothAdapter.startLeScan(),该 API 在 API 21 被标记为@Deprecated。 - API 21 → API 23:BLE 扫描迁移至
BluetoothLeScanner,但 API 23 起扫描需要位置权限。 - API 29 → API 31:新增
BLUETOOTH_SCAN、BLUETOOTH_CONNECT运行时权限,旧权限BLUETOOTH、BLUETOOTH_ADMIN被逐步废弃。 - API 34:
BluetoothAdapter.getDefaultAdapter()被标记为@Deprecated,需通过BluetoothManager获取。
常见错误:直接调用
startLeScan() 而不检查 API Level,会导致在 API 21+ 设备上编译通过但运行时触发废弃警告,并可能在未来的 Android 版本中被移除。同样,getDefaultAdapter() 在 API 34+ 设备上仍可工作,但后续版本可能返回 null 或抛出异常。
1.3 弃用与替代标记体系
Android 框架使用三种官方标记来标注 API 状态,理解其语义是兼容性编码的基础。
| 标记 | 含义 | 向后兼容处理 |
|---|---|---|
@Deprecated | 不推荐使用,未来可能移除 | 运行时通过 Build.VERSION.SDK_INT 判断版本,分别调用新旧 API |
@Removed(API 文档) | 在指定 API Level 后彻底移除 | 必须在最低支持版本中删除引用,使用替代 API |
@RequiresApi | 标注 API 最低需要的版本 | 调用处需用 if (Build.VERSION.SDK_INT >= ...) 保护,或类/方法添加 @RequiresApi |
// 示例:安全调用 BluetoothLeScanner(API 21+)同时兼容旧版 BLE 扫描
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
scanner.startScan(filters, scanSettings, scanCallback);
} else {
// 旧版 API 17-20
bluetoothAdapter.startLeScan(leScanCallback);
}
实践要点:推荐所有涉及蓝牙的代码均使用
@TargetApi 标注当前方法所需的最低版本,并用 Build.VERSION.SDK_INT 运行时判断。不要在方法签名上统一使用 @RequiresApi 而忽略运行时保护,否则会引发 NoSuchMethodError。
1.4 API 演进时间线(SVG)
下图中展示了从 Android 2.0 到 Android 14 的关键 API 引入与废弃节点,深色节点表示重大引入,红色节点表示废弃或移除,连接线体现版本间的继承与覆盖关系。
1.5 向后兼容核心策略
基于上述演进史,向后兼容实践应遵循以下标准流程:
- 确定最低支持版本(通常为 API 17 或 API 21)。
- 在代码中针对每个关键节点使用
Build.VERSION.SDK_INT进行分支。 - 为每个废弃 API 准备对应版本的替代实现,并添加单元测试。
- 使用
@TargetApi注解标记方法所依赖的最高版本,以避免 Lint 警告。 - 定期用
lint --check Deprecation检查项目中已废弃的 API 调用。