使用 UsbDeviceConnection android 重启后热敏打印机仅打印一次

Thermal printer printing only once after restart using UsbDeviceConnection android

在我的 android 应用程序中,我集成了一项功能,可以使用热敏打印机直接从应用程序打印收据。我正在使用 'UsbDeviceConnection' class 打印我的收据。

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

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

我正在使用下面的 class 打印收据。

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();
    }
});

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

已修复。

我已经从 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);