Реализация печати документов из мобильного приложения
Печать из мобильного приложения — задача, которую недооценивают до первого краш-репорта из-за нулевого числа принтеров в системе или невозможности напечатать 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) {
// Write PDF bytes to 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 недели в зависимости от типа принтера и сложности шаблонов.







