Android 12应用已授权仍无法扫描周边BLE设备问题
Android 12 BLE扫描返回空列表修复方案
你的代码存在多处逻辑错误,按影响优先级逐一修复即可:
1. 适配器实例引用冲突(最核心问题)
你在类成员位置定义了全局的leDeviceListAdapter,扫描回调里往这个全局实例加设备,但在checkbluetooth方法中又重新创建了一个同名局部适配器实例,UI绑定的是这个没有任何数据的局部实例,自然永远显示0条设备。
// 删掉这两行错误代码 LeDeviceListAdapter leDeviceListAdapter = new LeDeviceListAdapter(); leDeviceListAdapter.setLayoutInflater(getLayoutInflater());
直接给全局的leDeviceListAdapter设置inflater即可,保证扫描回调、UI列表用的是同一个适配器实例。
2. 权限逻辑完全失效
- 你申请了普通应用无法获取的
BLUETOOTH_PRIVILEGED系统权限,会直接导致权限申请失败 NEARBY_DEVICES是权限组,不能直接申请,只需申请组下的BLUETOOTH_SCAN/BLUETOOTH_CONNECT等具体权限即可requestPermissions是异步操作,你调用完权限申请方法立刻执行扫描逻辑,此时用户还没授权,扫描会因权限不足失败- 权限回调中仅判断了
grantResults[0]的状态,完全没有校验其他权限是否授予,逻辑无效 - Android 12(API31+)不需要动态申请旧版
BLUETOOTH/BLUETOOTH_ADMIN权限,这两个权限在targetSdk≥31时会自动授予
修复步骤:
- 从权限申请列表、Manifest文件中删除
BLUETOOTH_PRIVILEGED和NEARBY_DEVICES两项声明 - 不需要BLE扫描结果获取位置的话,给
BLUETOOTH_SCAN加上neverForLocation标记,可免去位置权限要求:<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" tools:targetApi="s" /> - 等
onRequestPermissionsResult回调中确认所有需要的权限都授予后,再执行蓝牙初始化和扫描逻辑,不要调用完申请方法立刻扫描
3. 扫描时序逻辑错误
- 检测到蓝牙未开启时,你弹出了蓝牙开启请求但没有return,代码会继续往下执行扫描逻辑,此时蓝牙未启动,扫描必然失败。需要在弹出开启请求后直接return,等
onActivityResult收到蓝牙开启成功的回调后再启动扫描 - 方法里写了
for (int i=0;i<2;i++)无意义循环,第一次循环启动扫描后scanning标记设为true,第二次循环会立刻停止扫描,等于刚启动就关闭 - 调用
startScan前没有判断bluetoothLeScanner是否为null,蓝牙未就绪时会触发空指针
修复:删掉两层无意义循环,蓝牙状态校验不通过时直接中断方法,等状态就绪后再执行扫描。
4. 适配器ViewHolder逻辑倒置
getView方法中你无论convertView是否为空,上来就新建ViewHolder,正确逻辑应该是先判断convertView是否为null:为null时inflate布局、创建ViewHolder、绑定控件后setTag;不为null时直接从getTag取已缓存的ViewHolder,否则会导致列表渲染异常、数据不显示。
额外排查项
- 测试前先确认周边确实有处于可发现广播状态的BLE设备,可用其他BLE调试APP先验证设备正常广播
- 部分Android 12机型即使权限齐全,系统位置开关关闭时也会屏蔽BLE扫描结果,测试时先打开位置开关
- 不要用模拟器测试BLE功能,模拟器蓝牙驱动普遍存在兼容问题,必须用真机测试
内容的提问来源于stack exchange,提问作者Ali Abdullah
相关产品推荐
相关产品推荐

