How can I ensure my Epson TM-m30 finishes printing before disconnecting in Android using ePOS SDK?

135 Views Asked by At

I am coding a simple Android App using Kotlin and Epson's ePOS SDK for Android to learn more about Android App development and Bluetooth Printing. However, I hit a dead-end, I am struggling to find a way to wait for the printer to finish it's print job before disconnecting, I want to do this because currently if I try connecting and printing, and then try disconnecting afterwards, it gives me an error saying it failed to disconnect, after fiddling around with different methods, I found out this is because the app is attempting to disconnect from the printer too early (while a print job is happening), despite adding those await functions to make sure it finishes each function before disconnecting.

I want to be able to wait for the printer to finish it's print job entirely before executing the disconnect command to prevent this error from happening.

Logcat: Successfully connects and prints for the first time, fails to disconnects, and cannot connect, print, disconnect unless the app restarts.

2023-06-04 21:33:40.954  7338-7409  PrintJob                com.dishdasher.orderprintbluetooth   D  Successfully Printed
2023-06-04 21:33:41.018  7338-7409  PrintJob                com.dishdasher.orderprintbluetooth   E  Failed to disconnect from printer: null, status: 6
2023-06-04 21:33:42.895  7338-7409  PrintJob                com.dishdasher.orderprintbluetooth   E  Failed to connect: null
2023-06-04 21:33:42.898  7338-7409  PrintJob                com.dishdasher.orderprintbluetooth   E  Failed to print: null
2023-06-04 21:33:42.899  7338-7419  PrintJob                com.dishdasher.orderprintbluetooth   E  Failed to disconnect from printer: null, status: 5

Printing.kt:

import android.util.Log
import com.epson.epos2.Epos2Exception
import com.epson.epos2.printer.Printer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.withContext
import kotlin.coroutines.CoroutineContext

// The Printing class manages the printing tasks.
// It uses Coroutines to run tasks asynchronously.
class Printing(private val context: Context) : CoroutineScope {

    // The printer object.
    private lateinit var yourPrinter: Printer

    // Flag to track if printer is currently in use.
    private var isPrinting: Boolean = false

    // Job instance for coroutine.
    private val job = Job()

    // Queue for storing print jobs.
    private val printQueue: MutableList<String> = mutableListOf()

    // Defines coroutine context to be main thread.
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job

    // Adds a print job to the queue.
    // If printer isn't currently printing, starts next print job.
    suspend fun print(PrintString: String) {
        printQueue.add(PrintString)
        if (!isPrinting) {
            printNextJob()
        } else {
            Log.d("PrintJob", "Print job added to queue")
        }
    }

    // Prints next job in the queue if available.
    private suspend fun printNextJob() {
        if (printQueue.isNotEmpty()) {
            val nextJob = printQueue.removeAt(0)
            isPrinting = true
            try {
                val connectTask = async { connectPrinter() }
                connectTask.await()
                val printTask = async { printTask(nextJob) }
                printTask.await()
                val disconnectTask = async { disconnectPrinter() }
                disconnectTask.await()
            } finally {
                isPrinting = false
                if (printQueue.isNotEmpty()) {
                    printNextJob()
                }
            }
        }
    }

    // Connects to printer. If connection fails, logs an error message.
    private suspend fun connectPrinter() {
        withContext(Dispatchers.IO) {
            try {
                yourPrinter = Printer(Printer.TM_M30, Printer.LANG_EN, context)
                yourPrinter.connect("BT:00:01:90:7B:E0:EE", 10000)
                Log.d("PrintJob", "Successfully Connected")
            } catch (e: Epos2Exception) {
                Log.e("PrintJob", "Failed to connect: ${e.message}")
            }
        }
    }

    // Prints the receipt. If printing fails, logs an error message.
    private suspend fun printTask(receiptString: String) {
        withContext(Dispatchers.IO) {
            try {
                yourPrinter.beginTransaction()
                yourPrinter.addText(receiptString)
                yourPrinter.addFeedLine(1)
                yourPrinter.addCut(Printer.CUT_FEED)
                yourPrinter.sendData(Printer.PARAM_DEFAULT)
                yourPrinter.endTransaction()
                Log.d("PrintJob", "Successfully Printed")
            } catch (e: Epos2Exception) {
                Log.e("PrintJob", "Failed to print: ${e.message}")
            }
        }
    }

    // Disconnects from the printer. If disconnection fails, logs an error message.
    private suspend fun disconnectPrinter() {
        withContext(Dispatchers.IO) {
            try {
                if (::yourPrinter.isInitialized) {
                    yourPrinter.disconnect()
                } else {
                    
                }
            } catch (ex: Epos2Exception) {
                Log.e(
                    "PrintJob",
                    "Failed to disconnect from printer: ${ex.message}, status: ${ex.errorStatus}"
                )
            }
        }
    }
}```
0

There are 0 best solutions below