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

Android Studio开发APP连接ESP32蓝牙时崩溃问题求助

蓝牙连接ESP32时APP崩溃问题

问题描述

开发一款终端APP,通过蓝牙连接ESP32读取测量数据。已完成界面和功能按钮开发,点击「列出设备」可显示所有蓝牙设备,但点击ESP32设备连接时APP崩溃,已配置Manifest中所有相关权限仍未解决。

报错信息

FATAL EXCEPTION: Thread-3
Process: com.example.plavi_zub_2, PID: 32283
java.lang.NullPointerException: 尝试对空对象引用调用虚拟方法 'java.io.InputStream android.bluetooth.BluetoothSocket.getInputStream()'
    at com.example.plavi_zub_2.MainActivity$SendReceive.<init>(MainActivity.java:326)
    at com.example.plavi_zub_2.MainActivity$ClientClass.run(MainActivity.java:302)

问题根源

报错核心是BluetoothSocket对象为空,直接原因是ClientClass的权限判断逻辑完全颠倒:

  • 构造方法中,仅当没有BLUETOOTH_CONNECT权限时才尝试创建socket,有权限时反而触发权限申请,导致socket初始化失败。
  • run方法中同样逻辑错误,有权限时去申请权限,无权限时才执行连接操作,此时socket大概率未初始化,后续调用socket.getInputStream()自然触发空指针崩溃。

修复方案

修改ClientClass的构造方法和run方法,修正权限判断逻辑,并增加空指针防御:

private class ClientClass extends Thread {
    private BluetoothDevice device;
    private BluetoothSocket socket;

    @RequiresApi(api = Build.VERSION_CODES.S)
    public ClientClass(BluetoothDevice device1) {
        device = device1;

        try {
            // 有权限时才创建socket,无权限则申请
            if (ActivityCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
                socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_CONNECT}, 44);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        try {
            // 确保有权限且socket不为空时才连接
            if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
                if (socket != null) {
                    socket.connect();
                    Message message = Message.obtain();
                    message.what = STATE_CONNECTED;
                    handler.sendMessage(message);

                    sendReceive = new SendReceive(socket);
                    sendReceive.start();
                } else {
                    // socket为空时提示连接失败
                    Message message = Message.obtain();
                    message.what = STATE_CONNECTION_FAILED;
                    handler.sendMessage(message);
                }
            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_CONNECT}, 44);
                // 权限申请后需用户重新触发连接,这里先提示失败
                Message message = Message.obtain();
                message.what = STATE_CONNECTION_FAILED;
                handler.sendMessage(message);
            }

        } catch (IOException e) {
            e.printStackTrace();
            Message message = Message.obtain();
            message.what = STATE_CONNECTION_FAILED;
            handler.sendMessage(message);
        }
    }
}

额外注意事项

  1. UUID一致性:必须保证APP中MY_UUID与ESP32蓝牙服务端的UUID完全一致,否则会出现连接失败。
  2. 权限回调处理:当前代码未处理权限申请后的回调,建议重写onRequestPermissionsResult方法,在权限授予后重新触发连接逻辑。
  3. 空指针防御:所有使用BluetoothSocket的地方都要先判空,避免类似崩溃。
  4. 线程规范:UI操作必须通过Handler在主线程执行,当前代码已遵循该规范,需保持。

内容的提问来源于stack exchange,提问作者Miloš Stojanović

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 16:16:06