zebra_printer 0.2.0
zebra_printer: ^0.2.0 copied to clipboard
Flutter management package for Zebra printers. Uses Zebra Link-OS SDK for Bluetooth & Network discovery, ZPL printing, and printer management.
Zebra Printer #
A Flutter package for Zebra printers. Uses Zebra Link-OS SDK for Bluetooth and Network connectivity, ZPL printing, and printer management. Supports Android platform.
Features #
Zebra-Specific Features (via PrinterManager - Recommended) #
- π Discover Zebra Printers - Find printers via Bluetooth & Network using Zebra SDK
- π Persistent Connection - Connect once, print multiple times
- π Print ZPL Labels - Send ZPL commands directly
- π Check Printer Status - Get real-time printer status
- βΉοΈ Get Printer Info - Retrieve printer details and firmware info
Generic Bluetooth Features (via BluetoothManager - Optional) #
- π‘ Scan and discover all Bluetooth devices
- π Pair and unpair with Bluetooth devices
- π― Generic Bluetooth connectivity for non-Zebra devices
Installation #
Add the package to your pubspec.yaml file:
dependencies:
zebra_printer: latest_version
Android Setup #
Add the required permissions to your android/app/src/main/AndroidManifest.xml file:
<!-- Bluetooth Permissions -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<!-- Location Permissions (Required for Bluetooth discovery on Android 12+) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Network Permissions (For network printer discovery) -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
Important: For Android 12+, you need to request runtime permissions for Bluetooth and Location.
Usage #
π― Recommended: Using PrinterManager (Zebra-Specific) #
The PrinterManager uses Zebra Link-OS SDK and is the recommended approach for working with Zebra printers.
Basic Setup
import 'package:zebra_printer/zebra_printer.dart';
final printerManager = PrinterManager();
1. Discover Zebra Printers
// Setup callbacks for real-time discovery updates
printerManager.onPrinterFound = (printer) {
print('Found: ${printer.friendlyName} (${printer.address})');
};
printerManager.onDiscoveryFinished = (printers) {
print('Discovery finished. Found ${printers.length} printers');
};
// Start discovery
try {
// Options: 'bluetooth', 'network', or 'both'
final printers = await printerManager.startDiscovery(type: 'both');
for (var printer in printers) {
print('${printer.friendlyName} - ${printer.type} - ${printer.address}');
}
} catch (e) {
print('Discovery error: $e');
}
// Stop discovery when done
await printerManager.stopDiscovery();
2. Connect to Printer
// Connect to a discovered printer
try {
final connectionInfo = await printerManager.connect('AC:3F:A4:XX:XX:XX');
print('Connected: ${connectionInfo['friendlyName']}');
} catch (e) {
print('Connection error: $e');
}
// Check connection status
bool connected = await printerManager.isConnected();
// Or check specific printer
bool connected = await printerManager.isConnected(address: 'AC:3F:A4:XX:XX:XX');
3. Print Labels
// Print custom ZPL
String zpl = """
^XA
^FO50,50
^A0N,50,50
^FDHello from Flutter!^FS
^FO50,120
^A0N,30,30
^FDDate: ${DateTime.now()}^FS
^XZ
""";
try {
String result = await printerManager.sendZplToPrinter(
'AC:3F:A4:XX:XX:XX',
zpl
);
print('Print successful: $result');
} catch (e) {
print('Print error: $e');
}
// Or use the quick test print
await printerManager.printTestLabel('AC:3F:A4:XX:XX:XX');
4. Check Printer Status
try {
PrinterStatus status = await printerManager.checkPrinterStatus('AC:3F:A4:XX:XX:XX');
print('Connected: ${status.isConnected}');
print('Paper: ${status.isPaperOut ? "Out" : "OK"}');
print('Head: ${status.isHeadOpen ? "Open" : "Closed"}');
print('Paused: ${status.isPaused}');
} catch (e) {
print('Status check error: $e');
}
5. Get Printer Information
try {
String info = await printerManager.getPrinterInfo('AC:3F:A4:XX:XX:XX');
print('Printer Info: $info');
} catch (e) {
print('Info error: $e');
}
6. Disconnect
// Disconnect from specific printer
await printerManager.disconnect(address: 'AC:3F:A4:XX:XX:XX');
// Or disconnect from currently connected printer
await printerManager.disconnect();
Complete Example with Connection State Monitoring
class PrinterScreen extends StatefulWidget {
@override
_PrinterScreenState createState() => _PrinterScreenState();
}
class _PrinterScreenState extends State<PrinterScreen> {
final printerManager = PrinterManager();
List<DiscoveredPrinter> printers = [];
DiscoveredPrinter? selectedPrinter;
bool isConnected = false;
@override
void initState() {
super.initState();
// Listen for connection state changes
printerManager.onConnectionStateChanged = (info) {
setState(() {
isConnected = info['isConnected'] ?? false;
});
print('Connection state: $isConnected');
};
// Listen for discovered printers
printerManager.onPrinterFound = (printer) {
setState(() {
if (!printers.any((p) => p.address == printer.address)) {
printers.add(printer);
}
});
};
}
Future<void> discover() async {
setState(() => printers.clear());
await printerManager.startDiscovery(type: 'both');
}
Future<void> connect(DiscoveredPrinter printer) async {
try {
await printerManager.connect(printer.address);
setState(() => selectedPrinter = printer);
} catch (e) {
print('Connection error: $e');
}
}
Future<void> printTest() async {
if (selectedPrinter != null) {
await printerManager.printTestLabel(selectedPrinter!.address);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Zebra Printer')),
body: Column(
children: [
ElevatedButton(
onPressed: discover,
child: Text('Discover Printers'),
),
if (isConnected) ...[
ElevatedButton(
onPressed: printTest,
child: Text('Print Test'),
),
ElevatedButton(
onPressed: () => printerManager.disconnect(),
child: Text('Disconnect'),
),
],
Expanded(
child: ListView.builder(
itemCount: printers.length,
itemBuilder: (context, index) {
final printer = printers[index];
return ListTile(
title: Text(printer.friendlyName),
subtitle: Text('${printer.type} - ${printer.address}'),
onTap: () => connect(printer),
);
},
),
),
],
),
);
}
}
π§ Alternative: Using BluetoothManager (Generic Bluetooth) #
The BluetoothManager provides generic Android Bluetooth functionality for non-Zebra devices or when you need low-level Bluetooth control.
import 'package:zebra_printer/zebra_printer.dart';
final bluetoothManager = BluetoothManager();
// Check Bluetooth status
bool isEnabled = await bluetoothManager.isBluetoothEnabled();
// Get paired devices
List<BluetoothDevice> bondedDevices = await bluetoothManager.getBondedDevices();
// Listen for device discovery
bluetoothManager.onDeviceFound.listen((device) {
print('Found: ${device.name} (${device.address})');
});
// Start scanning
await bluetoothManager.startDiscovery();
// Stop scanning
await bluetoothManager.stopDiscovery();
// Connect to device
await bluetoothManager.connect('00:11:22:33:44:55');
// Disconnect
await bluetoothManager.disconnect();
// Clean up
bluetoothManager.dispose();
ZPL Examples #
Simple Label #
String createSimpleLabel(String text) {
return """
^XA
^FO50,50
^A0N,50,50
^FD$text^FS
^XZ
""";
}
Barcode Label #
String createBarcodeLabel(String barcode, String description) {
return """
^XA
^FO50,50^A0N,30,30^FD$description^FS
^FO50,100^BY3^BCN,100,Y,N,N^FD$barcode^FS
^XZ
""";
}
QR Code Label #
String createQRCodeLabel(String data) {
return """
^XA
^FO50,50^A0N,30,30^FDQR Code:^FS
^FO50,100^BQN,2,10^FDMA,$data^FS
^XZ
""";
}
Multi-Line Receipt #
String createReceipt(String storeName, List<String> items, String total) {
String zpl = "^XA\n";
zpl += "^FO50,50^A0N,40,40^FD$storeName^FS\n";
int y = 100;
for (var item in items) {
zpl += "^FO50,$y^A0N,25,25^FD$item^FS\n";
y += 35;
}
zpl += "^FO50,$y^GB350,2,2^FS\n";
y += 20;
zpl += "^FO50,$y^A0N,30,30^FDTotal: $total^FS\n";
zpl += "^XZ";
return zpl;
}
ποΈ Architecture & SDK Usage #
This package uses two different approaches for Android implementation:
Android Native Implementation Comparison #
| Feature | PrinterManager | BluetoothManager | Native SDK Used |
|---|---|---|---|
| Discovery | β Zebra-specific discovery | β All BT devices | PrinterManager: Zebra SDK (BluetoothDiscoverer, NetworkDiscoverer)BluetoothManager: Android Bluetooth API |
| Connection | β Persistent connection | β Generic BT connection | PrinterManager: Zebra SDK (BluetoothConnection)BluetoothManager: Android Bluetooth API ( BluetoothSocket) |
| Print (ZPL) | β Optimized for Zebra | β Raw data send | Both: Zebra SDK (Connection.write()) |
| Printer Status | β Full status info | β Not available | PrinterManager: Zebra SDK (SGD.GET()) |
| Printer Info | β Model, SN, firmware | β Not available | PrinterManager: Zebra SDK (SGD.GET(), ZebraPrinterFactory) |
| Get Paired Devices | β All paired BT devices | β All paired BT devices | Both: Android Bluetooth API (BluetoothAdapter.getBondedDevices()) |
| Unpair Device | β Remove pairing | β Remove pairing | Both: Android Bluetooth API (Reflection: device.removeBond()) |
| Connection Caching | β 10s cache for fast prints | β No caching | PrinterManager: Custom implementation with Zebra SDK |
| Language Detection | β ZPL/CPCL detection | β Not available | PrinterManager: Zebra SDK (printer.getPrinterControlLanguage()) |
Why Two Managers? #
-
PrinterManager (Recommended for Zebra):
- Uses Zebra Link-OS SDK for all printer-specific operations
- Falls back to Android Bluetooth API only for operations not supported by Zebra SDK (pairing/unpairing)
- Optimized for Zebra printers with connection pooling and status monitoring
- Provides rich printer information and status
-
BluetoothManager (Generic Bluetooth):
- Uses Android Bluetooth API for generic Bluetooth operations
- Suitable for non-Zebra devices or when you need raw Bluetooth control
- Can discover and connect to any Bluetooth device
- Simpler implementation for basic printing needs
π Detailed Method Comparison #
PrinterManager.java Implementation
| Method | Zebra SDK Used | Android API Used | Notes |
|---|---|---|---|
startDiscovery() |
β
BluetoothDiscoverer.findPrinters()β NetworkDiscoverer.findPrinters() |
β None | Uses Zebra SDK's discovery handlers |
connect() |
β
BluetoothConnectionβ ZebraPrinterFactory.getInstance() |
β None | Opens and validates Zebra printer connection |
disconnect() |
β
Connection.close() |
β None | Closes Zebra SDK connection |
sendZplToPrinter() |
β
BluetoothConnectionβ Connection.write()β SGD.GET() (readiness check) |
β None | Optimized with connection caching & retry logic |
getPrinterInfo() |
β
SGD.GET("device.product_name")β SGD.GET("device.unique_id")β printer.getPrinterControlLanguage() |
β None | Retrieves detailed printer information |
checkPrinterStatus() |
β
SGD.GET("head.paper_out")β SGD.GET("device.pause")β SGD.GET("head.open") |
β None | Real-time status monitoring |
getPairedPrinters() |
β None | β
BluetoothAdapter.getBondedDevices() |
Zebra SDK doesn't provide paired device list |
unpairPrinter() |
β None | β
device.removeBond() (via Reflection) |
Zebra SDK doesn't support unpairing |
isConnected() |
β
Checks activeConnection state |
β None | Internal state management |
BluetoothManager.java Implementation
| Method | Zebra SDK Used | Android API Used | Notes |
|---|---|---|---|
startDiscovery() |
β None | β
BluetoothAdapter.startDiscovery() |
Discovers all Bluetooth devices |
connect() |
β None | β
BluetoothSocket.connect() |
Generic Bluetooth connection |
disconnect() |
β None | β
BluetoothSocket.close() |
Closes Bluetooth socket |
getBondedDevices() |
β None | β
BluetoothAdapter.getBondedDevices() |
Returns all paired devices |
pairDevice() |
β None | β
device.createBond() (via Reflection) |
Initiates pairing process |
unpairDevice() |
β None | β
device.removeBond() (via Reflection) |
Removes pairing |
π Key Insights #
- PrinterManager is 99% Zebra SDK, except for pairing operations which require Android API
- BluetoothManager is 100% Android Bluetooth API
- Both can print to Zebra printers, but PrinterManager provides much richer functionality
- getPairedPrinters() and unpairPrinter() use Android API in both managers because Zebra SDK doesn't expose these operations
API Reference #
PrinterManager Methods #
| Method | Parameters | Return Type | Description |
|---|---|---|---|
startDiscovery |
type: String (optional) |
Future<List<DiscoveredPrinter>> |
Discovers Zebra printers. Type: 'bluetooth', 'network', or 'both' (default) |
stopDiscovery |
- | Future<bool> |
Stops the discovery process |
getPairedPrinters |
- | Future<List<BluetoothDevice>> |
Returns all paired Bluetooth devices |
unpairPrinter |
address: String |
Future<bool> |
Removes pairing with device |
connect |
address: String |
Future<bool> |
Connects to a Zebra printer and keeps connection open |
disconnect |
address: String? (optional) |
Future<bool> |
Disconnects from printer. If address is null, disconnects from current printer |
isConnected |
address: String? (optional) |
Future<bool> |
Checks connection status. If address is null, checks general status |
sendZplToPrinter |
macAddress: String, zplData: String |
Future<String> |
Sends ZPL code to printer (uses active connection or creates temporary one) |
printTestLabel |
macAddress: String |
Future<String> |
Prints a test label |
checkPrinterStatus |
macAddress: String |
Future<PrinterStatus> |
Gets printer status (paper, head, pause, temperature) |
getPrinterInfo |
macAddress: String |
Future<String> |
Gets printer information (model, serial, firmware, language) |
PrinterManager Callbacks #
| Callback | Parameters | Description |
|---|---|---|
onPrinterFound |
DiscoveredPrinter |
Called when a printer is found during discovery |
onDiscoveryFinished |
List<DiscoveredPrinter> |
Called when discovery is complete |
onConnectionStateChanged |
Map<String, dynamic> |
Called when connection state changes |
Models #
DiscoveredPrinter
class DiscoveredPrinter {
final String type; // "bluetooth" or "network"
final String address; // MAC address or IP address
final String friendlyName; // Printer name
}
PrinterStatus
class PrinterStatus {
final bool isConnected;
final bool isPaperOut;
final bool isHeadOpen;
final bool isPaused;
final String? errorMessage;
}
Zebra Link-OS SDK #
This package uses the Zebra Link-OS SDK for Android platform. For more detailed information, refer to Zebra's official documentation.
Supported Features #
- Bluetooth Classic and Network connectivity
- Zebra printer discovery using SDK
- ZPL command execution
- Real-time printer status monitoring
- Persistent connections for multiple print jobs
- Printer information retrieval
Troubleshooting #
Printer Not Found #
- Ensure Bluetooth is enabled on your device
- Check Location permission is granted (required for Bluetooth discovery)
- Make sure printer is powered on and in range
- Try power cycling the printer
- Check if printer is already paired with another device
Connection Issues #
- Verify the MAC address is correct
- Unpair and re-pair the device if needed
- Check printer battery level
- Ensure printer supports Bluetooth connectivity
- Try restarting both devices
Print Quality Issues #
- Verify ZPL commands are correct
- Check printer paper and ribbon levels
- Adjust print darkness settings via ZPL
- Clean printer head if needed
Example App #
The package includes a comprehensive example app demonstrating:
- Zebra-specific printer discovery (SDK-based)
- Generic Bluetooth device scanning
- Connection management
- Printing examples
- Status monitoring
Run the example:
cd example
flutter run
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
License #
This project is licensed under the MIT License. See the LICENSE file for details.
Support #
For issues and feature requests, please visit our GitHub Issues page.
Credits #
- Powered by Zebra Link-OS SDK
- Maintained by the Flutter community