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

Android蓝牙设备搜索项目无显示问题求助

蓝牙设备搜索项目无法显示设备列表的问题排查与修复

核心问题分析与修复步骤

1. ArrayAdapter未初始化(触发空指针异常)

代码中仅声明了aAdapter但未实例化,调用aAdapter.add()时会直接抛出空指针,导致设备数据根本无法添加到列表。

修复:在onCreate中提前初始化ArrayAdapter并绑定到ListView:

// 初始化适配器,使用系统默认的列表项布局
aAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
out = findViewById(R.id.simpleListView);
out.setAdapter(aAdapter); // 一次绑定即可,无需在广播中重复设置

2. 缺少必要权限

Android 6.0及以上版本,蓝牙搜索依赖位置权限;Android 12+还需单独的蓝牙扫描权限,没有这些权限系统会直接拦截搜索请求。

修复:在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-feature android:name="android.hardware.bluetooth" android:required="true" />

同时添加动态权限申请(位置权限属于危险权限,必须用户主动授权):

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

3. 蓝牙发现时机错误

当前代码在Activity创建时直接启动搜索,但如果用户刚通过系统弹窗开启蓝牙,蓝牙模块可能尚未完全就绪,导致搜索失败。

修复:在onActivityResult中处理蓝牙开启成功的回调,再启动搜索:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_ENABLE_BLUETOOTH) {
        if (resultCode == RESULT_OK) {
            // 蓝牙就绪后再启动搜索
            if (mBTA.isDiscovering()) {
                mBTA.cancelDiscovery();
            }
            mBTA.startDiscovery();
        } else {
            Toast.makeText(this, "蓝牙未开启,无法搜索设备", Toast.LENGTH_SHORT).show();
        }
    }
}

4. 未处理设备名称为空的情况

部分蓝牙设备未设置名称,直接调用device.getName()会导致字符串拼接异常,甚至崩溃。

修复:在广播接收器中添加空值判断:

private class SingBroadcastReceiver extends 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 deviceName = device.getName() != null ? device.getName() : "未知设备";
            String deviceInfo = deviceName + "\n" + device.getAddress();
            aAdapter.add(deviceInfo);
        }
    }
}

5. 未注销广播接收器

动态注册的广播接收器如果不注销,会导致内存泄漏,影响应用性能。

修复:在onDestroy中注销广播并停止蓝牙搜索:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mReceiver != null) {
        unregisterReceiver(mReceiver);
    }
    if (mBTA != null && mBTA.isDiscovering()) {
        mBTA.cancelDiscovery();
    }
}

修改后的完整MainActivity代码

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends Activity {
    private BluetoothAdapter mBTA;
    private SingBroadcastReceiver mReceiver;
    private ArrayAdapter<String> aAdapter;
    private ListView out;

    private static final int REQUEST_ENABLE_BLUETOOTH = 1;
    private static final int REQUEST_LOCATION_PERMISSION = 2;

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

        // 初始化列表和适配器
        out = findViewById(R.id.simpleListView);
        aAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
        out.setAdapter(aAdapter);

        // 获取蓝牙适配器
        mBTA = BluetoothAdapter.getDefaultAdapter();
        if (mBTA == null) {
            Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
            return;
        }

        // 检查蓝牙状态
        if (!mBTA.isEnabled()) {
            Intent enableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBT, REQUEST_ENABLE_BLUETOOTH);
        } else {
            // 蓝牙已开启,检查权限后启动搜索
            checkPermissionAndStartDiscovery();
        }

        // 注册广播接收器
        mReceiver = new SingBroadcastReceiver();
        IntentFilter ifilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        this.registerReceiver(mReceiver, ifilter);
    }

    // 检查权限并启动蓝牙搜索
    private void checkPermissionAndStartDiscovery() {
        if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION);
        } else {
            startBluetoothDiscovery();
        }
    }

    // 启动蓝牙搜索
    private void startBluetoothDiscovery() {
        if (mBTA.isDiscovering()) {
            mBTA.cancelDiscovery();
        }
        mBTA.startDiscovery();
        Toast.makeText(this, "开始搜索蓝牙设备...", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_ENABLE_BLUETOOTH) {
            if (resultCode == RESULT_OK) {
                checkPermissionAndStartDiscovery();
            } else {
                Toast.makeText(this, "蓝牙未开启,无法搜索设备", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_LOCATION_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startBluetoothDiscovery();
            } else {
                Toast.makeText(this, "需要位置权限才能搜索蓝牙设备", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private class SingBroadcastReceiver extends 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 deviceName = device.getName() != null ? device.getName() : "未知设备";
                String deviceInfo = deviceName + "\n" + device.getAddress();
                aAdapter.add(deviceInfo);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
        }
        if (mBTA != null && mBTA.isDiscovering()) {
            mBTA.cancelDiscovery();
        }
    }
}

内容的提问来源于stack exchange,提问作者Евгений Смирнов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:09:52