Android 11设备BluetoothAdapter.startDiscovery()仅单设备可用问题
Android 11(API 30)蓝牙扫描仅部分设备生效的排查与解决
针对同版本Android设备蓝牙扫描不一致的问题,给出以下具体排查和修复步骤:
1. 强制切换定位服务精度模式
Android 11下,蓝牙扫描依赖高精度定位模式(GPS+网络混合定位),若设备设置为「省电模式」(仅网络定位),即使授予了定位权限,部分厂商ROM会限制蓝牙扫描功能。
- 操作路径:系统设置 → 定位服务 → 定位模式 → 切换为「高精度」
2. 确保动态权限的有效性与调用时机
虽然ACCESS_FINE_LOCATION包含ACCESS_COARSE_LOCATION,但需保证调用startDiscovery()前,权限已实际授予,而非仅通过状态判断。修改点击事件的权限检查逻辑:
btnSearch.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 先检查定位权限 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // 重新请求权限,避免直接跳过检查 registerForActivityResult(new ActivityResultContracts.RequestPermissions(), result -> { if (result[0]) { startBluetoothScan(); } else { txtStatus.setText("需要定位权限才能扫描蓝牙设备"); btnSearch.setEnabled(true); } }).launch(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}); return; } // 权限已授予,执行扫描 startBluetoothScan(); } }); // 抽离扫描逻辑到单独方法 @SuppressLint("MissingPermission") private void startBluetoothScan() { enableBt(); txtStatus.setText("Searching..."); btnSearch.setEnabled(false); btnCancel.setVisibility(View.VISIBLE); pbLoading.setVisibility(View.VISIBLE); deviceList.clear(); addresses.clear(); setAdapter(); // 确保蓝牙已稳定开启后再启动扫描 if (bluetoothAdapter.isEnabled()) { bluetoothAdapter.startDiscovery(); } }
3. 监听蓝牙扫描状态广播
通过广播确认扫描是否真的未启动,还是仅未发现设备:
private BroadcastReceiver bluetoothDiscoveryReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 注册扫描状态广播 bluetoothDiscoveryReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { Log.d("BluetoothScan", "扫描已成功启动"); } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { Log.d("BluetoothScan", "扫描已结束"); btnSearch.setEnabled(true); pbLoading.setVisibility(View.GONE); } } }; IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(bluetoothDiscoveryReceiver, filter); } @Override protected void onDestroy() { super.onDestroy(); // 注销广播 if (bluetoothDiscoveryReceiver != null) { unregisterReceiver(bluetoothDiscoveryReceiver); } }
查看Logcat的BluetoothScan日志,确认扫描是否正常启动。
4. 修复enableBt()的异步逻辑
原代码中enableBt()可能未等待蓝牙完全开启就调用startDiscovery(),导致部分设备扫描失败。修改为异步等待蓝牙开启:
@SuppressLint("MissingPermission") private void enableBt() { if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { // 蓝牙成功开启后启动扫描 bluetoothAdapter.startDiscovery(); } else { txtStatus.setText("蓝牙未开启,无法扫描"); btnSearch.setEnabled(true); pbLoading.setVisibility(View.GONE); } }).launch(enableBtIntent); } }
5. 检查厂商定制权限限制
部分Android 11设备(如MIUI、ColorOS等定制ROM)会额外限制蓝牙扫描权限,需手动确认:
- 操作路径:系统设置 → 应用管理 → 你的应用 → 权限管理 → 蓝牙 → 确保「允许扫描附近设备」开关已开启(部分厂商会提前加入API 31+的权限开关)
内容的提问来源于stack exchange,提问作者Martinator
相关产品推荐
相关产品推荐

