第4章:BLUETOOTH_CONNECT 与 BLUETOOTH_ADVERTISE 权限——用途区别、典型场景、声明要求

Android 12 将旧版 BLUETOOTH 权限拆分为三个细粒度权限:BLUETOOTH_SCAN、BLUETOOTH_CONNECT 和 BLUETOOTH_ADVERTISE。本章聚焦后两个权限:BLUETOOTH_CONNECT 管理蓝牙连接的建立与数据交互,BLUETOOTH_ADVERTISE 管理设备以广播形式向周围宣告自身存在(即周边模式/外围模式)。

拆分的核心目的:让用户能够按“扫描→连接→广播”三个独立阶段分别授权,从而在隐私和功能颗粒度上远超旧版单一大权限。

4.1 概念对比:CONNECT vs ADVERTISE

维度BLUETOOTH_CONNECTBLUETOOTH_ADVERTISE
核心能力建立 ACL 连接、读写 GATT 属性、发起服务发现、绑定配对、连接参数更新等双向通信操作以 BLE 广播包向周围广播设备信息(包括厂商自定义数据、扫描响应数据)、启动外围模式(Peripheral Mode)
典型角色中央设备(Central / GATT Client)外围设备(Peripheral / GATT Server)
是否需要位置权限Android 12+ 不再强制位置权限(连接阶段已不需要 Wi-Fi/蓝牙扫描结果)仅广播不需要位置;但若广播后期望其他设备发现并连接,通常仍需配合 BLUETOOTH_CONNECT
运行时请求时机在尝试连接或绑定之前请求在开始广播之前请求
API 示例BluetoothDevice.createBond()、BluetoothGatt.connect()BluetoothLeAdvertiser.startAdvertising()
BLUETOOTH_CONNECT 与 BLUETOOTH_ADVERTISE 权限作用域示意图 CONNECT 与 ADVERTISE 权限在蓝牙栈中的位置 Android 应用层 Android App BLUETOOTH_CONNECT BLUETOOTH_ADVERTISE Android Bluetooth 框架层 GATT / RFCOMM 连接 BLE 广播 / 外围模式 蓝牙硬件层 蓝牙芯片 / 控制器 + 权限用途 CONNECT:建立连接 ADVERTISE:发送广播

4.2 生活类比

🎙️ 广播员 vs 📞 通话者

  • BLUETOOTH_ADVERTISE 就像在广场上举着牌子宣传:“我在这里!我的名字是XX,可以提供这些服务!” —— 只负责宣告,不建立连接。
  • BLUETOOTH_CONNECT 就像有人看到广告后主动走过来与你握手、交换名片、建立对话通道 —— 此时才涉及连接与数据传输。

在实际设备上,一个 BLE 外围设备(如智能手环)同时需要 ADVERTISE(广播自身)和 CONNECT(接受手机连接请求并传输数据)。

4.3 常见误区

  • 误区1:只要声明了 BLUETOOTH_CONNECT 就能自动广播。—— 错的。广播必须单独申请 BLUETOOTH_ADVERTISE,两者互不替换。
  • 误区2:BLUETOOTH_ADVERTISE 只用于手机做外围模式。—— 部分成立但不全面。手机也可以作为中央设备主动扫描并连接外围设备,但若手机作为外围设备被其他设备连接,仍然需要 ADVERTISE 权限发广播宣告自身。
  • 误区3:两个权限都必须动态请求,且不能同时请求。—— 可以同时请求。系统会分别弹窗授权,用户可以选择全部同意、拒绝其中任意一个。
  • 误区4:CONNECT 权限与扫描权限重复。—— 不重复。扫描(BLUETOOTH_SCAN)仅可获得设备存在性信息;连接(CONNECT)才能读取具体服务、特性、描述符。
  • 误区5:声明了 ADVERTISE 就可以在后台无限广播。—— Android 12+ 限制后台广播时长和频率,还需注意 startAdvertising() 回调的延迟和唤醒锁策略。

