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

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. 空指针异常检查

确保myBluetoothAdapterbluFoundArrayAdapter已经在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

火山引擎 最新活动