1. 为什么要关注 Android 12 蓝牙扫描权限变化
Android 12(API 31)引入的蓝牙扫描权限变更,不是一次简单的 API 升级,而是 Android 隐私保护体系从“粗放授权”向“细粒度、上下文感知授权”转型的关键节点。作为开发者,理解这一变化背后的驱动力、直接风险和自身责任,是确保应用在新版本生态中正常运行的起点。
1.1 新版本隐私保护趋势:从“全有或全无”到“最小化、透明化”
Android 从 6.0 运行时权限模型开始,持续收紧对敏感数据的访问。蓝牙扫描能获取 MAC 地址、设备类型、信号强度甚至位置信息,过去被归类为 ACCESS_FINE_LOCATION 的附属能力。Android 12 将其剥离为独立的 BLUETOOTH_SCAN 权限,并强制与位置权限解耦(部分场景仍需位置,但不再是绑定关系)。这一趋势反映以下原则:
- 权限最小化:应用只应申请完成功能所需的最小权限集合。扫描蓝牙设备不需要知道精确位置,只需扫描权即可。
- 运行时透明:用户在授权时能清晰区分“我要允许你扫描附近的蓝牙设备”和“我要允许你获取我的位置”,避免权限滥用。
- 权限降级与分拆:过去一个权限覆盖多个能力的模式,被拆解为更细粒度的独立权限,每个权限都有明确的语义和使用场景。
概念边界:
BLUETOOTH_SCAN 只允许扫描和获取设备信息,不包含连接权限。BLUETOOTH_CONNECT 用于配对和连接,是另一个独立权限。这种拆分让用户能更精确地控制应用的行为。
1.2 应用兼容风险:不升级,就崩溃
对于 targetSdkVersion 低于 31 的应用,Android 12 仍向后兼容旧权限模型(即仍通过位置权限间接获取扫描能力)。但一旦应用将 targetSdkVersion 升级到 31 或更高,必须按照新规则在运行时同时请求 BLUETOOTH_SCAN 和(必要时)位置权限,否则扫描功能将直接失效,且不会收到任何回调或异常提示。
| Target SDK | 蓝牙扫描权限 | 运行时行为 | 兼容状态 |
|---|---|---|---|
| 30 或更低 | 依赖位置权限 | 旧模型,可扫描 | 兼容,但有废弃警告 |
| 31 或更高 | 必须申请 BLUETOOTH_SCAN + 位置权限 | 新模型,否则静默失败 | 不升级则功能中断 |
除了功能中断,还有以下具体风险:
- 静默失败陷阱:应用可能仍能正常启动,但所有扫描回调(如
onScanResult)不会触发,调试极其困难。 - Google Play 审核风险:从 2022 年底,Google Play 要求新应用和更新必须针对 API 31+,且必须正确声明和使用新权限,否则可能被下架或拒绝更新。
- 多版本适配成本:如果应用仍需支持 Android 11 及以下设备,需要在代码中同时处理两套权限逻辑,增加了条件分支和测试复杂度。
常见误区:有些开发者误以为只在
AndroidManifest.xml 中添加 BLUETOOTH_SCAN 权限声明即可。实际上,Android 12+ 要求该权限必须在运行时通过 requestPermissions() 动态申请,且用户可随时撤销。静态声明 + 动态申请,缺一不可。
1.3 开发者责任边界:从“能用”到“合规”
权限变化的本质是责任前移。过去,系统替开发者决定了“能做什么”;现在,开发者需要主动证明“为什么需要这个权限”、“如何使用该权限”以及“如何保护用户数据”。具体责任边界包括:
- 权限声明与解释:在
AndroidManifest.xml中声明权限时,应配合usesPermissionFlags和maxSdkVersion限制权限仅在必要版本生效。 - 运行时解释与授权:用户拒绝或撤销权限后,应用应优雅降级(例如显示引导界面,而非直接崩溃)。
- 数据最小化采集:扫描到的设备 MAC 地址、RSSI 等数据,不应超出功能需求的范围存储或上传。若用于位置推断,必须遵循位置权限规则。
- 用户撤回权限响应:系统允许用户随时通过设置或运行时弹窗撤销权限。应用需要监听权限变化并动态调整扫描逻辑。
应用边界案例:一个蓝牙防丢器应用,只需要扫描到设备并触发报警,不需要知道设备的精确位置。开发者可以仅申请
BLUETOOTH_SCAN 权限,而不申请位置权限。但如果该应用同时需要在地图上标记设备位置,则必须额外申请 ACCESS_FINE_LOCATION。权限拆分后,用户能准确理解“扫描”和“定位”是两码事。
1.4 核心概念框架图
下图展示了 Android 12 蓝牙权限变化的驱动因素、具体风险以及开发者必须承担的新责任之间的逻辑关系:
1.5 练习题(自我检验)
- 单选题:Android 12 中,
BLUETOOTH_SCAN权限的运行时请求策略是什么?
A. 只需在清单中声明,无需运行时申请
B. 必须运行时动态申请,且用户可随时撤销
C. 与位置权限绑定,申请位置即自动获得扫描权
D. 仅支持系统应用使用,第三方应用无法申请
答案:B - 多选题:以下哪些属于 Android 12 蓝牙权限变化后的开发者责任?
A. 确保 targetSdkVersion 30 以下的应用也能运行新权限模型
B. 在运行时向用户解释为什么需要蓝牙扫描权限
C. 将扫描到的所有设备信息上传到云端
D. 监听权限变化并优雅降级
答案:B、D - 简答题:如果一个蓝牙扫描应用在 Android 12 设备上运行时没有任何错误提示,但始终收不到扫描结果,最可能的原因是什么?如何排查?
参考答案:最可能的原因是应用未正确申请BLUETOOTH_SCAN权限,或未在运行时动态请求。排查时先检查AndroidManifest.xml是否声明了新权限,再检查运行时请求流程是否执行,最后检查用户是否已授权。