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

Android Java蓝牙周边设备扫描无结果问题求助(附代码)

Android 蓝牙设备扫描无结果排查与修复方案(Java)

常见问题根源

  • 权限适配不全:Android 12+ 新增了BLUETOOTH_SCAN、BLUETOOTH_CONNECT等细分权限,仅在Manifest声明不够,必须动态申请;Android 10及以下扫描蓝牙仍需位置权限(ACCESS_FINE_LOCATION),需确保用户已授予。
  • 蓝牙状态未正确校验:必须主动检查蓝牙是否开启,不能依赖系统设置,需通过ACTION_REQUEST_ENABLE请求用户授权开启,而非直接操作。
  • 扫描API版本不匹配:旧教程常用的startDiscovery()仅适用于经典蓝牙,若扫描BLE设备需使用BluetoothLeScanner.startScan();两类设备的扫描API不通用,需区分场景。
  • 回调未正确注册:BLE扫描的ScanCallback需正确传入扫描方法,经典蓝牙的BroadcastReceiver需注册ACTION_FOUND过滤器,且不能遗漏注册步骤。
  • 后台扫描限制:Android 12+ 对后台扫描频率有严格限制,测试时需保持App在前台运行。

适配Android 12+的BLE扫描代码示例

Manifest权限声明

<!-- 旧版本兼容权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<!-- Android 12+ 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Android 10及以下位置权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="29" />

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

Java核心代码

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;

public class BluetoothScanActivity extends AppCompatActivity {
    private BluetoothLeScanner bleScanner;
    private ListView deviceListView;
    private ArrayList<String> deviceData = new ArrayList<>();
    private ArrayAdapter<String> listAdapter;

    // BLE扫描回调
    private final ScanCallback bleScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            String deviceInfo = String.format("%s | %s",
                    result.getDevice().getName() == null ? "未知设备" : result.getDevice().getName(),
                    result.getDevice().getAddress());
            if (!deviceData.contains(deviceInfo)) {
                deviceData.add(deviceInfo);
                listAdapter.notifyDataSetChanged();
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        deviceListView = findViewById(R.id.device_list);
        listAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, deviceData);
        deviceListView.setAdapter(listAdapter);

        // 初始化蓝牙管理器
        BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();

        // 检查蓝牙支持与开启状态
        if (bluetoothAdapter == null) {
            // 设备不支持蓝牙
            finish();
            return;
        }
        if (!bluetoothAdapter.isEnabled()) {
            startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 100);
            return;
        }

        bleScanner = bluetoothAdapter.getBluetoothLeScanner();
        checkPermissionsAndStartScan();
    }

    private void checkPermissionsAndStartScan() {
        if (checkSelfPermission(Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.BLUETOOTH_SCAN}, 200);
            return;
        }
        bleScanner.startScan(bleScanCallback);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 200 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            bleScanner.startScan(bleScanCallback);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 100 && resultCode == RESULT_OK) {
            checkPermissionsAndStartScan();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (bleScanner != null) {
            bleScanner.stopScan(bleScanCallback);
        }
    }
}

经典蓝牙扫描补充

若需扫描经典蓝牙设备,替换扫描逻辑为:

// 初始化广播接收器
private final BroadcastReceiver bluetoothReceiver = 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);
            String deviceInfo = device.getName() + " | " + device.getAddress();
            if (!deviceData.contains(deviceInfo)) {
                deviceData.add(deviceInfo);
                listAdapter.notifyDataSetChanged();
            }
        }
    }
};

// 注册广播与开始扫描
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(bluetoothReceiver, filter);
bluetoothAdapter.startDiscovery();

// 销毁时注销广播
@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(bluetoothReceiver);
    bluetoothAdapter.cancelDiscovery();
}

测试注意事项

  • 使用真实设备测试,模拟器蓝牙功能不稳定;
  • 保持App在前台,避免后台扫描被系统限制;
  • 确保待扫描设备处于可被发现状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 05:53:19