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); } } }
额外注意事项
- UUID一致性:必须保证APP中
MY_UUID与ESP32蓝牙服务端的UUID完全一致,否则会出现连接失败。 - 权限回调处理:当前代码未处理权限申请后的回调,建议重写
onRequestPermissionsResult方法,在权限授予后重新触发连接逻辑。 - 空指针防御:所有使用
BluetoothSocket的地方都要先判空,避免类似崩溃。 - 线程规范:UI操作必须通过Handler在主线程执行,当前代码已遵循该规范,需保持。
内容的提问来源于stack exchange,提问作者Miloš Stojanović
相关产品推荐
相关产品推荐

