Android USB直连激光打印机打印失败,求可行实现方案
Android USB 激光打印机直接打印问题解决方案
现有代码的核心问题
- 权限请求是异步操作,你在
checkInfo()中直接调用startPrinting()时,权限尚未授予,导致设备无法正常打开 - 未筛选USB设备,遍历所有设备后仅取最后一个,没有判断是否为打印机
- 错误选择USB端点:直接取第一个端点,未确认是**输出(OUT)**方向的端点(打印机需要向OUT端点发送数据)
- 数据发送逻辑错误:
UsbRequest使用时未向output_buffer写入要发送的数据,导致无内容传输 - 广播接收器获取权限后未触发打印逻辑,权限授予后的处理代码为空
修复后的代码示例
public class MainActivity extends Activity { PendingIntent mPermissionIntent; Button btnCheck; TextView textInfo; UsbDevice targetPrinter; UsbManager manager; private static final String ACTION_USB_PERMISSION = "com.example.myapp.USB_PERMISSION"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnCheck = findViewById(R.id.check); textInfo = findViewById(R.id.info); btnCheck.setOnClickListener(v -> { textInfo.setText(""); scanForPrinters(); }); } private void scanForPrinters() { manager = (UsbManager) getSystemService(Context.USB_SERVICE); mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); registerReceiver(mUsbReceiver, filter); HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); for (UsbDevice device : deviceList.values()) { // 通过USB设备类筛选打印机(类编号为7) if (device.getDeviceClass() == UsbConstants.USB_CLASS_PRINTER) { targetPrinter = device; manager.requestPermission(device, mPermissionIntent); return; // 找到第一个打印机设备,可根据需求调整为多选 } } textInfo.setText("未找到USB连接的打印机"); } private void startPrinting(final UsbDevice printerDevice) { new Thread(() -> { UsbDeviceConnection conn = null; UsbInterface usbInterface = null; try { // 获取打印机的第一个接口(通常打印机仅一个接口) usbInterface = printerDevice.getInterface(0); UsbEndpoint outEndpoint = null; // 寻找输出方向的端点 for (int i = 0; i < usbInterface.getEndpointCount(); i++) { UsbEndpoint endpoint = usbInterface.getEndpoint(i); if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) { outEndpoint = endpoint; break; } } if (outEndpoint == null) { Log.e("PrintError", "未找到输出端点"); runOnUiThread(() -> textInfo.setText("未找到打印机输出端点")); return; } // 打开设备并建立连接 conn = manager.openDevice(printerDevice); if (conn == null) { Log.e("PrintError", "无法打开打印机设备"); runOnUiThread(() -> textInfo.setText("无法打开打印机设备")); return; } // 声明USB接口 if (!conn.claimInterface(usbInterface, true)) { Log.e("PrintError", "无法声明USB接口"); runOnUiThread(() -> textInfo.setText("无法声明USB接口")); return; } // 准备打印数据(使用ESC/POS指令,大部分激光打印机支持) String printData = "\n这是测试打印内容\n\n" + "----------------\n" + "测试完成\n"; byte[] dataBytes = printData.getBytes(StandardCharsets.UTF_8); // 使用bulkTransfer发送数据(更简单可靠) int transferred = conn.bulkTransfer(outEndpoint, dataBytes, dataBytes.length, 5000); if (transferred > 0) { Log.i("PrintSuccess", "已传输 " + transferred + " 字节数据"); runOnUiThread(() -> textInfo.setText("打印请求已发送")); } else { Log.e("PrintError", "数据传输失败,返回值:" + transferred); runOnUiThread(() -> textInfo.setText("数据传输失败")); } } catch (Exception e) { Log.e("PrintException", "打印失败", e); runOnUiThread(() -> textInfo.setText("打印失败:" + e.getMessage())); } finally { // 释放资源 if (conn != null && usbInterface != null) { conn.releaseInterface(usbInterface); conn.close(); } try { unregisterReceiver(mUsbReceiver); } catch (Exception e) { Log.e("ResourceError", "释放接收器失败", e); } } }).start(); } private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if (device != null && device.equals(targetPrinter)) { startPrinting(device); } } else { Log.d("PrintError", "权限被拒绝:" + device); runOnUiThread(() -> textInfo.setText("打印机权限被拒绝")); } } } } }; @Override protected void onDestroy() { super.onDestroy(); try { unregisterReceiver(mUsbReceiver); } catch (Exception ignored) {} } }
修复说明
- 增加打印机设备筛选逻辑,通过USB设备类编号精准识别打印机
- 权限请求完成后在广播接收器中触发打印,确保权限已授予
- 正确寻找输出方向的USB端点,避免发送到错误端点
- 使用更稳定的
bulkTransfer方法发送数据,简化实现逻辑 - 补充错误处理和UI反馈,便于排查问题
- 修复资源释放逻辑,避免内存泄漏
可用实现库推荐
- USB Printer Library:针对Android USB打印封装的轻量库,支持ESC/POS指令集,兼容大部分激光、热敏打印机,无需手动处理USB权限和端点逻辑
- Android Print Framework:Android 4.4及以上系统自带的打印框架,系统自动处理设备发现和权限,只需构建打印文档即可,缺点是依赖打印机厂商驱动支持,部分小众设备可能不兼容
内容的提问来源于stack exchange,提问作者Mathan Kumar
相关产品推荐
相关产品推荐

