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

Android蓝牙设备列表异常:已配对设备显示正常,未配对设备不显示

解决未配对蓝牙设备无法加载的问题

老哥,我看了你的代码,已配对设备能正常显示,但未配对设备扫不出来,主要是两个常见问题卡壳了:权限不足和扫描时机不对,我给你一步步捋清楚怎么改:

1. 补充必要的蓝牙扫描权限

从Android 6.0(API 23)开始,蓝牙扫描需要位置相关权限;Android 12(API 31)及以上还新增了专门的蓝牙扫描权限,你得先在AndroidManifest.xml里声明静态权限:

<!-- 基础蓝牙操作权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- Android 6.0+ 蓝牙扫描必备的位置权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- Android 12+ 专属蓝牙扫描权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<!-- 可选:如果需要让当前设备被其他蓝牙设备发现 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

因为位置权限属于危险权限,必须动态申请,在你的BluetoothListActivity里添加权限检查和申请的方法:

private static final int REQUEST_PERMISSIONS = 1;

// 检查是否拥有所需权限
private boolean checkPermissions() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        // Android 12+ 需同时检查蓝牙扫描和位置权限
        return ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED
                && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
    } else {
        // 低版本仅需检查位置权限
        return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
    }
}

// 请求权限
private void requestPermissions() {
    List<String> permissionsNeeded = new ArrayList<>();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
            permissionsNeeded.add(Manifest.permission.BLUETOOTH_SCAN);
        }
    }
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
    }
    if (!permissionsNeeded.isEmpty()) {
        ActivityCompat.requestPermissions(this, permissionsNeeded.toArray(new String[0]), REQUEST_PERMISSIONS);
    }
}

2. 调整扫描时机,确保蓝牙开启后再启动扫描

你当前代码在onCreate里直接启动扫描,但如果蓝牙是通过ACTION_REQUEST_ENABLE刚开启的,这时候onCreate里的bluetoothAdapter.isEnabled()是false,扫描根本没执行。得在蓝牙启用成功后、权限申请通过后,再启动扫描:

修改onCreate方法,调整初始化逻辑顺序:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_bluetooth_list);
    
    if(bluetoothAdapter == null){
        Toast.makeText(this, "Bluetooth not supported.", Toast.LENGTH_SHORT).show();
        finish();
        return;
    }

    // 先初始化适配器和列表控件
    pairedDevicesArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
    newDevicesArrayAdapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);

    pairedDevicesList = findViewById(R.id.pairedDevicesListView);
    newDevicesList = findViewById(R.id.newDevicesListView);

    pairedDevicesList.setAdapter(pairedDevicesArrayAdapter);
    newDevicesList.setAdapter(newDevicesArrayAdapter);

    // 注册广播接收器
    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
    this.registerReceiver(broadcastReceiver, filter);
    filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    this.registerReceiver(broadcastReceiver,filter);

    // 加载已配对设备
    Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
    if(pairedDevices.size() > 0 ){
        for(BluetoothDevice device : pairedDevices){
            pairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
        }
    }else{
        pairedDevicesArrayAdapter.add("No device found");
    }

    // 先检查权限,再处理蓝牙启用和扫描
    if (checkPermissions()) {
        handleBluetoothAndScan();
    } else {
        requestPermissions();
    }
}

新增两个辅助方法处理蓝牙状态和扫描:

// 处理蓝牙状态,决定是否启动扫描
private void handleBluetoothAndScan() {
    if (!bluetoothAdapter.isEnabled()) {
        Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(i, ENABLE_REQUEST);
    } else {
        startBluetoothDiscovery();
    }
}

// 启动蓝牙扫描(先清空旧列表避免重复数据)
private void startBluetoothDiscovery() {
    if (bluetoothAdapter.isDiscovering()) {
        bluetoothAdapter.cancelDiscovery();
    }
    newDevicesArrayAdapter.clear();
    bluetoothAdapter.startDiscovery();
}

最后修改权限申请回调和蓝牙启用回调:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == ENABLE_REQUEST){
        if(resultCode == RESULT_OK){
            // 蓝牙启用成功,立即启动扫描
            startBluetoothDiscovery();
        } else {
            Toast.makeText(this, "You need to enable the bluetooth.", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSIONS) {
        boolean allGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allGranted = false;
                break;
            }
        }
        if (allGranted) {
            handleBluetoothAndScan();
        } else {
            Toast.makeText(this, "Permissions are required to scan Bluetooth devices.", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

3. 额外优化:避免空指针异常

有些蓝牙设备没有名称,直接调用device.getName()会导致空指针,在广播接收器里加个判断:

private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (device != null && device.getBondState() != BluetoothDevice.BOND_BONDED) {
                String deviceName = device.getName();
                String deviceAddress = device.getAddress();
                // 设备名称为空时,仅显示地址
                String displayText = deviceName != null ? deviceName + "\n" + deviceAddress : deviceAddress;
                newDevicesArrayAdapter.add(displayText);
            }
        }else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
            if (newDevicesArrayAdapter.getCount() == 0) {
                newDevicesArrayAdapter.add("No device found");
            }
        }
    }
};

这样修改后,应该就能正常扫描并显示未配对的蓝牙设备了。

内容的提问来源于stack exchange,提问作者JayJona

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:56:58