bt_printer_plugin 0.1.3
bt_printer_plugin: ^0.1.3 copied to clipboard
A Flutter plugin for Bluetooth thermal printing using ESC/POS commands.
import 'package:bt_printer_plugin/bt_printer_plugin.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BT Printer Test',
debugShowCheckedModeBanner: false,
theme: ThemeData(
useMaterial3: true,
colorSchemeSeed: Colors.green,
scaffoldBackgroundColor: Colors.white,
),
home: const PrinterScreen(),
);
}
}
class PrinterScreen extends StatefulWidget {
const PrinterScreen({super.key});
@override
State<PrinterScreen> createState() => _PrinterScreenState();
}
class _PrinterScreenState extends State<PrinterScreen> {
List<Map<String, String>> _printers = [];
String? _connectedPrinter;
bool _isLoading = false;
String _status = '';
@override
void initState() {
super.initState();
_fetchPrinters();
}
Future<void> _fetchPrinters() async {
setState(() {
_isLoading = true;
_status = 'Scanning for devices...';
});
try {
final devices = await BtPrinterPlugin.getPairedDevices();
setState(() {
_printers = devices;
_status = devices.isEmpty ? 'No printers found.' : 'Select a printer';
});
} catch (e) {
setState(() {
_status = 'Failed to get devices: $e';
_printers = [];
});
} finally {
setState(() {
_isLoading = false;
});
}
}
Future<void> _connectPrinter(String address, String name) async {
if (address.isEmpty) return;
setState(() {
_status = 'Connecting...';
});
try {
final success = await BtPrinterPlugin.connect(address);
setState(() {
_connectedPrinter = success ? address : null;
_status = success ? 'Connected to $name' : 'Connection failed';
});
} catch (e) {
setState(() {
_status = 'Connection error: $e';
});
}
}
Future<void> _printTestTicket() async {
if (_connectedPrinter == null) return;
const ticket = '''
\x1B\x40
\x1B\x61\x01Hello from Flutter
\x0AThis is a Bluetooth print test message.
\x0A\x0AThank you.
\x0A\x0A
''';
try {
final success = await BtPrinterPlugin.printRaw(ticket);
setState(() {
_status = success ? 'Test message sent to printer.' : 'Print failed.';
});
} catch (e) {
setState(() {
_status = 'Print error: $e';
});
}
}
Widget _buildPrinterTile(Map<String, String> printer) {
final isConnected = printer['address'] == _connectedPrinter;
return Card(
elevation: 1,
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: ListTile(
leading: const Icon(Icons.print, color: Colors.green),
title: Text(printer['name'] ?? 'Unknown'),
subtitle: Text(printer['address'] ?? ''),
trailing: isConnected
? const Icon(Icons.check_circle, color: Colors.green)
: OutlinedButton(
onPressed: () => _connectPrinter(
printer['address'] ?? '',
printer['name'] ?? '',
),
child: const Text("Connect"),
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
'Select Printer',
style: TextStyle(color: Colors.white),
),
iconTheme: const IconThemeData(color: Colors.white),
backgroundColor: Colors.green,
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: _fetchPrinters,
),
],
),
body: Column(
children: [
if (_isLoading) const LinearProgressIndicator(),
Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
children: [
const Icon(Icons.info_outline, size: 20, color: Colors.grey),
const SizedBox(width: 8),
Expanded(
child: Text(_status, style: const TextStyle(fontSize: 16)),
),
],
),
),
Expanded(
child: ListView.builder(
itemCount: _printers.length,
itemBuilder: (context, index) {
return _buildPrinterTile(_printers[index]);
},
),
),
if (_connectedPrinter != null)
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _printTestTicket,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: const Text(
"Print Test",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
),
),
],
),
);
}
}