flutter_print_label 0.1.0
flutter_print_label: ^0.1.0 copied to clipboard
Bluetooth label printer plugin (TSPL) for Android and iOS. Supports budget Chinese label printers (VOZY, Xprinter, Gprinter, ...) that advertise BLE without a name.
example/lib/main.dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_print_label/flutter_print_label.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'flutter_print_label example',
home: PrinterPage(),
);
}
}
class PrinterPage extends StatefulWidget {
const PrinterPage({super.key});
@override
State<PrinterPage> createState() => _PrinterPageState();
}
class _PrinterPageState extends State<PrinterPage> {
final _printer = FlutterPrintLabel.instance;
final List<PrinterDevice> _devices = [];
PrinterDevice? _selected;
PrinterConnectionStatus _status = PrinterConnectionStatus.disconnected;
bool _scanning = false;
StreamSubscription<PrinterDevice>? _scanSub;
StreamSubscription<PrinterConnectionStatus>? _statusSub;
@override
void initState() {
super.initState();
_statusSub = _printer.connectionStatus.listen((status) {
setState(() => _status = status);
});
_scan();
}
@override
void dispose() {
_scanSub?.cancel();
_statusSub?.cancel();
super.dispose();
}
void _scan() {
_scanSub?.cancel();
setState(() {
_devices.clear();
_scanning = true;
});
// iOS always scans BLE. On Android a BLE scan also finds printers that
// are not paired in system settings.
_scanSub = _printer.scan(isBle: Platform.isIOS).listen(
(device) {
setState(() {
final index = _devices.indexWhere((d) => d.address == device.address);
if (index >= 0) {
_devices[index] = device; // name update for the same device
} else {
_devices.add(device);
}
});
},
onDone: () => setState(() => _scanning = false),
);
}
Future<void> _connect(PrinterDevice device) async {
setState(() => _selected = device);
await _printer.connect(device);
// Wait for PrinterConnectionStatus.connected via the status stream.
}
Future<void> _printTestLabel() async {
// A 100 x 150 mm TSPL test label with text and a barcode.
await _printer.printTspl(
'SIZE 100 mm,150 mm\r\n'
'GAP 3 mm,0 mm\r\n'
'DIRECTION 1\r\n'
'CLS\r\n'
'TEXT 50,80,"3",0,2,2,"FLUTTER PRINT LABEL"\r\n'
'TEXT 50,180,"3",0,1,1,"Printer: ${_selected?.name ?? "-"}"\r\n'
'TEXT 50,240,"3",0,1,1,"Test print OK"\r\n'
'BARCODE 50,320,"128",100,1,0,2,2,"TEST1234"\r\n'
'PRINT 1,1\r\n',
);
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Test label sent')),
);
}
@override
Widget build(BuildContext context) {
final connected = _status == PrinterConnectionStatus.connected;
return Scaffold(
appBar: AppBar(
title: const Text('flutter_print_label'),
actions: [
IconButton(
icon: const Icon(Icons.refresh),
tooltip: 'Rescan',
onPressed: _scan,
),
],
),
body: Column(
children: [
ListTile(
leading: Icon(
connected ? Icons.bluetooth_connected : Icons.bluetooth_disabled,
color: connected ? Colors.green : Colors.grey,
),
title: Text('Status: ${_status.name}'),
subtitle: _selected == null ? null : Text(_selected!.name),
trailing: ElevatedButton(
onPressed: connected ? _printTestLabel : null,
child: const Text('Print test label'),
),
),
const Divider(height: 1),
Expanded(
child: _devices.isEmpty
? Center(
child: Text(
_scanning
? 'Scanning for printers...'
: 'No printers found.\n'
'Power-cycle the printer and rescan.',
textAlign: TextAlign.center,
),
)
: ListView.builder(
itemCount: _devices.length,
itemBuilder: (context, index) {
final device = _devices[index];
final isSelected =
_selected?.address == device.address;
return ListTile(
leading: const Icon(Icons.print),
title: Text(device.name),
subtitle: Text(device.address),
trailing: isSelected && connected
? const Icon(Icons.check_circle,
color: Colors.green)
: null,
onTap: () => _connect(device),
);
},
),
),
if (connected)
const Padding(
padding: EdgeInsets.all(12),
child: Text(
'Tip: a connected printer stops advertising, '
'so it will not appear in new scan results.',
style: TextStyle(fontSize: 12, color: Colors.grey),
),
),
],
),
);
}
}