DantSu / ESCPOS-ThermalPrinter-Android

Useful library to help Android developpers to print with (Bluetooth, TCP, USB) ESC/POS thermal printer.
MIT License
1.18k stars 359 forks source link

Print failed when using USB connection #180

Closed MMohamad70 closed 2 years ago

MMohamad70 commented 3 years ago

I am creating an image and print it via this library, when I am using the Bluetooth connection everything is okay and print without any problem, but when I change the connection type to USB, the print failed as the attached image shows (it doesn't even cut the paper). The code using to create image and print are the same and just the connection is different, I am wondering what is the problem and should I set anything special for the USB connection?

                    val connection = when (printer.type) {
                        PrinterType.Bluetooth -> {
                            val bluetoothDevice = bluetoothAdapter?.getRemoteDevice(printer.address)
                            BluetoothConnection(bluetoothDevice)
                        }
                        PrinterType.Wifi -> {
                            TcpConnection(printer.address, printer.port)
                        }
                        PrinterType.USB -> {
                            UsbConnections(context).list?.find { connection ->
                                printer.address == connection.device.deviceName &&
                                        printer.vendorId == connection.device.vendorId &&
                                        printer.productId == connection.device.productId
                            }
                        }
                    } ?: throw Exception("Cannot connect to the printer (${printer.name})")
                    var escPosPrinter: EscPosPrinter? = null
                    try {
                        escPosPrinter = EscPosPrinter(connection, 201, 72f, 48)
                        val textToPrint = StringBuilder()
                        var y = 0
                        while (y < height) {
                            val bitmap = Bitmap.createBitmap(
                                result,
                                0,
                                y,
                                width,
                                if (y + 256 >= height) height - y else 256
                            )
                            textToPrint.append("[C]<img>")
                                .append(
                                    PrinterTextParserImg.bitmapToHexadecimalString(
                                        escPosPrinter,
                                        bitmap
                                    )
                                )
                                .append("</img>\n")
                            y += 256
                        }
                        textToPrint.append("[L]\n")
                        textToPrint.append("[C]<qrcode size='20'>https://test.app/menu.html?branch_id=")
                            .append(branch.id.toString()).append("&table_id=0</qrcode>\n")
                        textToPrint.append("[L]\n")
                        textToPrint.append("[C]All Rights Reserved\n")
                        escPosPrinter.printFormattedText(textToPrint.toString())
                        escPosPrinter.printFormattedTextAndCut("[L]\n")
                        escPosPrinter.openCashBox()
                    } catch (e: EscPosConnectionException) {
                        showMessage("Cannot connect to the printer (${printer.name})")
                    } catch (ex: Exception) {
                        showMessage(ex.message.toString())
                    } finally {
                        escPosPrinter?.disconnectPrinter()
                    }

photo_2021-09-08 20 51 04

DantSu commented 3 years ago

Strange thing, your printer doesn't back to a new line when it print images, more strange only in USB mode !

I can't reproduce this issue my printer print correctly all images.

MMohamad70 commented 3 years ago

I bought a new printer to check and it's the same (it is okay over Bluetooth and failed over USB). I think the problem is related to my code not to the printer. I don't understand what do you mean by "your printer doesn't back to a new line when it print images", it prints some part of the image (the title, address, and tel), then it fails!

2021-09-10 19 06 27

DantSu commented 3 years ago

May be if you put a Time.sleep() between image that will work. Your android device send to the printer too many data at the same time and the printer is lost.

MMohamad70 commented 3 years ago

I tried it but nothing changed! It actually changed somehow, and the part of the image which was correct is now corrupted too.

2021-09-11 13 40 32

DantSu commented 3 years ago

Try to put printFormattedText("[L]<img>...</img>", 0) and a Time.sleep(100) inside the while.

MMohamad70 commented 3 years ago

I've tested this scenario, I think it is the same. One thing that I noticed, as you can see in the attached images, is that it is not correctly feeding paper.

2021-09-11 20 21 47 2021-09-11 20 26 32

When I ignore the image part, it prints correctly the QR and bottom text.

2021-09-11 20 26 46

iAmAndroidDeveloper commented 3 years ago

@MMohamad70 I facing same issue and resolved by using following code just try and let me know

val img = try {
                   val encodeByte: ByteArray = Base64.decode(result, Base64.DEFAULT)
                   val bitmap = BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.size)
                    ""[C]"<img>${
                        PrinterTextParserImg.bitmapToHexadecimalString(
                            printer,
                            bitmap
                        )
                    }</img>\n\n"
                } catch (e: Exception) {
                    ""
                }
MMohamad70 commented 3 years ago

@iAmAndroidDeveloper Thanks for your solution, but I cannot find out what is the result in this code! I have a bitmap not a byte array to pass to decode. I've tried to change my bitmap to a byte array and then using your solution but get a bad base64 error!

here is the method I am using for converting bitmap to a byte array:

fun Bitmap.toByteArray(): ByteArray {
        val size: Int = rowBytes * height
        val byteBuffer: ByteBuffer = ByteBuffer.allocate(size)
        this.copyPixelsToBuffer(byteBuffer)
        return byteBuffer.array()
}
iAmAndroidDeveloper commented 3 years ago

Can you pass image that you want to print

MMohamad70 commented 3 years ago

@iAmAndroidDeveloper It doesn't accept bitmap as an input argument!

iAmAndroidDeveloper commented 3 years ago

Ok NP @MMohamad70 let you know tomorrow morning

iAmAndroidDeveloper commented 2 years ago

@MMohamad70 let me know one thing that before going to print which format image you have? is this Drawable or base64 that you going to convert in Bitmap?

MMohamad70 commented 2 years ago

@iAmAndroidDeveloper I've created a bitmap and draw my receipt over it using Canvas.

This is a sample code of my image creation function:

val image = Bitmap.createBitmap(720, 8192, Bitmap.Config.ARGB_8888)
val canvas = Canvas(image)

canvas.drawText(title, 0f, position, Layout.Alignment.ALIGN_CENTER, width, paint)
canvas.drawText(..)
canvas.drawText(..)
canvas.drawText(..)
.
.
.

val bitmap = Bitmap.createBitmap(image, 0, 0, 720, position.toInt())
image.recycle()