You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android蓝牙打印机:如何检测断开连接/写入失败事件?

嘿,这个问题我之前帮好几个开发者解决过——短消息断连能触发异常,但长消息打印到一半设备断开就毫无反应,确实挺闹心的。下面给你几个实用的方案,你可以根据自己的场景组合试试:

针对蓝牙打印机写入中途断连的错误检测方案

1. 主动轮询连接状态

系统自带的蓝牙连接回调有时候在数据传输中不够及时,你可以在写入长消息的过程中,定期检查套接字和设备的连接状态:

  • BluetoothSocket.isConnected()确认套接字是否存活,或者BluetoothDevice.getBondState()判断设备是否还处于绑定状态。
  • 每500ms到1秒轮询一次,一旦发现连接断开,立刻终止写入并抛出异常。
// 写入长消息时的轮询示例
byte[] longData = getLongPrintMessage();
int offset = 0;
while (offset < longData.length) {
    // 检查连接状态
    if (!bluetoothSocket.isConnected()) {
        throw new IOException("Printer disconnected mid-write");
    }
    // 分块写入(避免单次写入过大)
    int chunkSize = Math.min(1024, longData.length - offset);
    outputStream.write(longData, offset, chunkSize);
    offset += chunkSize;
    // 短暂休眠,减少轮询频率
    Thread.sleep(500);
}

注意:轮询间隔别太密,不然会占用过多CPU资源,500ms到1秒的区间比较合适

2. 给套接字设置超时+校验写入字节数

默认的蓝牙OutputStream没有超时机制,断连后写入操作可能会一直阻塞。你可以给套接字设置读写超时,这样超过指定时间没响应就会抛出异常:

// 设置3秒超时,根据你的打印速度调整
bluetoothSocket.setSoTimeout(3000);

另外,每次写入后检查实际写入的字节数,如果和预期不符,大概率是连接出问题了:

int expectedBytes = chunk.length;
int actualBytes = outputStream.write(chunk);
if (actualBytes != expectedBytes) {
    throw new IOException("Partial data written - connection may be lost");
}

3. 监听系统蓝牙断开广播

注册一个广播接收器,监听ACTION_ACL_DISCONNECTED事件,一旦收到目标打印机的断开通知,就标记连接状态为失效,在写入线程中实时检查这个标记:

// 初始化广播接收器
private BroadcastReceiver bluetoothDisconnectReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
            BluetoothDevice disconnectedDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            // 对比你的打印机地址,确认是目标设备断开
            if (disconnectedDevice.getAddress().equals(yourPrinterMacAddress)) {
                isPrinterConnected = false;
            }
        }
    }
};

// 在写入线程中检查标记
while (offset < longData.length && isPrinterConnected) {
    // 写入逻辑...
}
if (!isPrinterConnected) {
    // 处理断连错误,比如提示用户重新连接
    showErrorToast("Printer disconnected during printing");
}

记得在Activity销毁时注销广播接收器,避免内存泄漏

4. 分段写入+打印机确认机制(如果打印机支持)

很多商用蓝牙打印机支持反馈指令——每打印完一段数据会返回一个确认信号。你可以把长消息分成小块,每写完一块就读取打印机的确认:

List<byte[]> messageChunks = splitLongMessage(longMessage, 256); // 按256字节分块
for (byte[] chunk : messageChunks) {
    outputStream.write(chunk);
    outputStream.flush();
    
    // 读取打印机的确认信号(假设返回0x00表示成功)
    byte[] response = new byte[1];
    int readBytes = inputStream.read(response);
    if (readBytes == -1 || response[0] != 0x00) {
        throw new IOException("Printer failed to confirm chunk - connection lost");
    }
}

这个方案最可靠,但前提是你的打印机支持这类反馈指令,需要查一下打印机的SDK文档或者AT指令集。


这些方案可以组合使用,比如“轮询状态+广播监听”的组合,既能覆盖实时断连的场景,又能避免轮询的延迟问题。

内容的提问来源于stack exchange,提问作者dor506

火山引擎 最新活动