dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) }
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
import android.Manifest.permission import android.content.pm.PackageManager import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat class PermissionRequestExampleActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) checkPermissions() } override fun onRequestPermissionsResult( requestCode: Intv permissions: Array<out String>, grantResults: IntArray, ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) } private fun checkPermissions() { if (!isPermissionsGranted()) { ActivityCompat.requestPermissions( this, PERMISSIONS, PERMISSIONS_REQUEST, ) return } } private fun isPermissionsGranted(): Boolean { var permissionsGranted = true for (permission in PERMISSIONS) { if (ContextCompat.checkSelfPermission( this, permission ) != PackageManager.PERMISSION_GRANTED ) { permissionsGranted = false break } } return permissionsGranted } companion object { private const val PERMISSIONS_REQUEST = 0 private val PERMISSIONS = arrayOf( permission.ACCESS_FINE_LOCATION, ) } }
import com.zebra.sdk.printer.discovery.DiscoveredPrinter interface ScanPrintersService { fun discoveredPrinters(): List<DiscoveredPrinter> fun startScan(printerScanCallback: PrinterScanCallback) fun clearDiscoveredPrinterList()
import android.content.Context import com.zebra.sdk.comm.ConnectionException import com.zebra.sdk.printer.discovery.BluetoothDiscoverer import com.zebra.sdk.printer.discovery.DiscoveredPrinter import com.zebra.sdk.printer.discovery.DiscoveryHandler import dagger.hilt.android.qualifiers.ApplicationContext import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @Singleton class ScanPrintersServiceImpl @Inject constructor( @ApplicationContext private val context: Context, ) : ScanPrintersService { private val printers = ArrayList<DiscoveredPrinter>() override fun discoveredPrinters() = printers override fun startScan(printerScanCallback: PrinterScanCallback) { try { printers.clear() printerScanCallback.onScanStarted() BluetoothDiscoverer.findPrinters(context, object : DiscoveryHandler { override fun foundPrinter(discoveredPrinter: DiscoveredPrinter) { printers.add(discoveredPrinter) printerScanCallback.onPrinterFound(discoveredPrinter) Timber.d("Bluetooth printer found: ${discoveredPrinter.address}") } override fun discoveryFinished() { printerScanCallback.onScanFinished(printers) Timber.d("Bluetooth discovery finished") } override fun discoveryError(e: String) { Timber.d("Bluetooth discovery error: $e") printerScanCallback.onScanError(e) } }) } catch (e: ConnectionException) { Timber.e(e) printerScanCallback.onScanError(e.localizedMessage ?: "Bluetooth discovery error") } } override fun clearDiscoveredPrinterList() { printers.clear() } }
interface PrinterScanCallback { fun onScanStarted() fun onPrinterFound(discoveredPrinter: DiscoveredPrinter) fun onScanFinished(discoveredPrinters: List<DiscoveredPrinter>) fun onScanError(error: String) }
import com.zebra.sdk.comm.BluetoothConnection import kotlinx.coroutines.flow.StateFlow interface PrinterConnectionService { fun currentConnection(): StateFlow<BluetoothConnection?> suspend fun connectToPrinter(macAddress: String): Boolean suspend fun closeConnection(): Boolean }
import com.zebra.sdk.comm.BluetoothConnection import com.zebra.sdk.comm.Connection import com.zebra.sdk.comm.ConnectionException import com.zebra.sdk.printer.SGD import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @Singleton class PrinterConnectionServiceImpl @Inject constructor() : PrinterConnectionService { private var currentConnection: MutableStateFlow<BluetoothConnection?> = MutableStateFlow(null) override fun currentConnection() = currentConnection override suspend fun connectToPrinter(macAddress: String): Boolean { return withContext(Dispatchers.Default) { val connection = BluetoothConnection(macAddress) try { Timber.d("Trying to connect to the printer") connection.open() Timber.d("Successfully connected to the printer") if (zebraPrinterSupportsPDF(connection)) { Timber.d("PDF print enabled") } else { Timber.d("PDF print not enabled") setPdfPrintingEnabled(connection) } currentConnection.value = connection true } catch (e: ConnectionException) { val error = "Error occurred while trying to connect to the printer" Timber.d(error) currentConnection.value = null false } } } override suspend fun closeConnection(): Boolean { return withContext(Dispatchers.Default) { Timber.d("Disconnect from the printer") currentConnection.value?.close() currentConnection.value = null true } } @Throws(ConnectionException::class) private fun zebraPrinterSupportsPDF(connection: Connection): Boolean { val printerInfo = SGD.GET("apl.enable", connection) return printerInfo == "pdf" } @Throws(ConnectionException::class) private fun setPdfPrintingEnabled(connection: Connection): Boolean { SGD.SET("apl.enable", "pdf", connection) val enabled = zebraPrinterSupportsPDF(connection) Timber.d("Trying to enable PDF print, success: $enabled") return enabled } }
import android.net.Uri import com.zebra.sdk.comm.BluetoothConnection interface PrintDocumentService { suspend fun printDocument(connection: BluetoothConnection, document: Uri): Boolean }
import android.net.Uri import com.zebra.sdk.comm.BluetoothConnection import com.zebra.sdk.printer.ZebraPrinterFactory import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.withContext import java.lang.Exception import javax.inject.Inject class PrintDocumentServiceImpl @Inject constructor() : PrintDocumentService { override suspend fun printDocument(connection: BluetoothConnection, document: Uri): Boolean { return withContext(Dispatchers.IO + SupervisorJob()) { try { if (!connection.isConnected) { return@withContext false } // Get Instance of Printer val printer = ZebraPrinterFactory.getLinkOsPrinter(connection) // Verify Printer Status is Ready val printerStatus = printer.currentStatus if (printerStatus.isReadyToPrint) { printer.sendFileContents(document.path) true } else { false } } catch (e: Exception) { false } } } }