Реалізація підключення до принтера через Bluetooth з мобільного додатка
Bluetooth-друк виглядає просто: знайти пристрій, підключитися, відправити байти. На практиці — сканування не знаходить принтер, тому що він уже сопряжений з іншим телефоном; з'єднання рветься в середині друку без сповіщення; на Android 12+ дозволи Bluetooth змінилися та старий код не компілюється.
Android: класичний Bluetooth vs BLE
Термопринтери (Zebra ZQ300, Bixolon SPP-R310, iDPRT SP450) працюють через Bluetooth Classic (SPP — Serial Port Profile). Не BLE. Це важливо: API різні.
Класичний Bluetooth на Android — BluetoothAdapter, BluetoothDevice, BluetoothSocket. З Android 12 (targetSdk 31+) потрібні нові дозволи:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
Без BLUETOOTH_SCAN з флагом neverForLocation Google Play вимагає обґрунтування — чому Bluetooth-сканування для визначення місцеположення. Флаг явно говорить, що не для цього.
Підключення через SPP UUID:
val device: BluetoothDevice = bluetoothAdapter.bondedDevices
.firstOrNull { it.name.contains("Zebra") } ?: return
val socket = device.createRfcommSocketToServiceRecord(
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") // SPP UUID
)
withContext(Dispatchers.IO) {
socket.connect()
val outputStream = socket.outputStream
outputStream.write(zplData)
outputStream.flush()
}
createRfcommSocketToServiceRecord може бросити IOException якщо пристрій зайнятий іншим з'єднанням. Zebra-принтери підтримують лише одне активне з'єднання — якщо принтер уже підключен до іншого телефону, з'єднання упаде з помилкою. Потрібно показувати користувачу внятне сообщение, а не стандартний крэш.
Пошук пристроїв. BluetoothAdapter.startDiscovery() — асинхронний, займає до 12 секунд, розряджає батарею. Краще показувати список уже сопряжених пристроїв (bondedDevices) — користувач сопрягує принтер один раз у настройках телефону. Пошук нових — лише за явним запросом.
Zebra Link-OS SDK: коли простого Bluetooth недостатньо
Для Zebra-принтерів є офіційний SDK — ZSDK_ANDROID_API_x.x.aar. Він абстрагує транспорт (Bluetooth / TCP) та додає корисне:
- Перевірка статусу принтера перед друком (
PrinterStatus) - Отримання конфігурації (
SettingsGenerator.getConfigLabel()) - Калібровка носія
- Отримання списку шрифтів та форматів на принтері
val connection = BluetoothConnection(macAddress)
connection.open()
val printer = ZebraPrinterFactory.getInstance(connection)
val status = printer.currentStatus
if (status.isReadyToPrint) {
printer.sendCommand(zplTemplate)
} else {
// status.isPaused, status.isHeadOpen, status.isPaperOut — конкретна причина
showError(getPrinterStatusMessage(status))
}
connection.close()
Без SDK — немає способу дізнатися, що в принтері закінчилася бумага до спроби друку. З SDK — status.isPaperOut дает конкретну причину відмови.
iOS: ExternalAccessory framework
На iOS термопринтери з Bluetooth Classic працюють через ExternalAccessory framework — MFi (Made for iPhone) протокол. Принтер повинен мати MFi-сертифікацію. Zebra, Star Micronics, Bixolon — сертифіковані.
import ExternalAccessory
let session = EASession(accessory: accessory, forProtocol: "com.zebra.rawport")
session?.outputStream?.schedule(in: .main, forMode: .default)
session?.outputStream?.open()
let data = zplString.data(using: .utf8)!
data.withUnsafeBytes { session?.outputStream?.write($0, maxLength: data.count) }
Рядок протоколу (com.zebra.rawport) — специфічний для вендора, прописується в Info.plist під ключем UISupportedExternalAccessoryProtocols. Без цього iOS не дає відкрити сесію.
BLE-принтери на iOS — без MFi-обмежень, через стандартний CoreBluetooth. Star Micronics mPOP, деякі моделі Bixolon — підтримують BLE.
Стабільність з'єднання та переподключення
Bluetooth-з'єднання рветься. Принтер вимкнули та включили. Телефон відійшов за межи радіуса. Реалізація без авто-реконнекта — джерело скарг у підтримку.
Паттерн: при IOException на outputStream.write() — закрити сокет, почекати 1–2 секунди, спробувати переподключитися (максимум 3 спроби). Якщо не удалось — зберегти завдання в локальну чергу, сповістити користувача. WorkManager з BackoffPolicy.LINEAR для повторних спроб при наступному доступному з'єднанні.
Реалізація Bluetooth-друку з підтримкою Zebra/Star/Bixolon: 1–2 тижні. Вартість розраховується індивідуально.







