Android蓝牙输出流写入触发空指针异常问题求助
解决Android蓝牙向Arduino写入数据时的空指针异常
看起来你遇到的问题是蓝牙连接建立后,写入输出流触发空指针,但接收数据正常——这通常意味着负责写入的线程或输出流对象没有被正确初始化。结合你给出的代码片段,我帮你梳理几个关键问题和修复方案:
1. 补全缺失的ConnectedThread类
你的代码里只定义了监听和连接线程,但负责实际数据读写的ConnectedThread完全缺失了,这大概率是空指针的根源。这个线程需要初始化输入/输出流,并提供写入数据的方法,添加如下代码:
private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) { Log.d(TAG, "ConnectedThread: 创建连接线程"); mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // 关闭连接进度对话框(如果之前显示的话) if(mProgressDialog != null){ mProgressDialog.dismiss(); } try { // 获取蓝牙Socket的输入输出流 tmpIn = mmSocket.getInputStream(); tmpOut = mmSocket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "ConnectedThread: 获取流失败: " + e.getMessage()); } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { byte[] buffer = new byte[1024]; // 缓冲区存储传入的数据 int bytes; // 读取的字节数 // 持续监听输入流直到连接断开或发生异常 while (true) { try { // 从输入流读取数据 bytes = mmInStream.read(buffer); String incomingMessage = new String(buffer, 0, bytes); Log.d(TAG, "收到数据: " + incomingMessage); // 这里可以把数据传递到UI线程更新文本框,比如用Handler或接口回调 } catch (IOException e) { Log.e(TAG, "ConnectedThread: 输入流读取异常: " + e.getMessage()); break; } } } // 对外提供的写入数据方法 public void write(byte[] bytes) { String text = new String(bytes, Charset.defaultCharset()); Log.d(TAG, "发送数据: " + text); try { mmOutStream.write(bytes); } catch (IOException e) { Log.e(TAG, "ConnectedThread: 写入数据失败: " + e.getMessage()); } } // 关闭连接 public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } }
2. 完善connected方法
你的代码里调用了connected(socket,mmDevice)但没有实现,这个方法需要初始化并启动ConnectedThread:
private void connected(BluetoothSocket socket, BluetoothDevice device) { Log.d(TAG, "connected: 启动数据读写线程"); // 创建并启动负责数据传输的线程 mConnectedThread = new ConnectedThread(socket); mConnectedThread.start(); }
3. 添加对外暴露的发送数据接口
在BluetoothService类中添加一个方法,让你的Activity可以调用它发送数据:
// 向蓝牙设备发送数据的对外方法 public void write(byte[] out) { // 确保连接线程已初始化 ConnectedThread r; synchronized (this) { if (mConnectedThread == null) return; r = mConnectedThread; } r.write(out); }
4. 补全startClient方法的逻辑
你的代码里startClient方法写到一半中断了,确保它能正确完成连接流程:
public void startClient(BluetoothDevice device, UUID uuid){ Log.d(TAG, "startClient: Started."); // 初始化连接进度对话框 mProgressDialog = ProgressDialog.show(mContext, "连接中...", "请稍候", true); // 取消正在进行的旧连接线程 if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } // 创建新的连接线程并启动 mConnectThread = new ConnectThread(device, uuid); mConnectThread.start(); }
5. 发送数据的注意事项
在Activity中调用发送方法时,要确保:
- 蓝牙连接已经完全建立(即
mConnectedThread不为null) - 发送的数据转换为合法的字节数组(比如字符串转字节:
"forward".getBytes())
示例调用:
// 假设你已经获取了BluetoothService实例 if (bluetoothService != null) { bluetoothService.write("open_light".getBytes()); }
问题根源说明
接收数据正常说明蓝牙物理连接是通的,但写入时触发空指针,本质是负责写入的ConnectedThread或其内部的mmOutStream没有被初始化——因为你之前的代码里完全缺少这个线程的定义和启动逻辑。
内容的提问来源于stack exchange,提问作者Tatsuo
相关产品推荐
相关产品推荐

