首页 > 解决方案 > 使用 UsbDeviceConnection android 重启后热敏打印机仅打印一次

问题描述

在我的一个 android 应用程序中,我集成了一项使用热敏打印机直接从应用程序打印收据的功能。我正在使用“UsbDeviceConnection”类来打印我的收据。

这不是每次都能正常工作。就像我打印收据一样,它会打印一次,然后如果我再次发送打印,那么它会将所有字节写入打印机连接,但实际上它并没有打印收据。

要再次打印收据,我必须重新启动打印机一次。因此,如果我将重新启动我的热敏打印机,那么我可以再次打印收据。

我正在使用下面的课程来打印收据。

public class UsbCommunicator {

    private UsbManager mUsbManager;
    private PendingIntent mPermissionIntent;
    private UsbDevice selectedUsbDevice;
    private UsbInterface selectedUsbInterface;
    private int endpointOutId;
    private int endpointInId;
    private final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

    public UsbCommunicator2(Context context) {
        // Create USB manager
        mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

        // Set USB permissions broadcaster
        mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
        context.registerReceiver(mUsbReceiver, new IntentFilter(ACTION_USB_PERMISSION));
    }

    public ArrayList<UsbDevice> getConnectedDevices() {
        ArrayList<UsbDevice> usbDevices = new ArrayList<>();
        // Get every connected USB device and store in HashMap
        HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        // Loop through every connected USB device
        while (deviceIterator.hasNext()) {
            UsbDevice device = deviceIterator.next();
            usbDevices.add(device);
        }
        return usbDevices;
    }

    public void setDevice(UsbDevice device) {
        if (!mUsbManager.hasPermission(device))
            mUsbManager.requestPermission(device, mPermissionIntent);
        else {
            selectedUsbDevice = device;
            setDeviceInterface(device);
            setDeviceEndpoints(device);
        }
    }

    public void sendData(byte[] bytes, CommunicationListener commListener) {
        if (!deviceSelected() || !hasPermission()) return;
        UsbEndpoint outputEndpoint = selectedUsbInterface.getEndpoint(endpointOutId);

        new CommunicatorTask(commListener, outputEndpoint, bytes).execute();
    }

    public boolean deviceSelected() {
        return selectedUsbDevice != null ? true : false;
    }

    public boolean hasPermission() {
        return deviceSelected() && mUsbManager.hasPermission(selectedUsbDevice);
    }

    private void setDeviceInterface(UsbDevice device) {
        // Get the device interface, this is known to be 0 for the targetted Star and Sanei devices, but can vary for other devices
        selectedUsbInterface = device.getInterface(0);
    }

    private void setDeviceEndpoints(UsbDevice device) {
        if (selectedUsbInterface == null) return;
        // Loop through every end point on the interface to find the right end points
        for (int i = 0; i < selectedUsbInterface.getEndpointCount(); i++) {
            UsbEndpoint endpoint = selectedUsbInterface.getEndpoint(i);
            if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT)
                endpointOutId = i;
            else if (endpoint.getDirection() == UsbConstants.USB_DIR_IN)
                endpointInId = i;
        }
    }

    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

        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);
                    // Device permission was granted
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if (device != null) {
                            selectedUsbDevice = device;
                            setDeviceInterface(device);
                            setDeviceEndpoints(device);
                        }
                    }
                }
            }
        }
    };

    private class CommunicatorTask extends AsyncTask<Void, Void, Integer> {

        private CommunicationListener commListener;
        private UsbEndpoint outputEndpoint;
        private byte[] bytes;
        private UsbDeviceConnection connection;

        public CommunicatorTask(CommunicationListener commListener, UsbEndpoint outputEndpoint, byte[] bytes) {
            this.commListener = commListener;
            this.outputEndpoint = outputEndpoint;
            this.bytes = bytes;

            connection = mUsbManager.openDevice(selectedUsbDevice);
            connection.claimInterface(selectedUsbInterface, true);
        }

        protected Integer doInBackground(Void... unused) {
            int bytesWritten = 0;
            while (bytesWritten < bytes.length) {
                bytesWritten += connection.bulkTransfer(outputEndpoint, bytes, bytesWritten, bytes.length - bytesWritten, 0);
            }
            return bytesWritten;
        }

        protected void onPostExecute(Integer bytesTransferred) {
            connection.close();
            commListener.onComplete(bytesTransferred);
        }
    }
}

下面是我的 Activity 文件中的代码。

UsbCommunicator usbComm = new UsbCommunicator(context);

ArrayList<UsbDevice> connectedDevices = usbComm.getConnectedDevices();

if(connectedDevices.size() == 0) {
    Toast.makeText(context, "No USB Printer Detected", Toast.LENGTH_SHORT).show();
    return;
}

UsbDevice device = connectedDevices.get(0);
usbComm.setDevice(device);
Bytes[] bytes = createSampleReceipt(imgPath); << This method will convert Image to Bytes array

usbComm.sendData(bytes, new CommunicationListener(){

    @Override
    public void onComplete(int bytesTransferred) {
        Toast.makeText(context, "Printer Success", Toast.LENGTH_SHORT).show();
    }
});

在这种情况下,打印只能工作一次,然后要打印另一张收据,我必须重新启动热敏打印机。在实际场景中,它应该根据请求发送所有打印,并且不需要重新启动打印机。

标签: androidarraysprintingusbthermal-printer

解决方案


它是固定的。

我已经从 doInBackground 中删除了 while 循环,它开始正常工作。

我意识到这可能是 While 循环的问题,因为它可能丢失了一些字节,或者写入变量的字节可能有问题。所以我删除了while循环并直接添加了该代码以将字节发送到usb。它开始工作正常。

所以。

while (bytesWritten < bytes.length) {
     bytesWritten += connection.bulkTransfer(outputEndpoint, bytes, bytesWritten, bytes.length - bytesWritten, 0);
}

替换为

bytesWritten = connection.bulkTransfer(outputEndpoint, bytes, bytes.length, 2000);

推荐阅读