Реалізація друку документів з мобільного додатка
Друк з мобільного додатка — задача, яку недооцінюють до першого краш-репорту з-за нулевого числа принтерів у системі або неможливості надрукувати PDF на принтері конкуруючого вендора. Правильна реалізація вимагає розуміння трьох незалежних каналів: системний Print Framework, AirPrint/Mopria, та прямий друк через SDK вендора.
Android: Print Framework та його обмеження
Android надає PrintManager + PrintDocumentAdapter — стандартний шлях з системним діалогом вибору принтера. Працює через PrintService плагіни: Google Cloud Print застарів, Mopria Print Service — актуальний стандарт для Wi-Fi принтерів.
Для друку PDF:
val printManager = getSystemService(Context.PRINT_SERVICE) as PrintManager
val jobName = "Document_${System.currentTimeMillis()}"
printManager.print(jobName, object : PrintDocumentAdapter() {
override fun onLayout(oldAttr: PrintAttributes?, newAttr: PrintAttributes,
cancellationSignal: CancellationSignal,
callback: LayoutResultCallback, extras: Bundle?) {
if (cancellationSignal.isCanceled) { callback.onLayoutCancelled(); return }
val info = PrintDocumentInfo.Builder(jobName)
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.setPageCount(pageCount)
.build()
callback.onLayoutFinished(info, oldAttr != newAttr)
}
override fun onWrite(pages: Array<out PageRange>, destination: ParcelFileDescriptor,
cancellationSignal: CancellationSignal, callback: WriteResultCallback) {
// Запис PDF байтів до destination.fileDescriptor
}
}, null)
Головна проблема: PrintDocumentAdapter працює з ParcelFileDescriptor. Передати готовий PDF — потрібно скопіювати байти через FileOutputStream. Бібліотека PdfDocument з Android SDK підходить для простих документів; для складних — iText7 або рендеринг з HTML через WebView.createPrintDocumentAdapter().
WebView.createPrintDocumentAdapter() — недооцінений інструмент. HTML + CSS → WebView → PrintDocumentAdapter. Підтримує @media print, page-break-before, @page { size: A4 }. Для шаблонів накладних, актів, етикеток — простіше, ніж малювати через Canvas.
iOS: AirPrint та UIPrintInteractionController
На iOS друк через UIPrintInteractionController. Підтримує UIPrintInfo для настройки (duplex, orientation) та кілька типів контенту: UIPrintingItem (URL до файлу), UIPrintPageRenderer (користувацький рендеринг).
let printController = UIPrintInteractionController.shared
let printInfo = UIPrintInfo(dictionary: nil)
printInfo.jobName = "Invoice"
printInfo.outputType = .general
printController.printInfo = printInfo
printController.printingItem = pdfURL // URL до локального PDF
printController.present(animated: true)
AirPrint працює без настройки — iOS автоматично виявляє принтери у мережі через Bonjour. Проблема: принтер повинен підтримувати AirPrint. Більшість корпоративних Canon, HP, Epson — підтримують. Старі моделі — ні.
Прямий друк на етикеточні принтери
Для складських та торговельних додатків потрібен друк на Zebra ZPL або TSC TSPL. Системний Print Framework тут не допоможе — потрібен прямий TCP/IP або Bluetooth.
Zebra Link-OS SDK для Android: ZebraPrinter через Connection (TCP або Bluetooth). Відправка ZPL-шаблону:
val connection = TcpConnection("192.168.1.100", 9100)
connection.open()
val printer = ZebraPrinterFactory.getInstance(connection)
printer.sendCommand("^XA^FO50,50^A0N,30,30^FDHello World^FS^XZ")
connection.close()
ZPL-шаблони зручно зберігати на сервері та заповнювати через String.format() або Mustache. Для динамічних штрихкодів — ^BC (Code128) або ^BQ (QR) команди ZPL.
Вибір підходу за сценарієм
| Сценарій | Підхід |
|---|---|
| Документи A4 (накладні, акти) | WebView → PrintDocumentAdapter / AirPrint |
| PDF з сервера | PrintDocumentAdapter з ParcelFileDescriptor / UIPrintInteractionController |
| Етикетки Zebra ZPL | Zebra Link-OS SDK, прямий TCP |
| Чеки на термопринтерах | ESCPOS через Bluetooth або TCP |
| Касові чеки (54-ФЗ) | ATOL SDK / Евотор SDK |
Реалізація друку документів: 1–3 тижні в залежності від типу принтера та складності шаблонів.







