Android Java蓝牙数据接收异常:while(true)导致APP无法运行
问题原因
你把蓝牙数据接收的无限while(true)循环直接写在了onCreate方法中——而onCreate是运行在Android的UI主线程里的。主线程一旦被这个死循环持续占用,就无法处理界面绘制、用户点击等UI相关任务,直接导致APP卡死、停止响应。
另外,代码里还有个细节问题:inputStream.read(b)是阻塞式方法,在没读到数据时会一直等待,这会进一步加剧主线程的阻塞。
解决方案
把蓝牙数据接收逻辑移到子线程中执行,同时子线程不能直接修改UI,必须通过Android提供的UI线程切换机制来更新界面。下面是修改后的完整代码示例:
static final UUID mUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private Button button1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button1 = findViewById(R.id.button); BluetoothAdapter btadapter = BluetoothAdapter.getDefaultAdapter(); System.out.println(btadapter.getBondedDevices()); BluetoothDevice hc06 = btadapter.getRemoteDevice("98:D3:31:B3:15:81"); System.out.println(hc06.getName()); BluetoothSocket btSocket = null; int counter = 0; do { try { btSocket = hc06.createRfcommSocketToServiceRecord(mUUID); System.out.println(btSocket); btSocket.connect(); System.out.println(btSocket.isConnected()); } catch (IOException e) { e.printStackTrace(); } counter++; } while (btSocket != null && !btSocket.isConnected() && counter < 3); // 启动子线程处理蓝牙数据接收 if (btSocket != null && btSocket.isConnected()) { new Thread(() -> { InputStream inputStream = null; try { inputStream = btSocket.getInputStream(); inputStream.skip(inputStream.available()); byte[] b = new byte[6]; while (!Thread.currentThread().isInterrupted()) { // 用线程中断代替死循环,方便后续停止 int readLength = inputStream.read(b); // 记录实际读取的字节数,避免空数据问题 if (readLength > 0) { System.out.println(b[0]); // 切换回主线程更新UI runOnUiThread(() -> { if (b[0] == 2) { button1.setBackgroundColor(Color.GREEN); } else { button1.setBackgroundColor(Color.RED); } }); } } } catch (IOException e) { e.printStackTrace(); } finally { try { if (inputStream != null) inputStream.close(); if (btSocket != null) btSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } }
关键修改点
- 把蓝牙接收逻辑放到独立的
Thread中,彻底避免阻塞UI主线程。 - 用
Thread.currentThread().isInterrupted()代替while(true),后续可以通过thread.interrupt()安全停止接收线程。 - 使用
runOnUiThread()方法切换回主线程修改按钮颜色,符合Android的UI线程操作规则。 - 增加了流和Socket的关闭逻辑,避免资源泄漏。
- 记录
inputStream.read()的返回值,确保读到有效数据再处理,避免无效操作。
内容的提问来源于stack exchange,提问作者CoNe
相关产品推荐
相关产品推荐

