调用蓝牙连接线程时Android应用加载失败且报StrictMode资源泄露错误
根因分析
- 白屏问题核心原因:主线程被阻塞
你在运行在UI主线程的onCreate方法中直接调用bluetoothFunctionality.run(),该调用不会启动新线程,只会把run方法的逻辑直接放到主线程执行。而BSS.accept()是阻塞调用,会一直停在这等待蓝牙连接,主线程被占用后无法渲染视图、处理交互,直接出现空白屏幕。 - StrictMode资源泄漏报错原因
多处资源未做兜底关闭逻辑:- 连接建立后只关闭了服务端Socket
BSS,建立连接拿到的客户端SocketBS用完后未释放 - 若
accept过程抛出异常,BSS不会走关闭逻辑,直接造成资源泄漏 - 若
manageConnection中写数据抛出异常,BS也不会被释放
- 连接建立后只关闭了服务端Socket
修复步骤
- 正确启动蓝牙工作线程,不要直接调用
run(),改为启动独立工作线程:
把onCreate中的代码
bluetoothFunctionality.run();
修改为
// 若BluetoothFunctionality实现了Runnable接口用这行 new Thread(bluetoothFunctionality).start(); // 若BluetoothFunctionality继承了Thread类直接调用start()即可 // bluetoothFunctionality.start();
- 补全资源关闭逻辑,用finally块保证无论流程正常还是异常,资源都能被释放,修改run方法:
@Override public void run() { BluetoothSocket acceptSocket = null; try { Log.println(Log.INFO,TAG, "[*] Looking for Connection"); acceptSocket = BSS.accept(); if(acceptSocket != null) { x = new EstablishedBTConnection(acceptSocket); Log.println(Log.INFO, TAG, "[*] Connection established!"); x.manageConnection(1); } } catch (IOException e) { e.printStackTrace(); Log.println(Log.INFO, TAG, "[*] Connection failed!"); } finally { // 兜底关闭所有资源 try { if (acceptSocket != null) { acceptSocket.close(); } if (BSS != null) { BSS.close(); } } catch (IOException e) { Log.e(TAG, "Close socket failed", e); } } }
提示:原有代码中的while(true)无意义,accept本身就会阻塞到有连接接入或者抛出异常,不需要死循环包裹
3. 完善EstablishedBTConnection的资源管理逻辑:
public class EstablishedBTConnection { private BluetoothSocket BS; public EstablishedBTConnection(BluetoothSocket BS) { this.BS = BS; } public int manageConnection(int action) { if(action == 1) { try { BS.getOutputStream().write(50); } catch (IOException e) { e.printStackTrace(); } finally { // 如果需要保持长连接就不要在这里关闭,等不需要连接的时候再统一关闭 try { BS.close(); } catch (IOException e) { Log.e(TAG, "Close client socket failed", e); } } } return 0; } }
- 额外注意HC-06模块默认使用的UUID为
00001101-0000-1000-8000-00805F9B34FB,如果使用自定义UUID会直接导致连接失败。
内容的提问来源于stack exchange,提问作者Dennis L
相关产品推荐
相关产品推荐

