Android12+无需位置权限扫描BLE Beacon失败及UUID获取求助
为了避免申请位置权限,我移除了AndroidManifest中的以下位置权限:
<!-- Location Permission --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
并将BLUETOOTH_SCAN权限配置为:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" tools:targetApi="s" />
配置后蓝牙扫描功能正常,但无法发现我的Beacon。根据谷歌官方文档说明:
Note: If you include neverForLocation in your android:usesPermissionFlags, some BLE beacons are filtered from the scan results.
我想知道neverForLocation具体会过滤哪些设备,以及如何在Android 12及以上版本无需申请位置权限的前提下,获取我的Beacon的UUID(注:申请位置权限时功能可正常运行)。
添加neverForLocation标记后,系统会过滤所有被识别为「位置相关BLE信标」的设备,这类设备主要是符合标准信标协议(比如iBeacon、Eddystone、AltBeacon)的设备。因为这类信标的设计初衷就是用于位置定位,系统会默认将它们归类为位置服务依赖设备,因此在声明neverForLocation(即明确告知系统蓝牙扫描不用于定位)时,会被自动过滤。
以下是几种无需位置权限即可获取Beacon UUID的可行方案:
修改Beacon广播数据格式(可控硬件时优先选择)
如果能修改Beacon的硬件配置,调整其广播包结构:- 避免使用iBeacon/Eddystone等标准信标帧格式,不要包含对应协议的特有标识(比如iBeacon的Apple厂商ID、Eddystone的Google服务UUID)。
- 将UUID放入自定义的
Service Data或Manufacturer Data字段中,使用非标准的标识。这样系统不会将其识别为位置信标,就能在neverForLocation模式下被扫描到。
通过蓝牙配对获取(适用于可配对的Beacon)
如果你的Beacon支持蓝牙配对,先引导用户完成设备配对:- 配对成功后,该Beacon会被列入系统的已配对设备列表,即使在neverForLocation模式下,你也可以通过
BluetoothAdapter.getBondedDevices()获取到该设备,进而通过连接读取其UUID等数据。注意配对流程需要用户手动确认。
- 配对成功后,该Beacon会被列入系统的已配对设备列表,即使在neverForLocation模式下,你也可以通过
Android 13+权限补充(效果有限)
如果应用目标版本是Android 13及以上,可以申请BLUETOOTH_CONNECT和BLUETOOTH_ADVERTISE权限(这两个属于普通权限,无需位置权限),同时在扫描时设置更精准的过滤规则(比如指定Beacon的MAC地址),尝试绕过系统的位置信标过滤。但此方法对标准信标的过滤规避效果不稳定,仅作为备选。
内容的提问来源于stack exchange,提问作者Anna

