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,提问作者Евгений Смирнов
相关产品推荐
相关产品推荐

