You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android蓝牙发现功能异常:扫描无回调问题求助

解决Android蓝牙扫描收不到BroadcastReceiver回调的问题

嘿,我看了你遇到的蓝牙扫描没触发ACTION_FOUND回调的问题,结合你的代码和日志来看,核心问题大概率是权限缺失,还有几个小细节需要调整,我帮你一步步解决:

一、核心问题:权限不足(Android 6.0+必现)

从Android 6.0(API Level 23)开始,蓝牙扫描需要位置权限(ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION),因为系统把蓝牙扫描和位置服务绑定了——如果没有位置权限,系统会直接阻止蓝牙设备发现,自然收不到ACTION_FOUND的广播。

另外如果你的测试设备是Android 12(API Level 31)及以上,还需要新增蓝牙专属权限。

二、具体修复步骤

1. 补充AndroidManifest.xml权限

打开你的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_CONNECT" />

<!-- 声明设备支持蓝牙 -->
<uses-feature android:name="android.hardware.bluetooth" android:required="true" />

2. 动态申请位置权限(API 23+)

因为位置权限是危险权限,必须在运行时申请,不能只靠Manifest。修改你的ScanOnClick方法,先检查权限再启动扫描:

private static final int REQUEST_LOCATION_PERMISSION = 2;

public void ScanOnClick(View v) {
    Log.i("NKNKNK","SCAN button clicked");
    if (BA == null) {
        BA = BluetoothAdapter.getDefaultAdapter();
    }
    if (!BA.isEnabled()) {
        Log.i("NKNKNK", "Bluetooth is not enabled");
        return;
    }

    // 检查位置权限
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {
        // 申请权限
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_LOCATION_PERMISSION);
        return;
    }

    // 权限已获取,启动扫描
    if (BA.isDiscovering()) {
        BA.cancelDiscovery();
    }
    Log.i("NKNKNK","Starting discovery logged");
    BA.startDiscovery();
}

还要添加权限申请结果的回调:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_LOCATION_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限通过,重新启动扫描
            if (BA != null && BA.isEnabled() && !BA.isDiscovering()) {
                BA.startDiscovery();
            }
        } else {
            Log.i("NKNKNK", "Location permission denied, cannot scan Bluetooth devices");
            // 可以提示用户需要权限才能扫描
        }
    }
}

3. 完善BroadcastReceiver的IntentFilter(可选但推荐)

只监听ACTION_FOUND不够直观,建议添加扫描开始和结束的广播,方便调试:
修改onCreate里的IntentFilter注册:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // ... 其他代码 ...

    IntentFilter filter = new IntentFilter();
    filter.addAction(BluetoothDevice.ACTION_FOUND);
    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    registerReceiver(mReceiver, filter);

    // 初始化BluetoothAdapter
    BA = BluetoothAdapter.getDefaultAdapter();
}

然后在mReceiver里添加对应处理:

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        Log.i("NKNKNK","onReceive method");
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            Log.i("NKNKNK","Device found: " + device.getName() + "; MAC " + device.getAddress());
        } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
            Log.i("NKNKNK", "Bluetooth discovery started");
        } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
            Log.i("NKNKNK", "Bluetooth discovery finished");
        }
    }
};

4. 优化BluetoothAdapter实例获取

不要在ScanOnClick里重复获取BA,直接在onCreate里初始化一次即可,避免不必要的系统调用。

三、测试验证

  1. 重新编译安装APP
  2. 打开蓝牙后,点击扫描按钮,会弹出位置权限申请对话框,允许权限
  3. 此时查看日志,应该能看到Bluetooth discovery started,然后陆续收到Device found的日志

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

火山引擎 最新活动