4.4 典型声明与使用场景

  • 场景1:经典 BLE 外围设备(如心率带) —— 应用需要 BLUETOOTH_ADVERTISE 发送广播,同时需要 BLUETOOTH_CONNECT 接受手机连接并传输心率数据。
  • 场景2:手机作为中央设备连接已配对的蓝牙键盘 —— 仅需要 BLUETOOTH_CONNECT(不需要广播)。
  • 场景3:BLE 信标(Beacon)广播 —— 仅需要 BLUETOOTH_ADVERTISE,不建立连接。
  • 场景4:点对点文件传输(经典蓝牙) —— 需要 BLUETOOTH_CONNECT,不需要广播(经典蓝牙使用 Inquiry/Page 配对流程与 BLE 广播不同)。

4.5 声明要求(AndroidManifest + 运行时)

声明类型代码/配置说明
静态声明
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
Android 12+ 必须在 manifest 中显式声明这两个 normal 权限(与旧版危险权限不同)
运行时请求(典型)
ActivityResultLauncher<String> launcher = 
    registerForActivityResult(...);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    launcher.launch(Manifest.permission.BLUETOOTH_CONNECT);
    launcher.launch(Manifest.permission.BLUETOOTH_ADVERTISE);
}
尽管是 normal 权限,但 Android 12+ 对于 BLUETOOTH_CONNECT 仍要求运行时请求(ADVERTISE 在部分设备上可能静默授权,仍需 manifest 声明)
特殊场景:仅广播
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
如果应用只作为信标发送广播,不需要连接,则只声明 ADVERTISE 即可,但仍需确保 BLE 可用且位置服务不强制(Android 12+ 已取消位置依赖)

💡 最小权限原则:

  • 只进行扫描 → 仅 BLUETOOTH_SCAN
  • 只发起连接(已知设备)→ BLUETOOTH_CONNECT
  • 只做广播(如信标)→ BLUETOOTH_ADVERTISE
  • 如果需要扫描后再连接(从发现到交互),则同时申请 SCAN + CONNECT

4.6 自我检测

题目1(单选): 你正在开发一个 BLE 外围设备 App,它需要定期广播温度数据,并且也允许其他 App 连接它来读取历史记录。这个 App 应该请求哪些蓝牙权限?

  1. 仅 BLUETOOTH_ADVERTISE
  2. 仅 BLUETOOTH_CONNECT
  3. 同时请求 BLUETOOTH_ADVERTISE 和 BLUETOOTH_CONNECT
  4. BLUETOOTH_SCAN + BLUETOOTH_ADVERTISE

✅ 答案:C —— 广播需要 ADVERTISE,接受连接并交互数据需要 CONNECT。注意这里 App 自己不需要扫描,因此不需要 BLUETOOTH_SCAN。

题目2(判断): 在 Android 12+ 上,只要在 manifest 中声明了 BLUETOOTH_CONNECT,就可以调用 startAdvertising() 方法。

❌ 错误 — startAdvertising() 属于 BLUETOOTH_ADVERTISE 权限保护的方法,仅有 CONNECT 无法调用,会抛出 SecurityException。

4.7 应用边界与注意事项

  • 硬件依赖: 即使拥有 ADVERTISE 权限,若设备 BLE 不支持 Peripheral 模式(部分旧款手机仅支持 Central),广播将失败。通过 BluetoothAdapter.isMultipleAdvertisementSupported() 检测。
  • 版本兼容: Android 12 以下设备不识别这两个新权限,运行时请求会因 Build.VERSION.SDK_INT < Build.VERSION_CODES.S 而跳过。可降级使用旧版 BLUETOOTH 权限。
  • 用户撤销: 用户可以在系统设置中单独关闭 BLUETOOTH_CONNECT 或 BLUETOOTH_ADVERTISE,应用应当通过 checkSelfPermission() 持续校验。
  • 与位置权限的关联: 在 Android 12+ 中,扫描需要位置但连接和广播不再需要位置。但在部分定制厂商系统上,若启用 “始终允许” 位置的旧策略,仍可能需要位置权限才能正常配对。

📌 关键行动点:

  • 更新 targetSdkVersion 到 31+ 后请立即迁移至新权限体系。
  • 在 manifest 中声明你需要的每个细粒度权限,不要隐藏。
  • 运行时分别处理每个权限的授权回调,避免笼统假设。