You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:15:33