Android应用蓝牙设备搜索功能崩溃问题求助
解决蓝牙搜索点击崩溃的问题
我帮你梳理下几个大概率导致崩溃的原因,以及对应的解决办法:
1. 权限缺失(最常见的崩溃诱因)
你目前只添加了基础的蓝牙权限,但从Android 6.0(API Level 23)开始,蓝牙扫描必须依赖位置权限;Android 12(API Level 31)及以上更是新增了专门的BLUETOOTH_SCAN权限,权限不足直接会触发崩溃或扫描失败。
修复步骤:
第一步:补充Manifest权限
在AndroidManifest.xml里添加完整的权限配置:
<!-- 适配Android 11及以下版本的位置权限 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 适配Android 12+的专属扫描权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <!-- 保留你已有的旧版蓝牙权限,限制在Android 11及以下生效 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
第二步:动态申请权限
Android 6.0+需要在代码里主动申请危险权限,不能只靠Manifest配置。添加以下权限检查逻辑:
private static final int REQUEST_BLUETOOTH_PERMISSIONS = 1001; private void checkBluetoothPermissions() { List<String> neededPermissions = new ArrayList<>(); // 根据系统版本判断需要申请的权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { neededPermissions.add(Manifest.permission.BLUETOOTH_SCAN); } } else { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { neededPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION); } } if (!neededPermissions.isEmpty()) { ActivityCompat.requestPermissions(this, neededPermissions.toArray(new String[0]), REQUEST_BLUETOOTH_PERMISSIONS); } else { // 权限已获取,执行扫描逻辑 startBluetoothDiscovery(); } } // 处理权限申请结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_BLUETOOTH_PERMISSIONS) { boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (allGranted) { startBluetoothDiscovery(); } else { Toast.makeText(this, "需要权限才能扫描蓝牙设备", Toast.LENGTH_SHORT).show(); } } }
第三步:修改原搜索方法
把你原来的searchBluetooth方法改成先检查权限:
public void searchBluetooth(View v) { checkBluetoothPermissions(); } private void startBluetoothDiscovery() { // 先判断蓝牙适配器是否初始化成功 if(myBluetoothAdapter == null) { Toast.makeText(this, "当前设备不支持蓝牙功能", Toast.LENGTH_SHORT).show(); return; } if(myBluetoothAdapter.isDiscovering()) { myBluetoothAdapter.cancelDiscovery(); } else { // 移除多余的sendBroadcast(intent); 这行是错误的,ACTION_FOUND广播由系统发送,不需要自己发 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); // 清空列表避免重复添加旧设备 bluFoundArrayAdapter.clear(); myBluetoothAdapter.startDiscovery(); } }
2. 空指针异常检查
确保myBluetoothAdapter和bluFoundArrayAdapter已经在Activity的onCreate方法中正确初始化:
BluetoothAdapter myBluetoothAdapter; ArrayAdapter<String> bluFoundArrayAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_activity_layout); // 初始化蓝牙适配器 myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 初始化ListView和适配器 ListView bluetoothListView = findViewById(R.id.your_listview_id); bluFoundArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1); bluetoothListView.setAdapter(bluFoundArrayAdapter); }
3. 广播接收器的生命周期管理
记得在Activity销毁时注销广播接收器,避免内存泄漏和异常:
@Override protected void onDestroy() { super.onDestroy(); try { unregisterReceiver(receiver); } catch (IllegalArgumentException e) { // 如果接收器未注册,捕获异常防止崩溃 e.printStackTrace(); } }
按上面的步骤调整后,应该就能解决点击崩溃的问题,顺利扫描并显示蓝牙设备了。
内容的提问来源于stack exchange,提问作者user924245




