mf_bluetooth_printer 1.0.5 copy "mf_bluetooth_printer: ^1.0.5" to clipboard
mf_bluetooth_printer: ^1.0.5 copied to clipboard

A Flutter package for MF Bluetooth Printer — print receipts to Bluetooth thermal printers via ESC/POS.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart' as fbp;
import 'package:mf_bluetooth_printer/mf_bluetooth_printer.dart';
import 'package:permission_handler/permission_handler.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Bluetooth Thermal Printer Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF1565C0),
          brightness: Brightness.light,
        ),
        cardTheme: CardThemeData(
          elevation: 1,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(12),
          ),
          margin: EdgeInsets.zero,
          clipBehavior: Clip.antiAlias,
        ),
      ),
      home: const PrinterExamplePage(),
    );
  }
}

class PrinterExamplePage extends StatefulWidget {
  const PrinterExamplePage({super.key});

  @override
  State<PrinterExamplePage> createState() => _PrinterExamplePageState();
}

class _PrinterExamplePageState extends State<PrinterExamplePage> {
  final BluetoothPrinterService _printer = BluetoothPrinterService();

  @override
  void dispose() {
    _printer.dispose();
    super.dispose();
  }

  Future<void> _scan() async {
    try {
      await _printer.startScan();
    } catch (e) {
      if (mounted) {
        final msg = e.toString().replaceFirst('Exception: ', '');
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(msg),
            behavior: SnackBarBehavior.floating,
            action: SnackBarAction(
              label: 'Settings',
              onPressed: () => openAppSettings(),
            ),
          ),
        );
      }
    }
  }

  Future<void> _connect(fbp.BluetoothDevice device) async {
    try {
      await _printer.connectToDevice(device);
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: const Text('Connected to printer'),
            behavior: SnackBarBehavior.floating,
            backgroundColor: Colors.green.shade700,
          ),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Connect error: $e'),
            behavior: SnackBarBehavior.floating,
            backgroundColor: Colors.red.shade700,
          ),
        );
      }
    }
  }

  Future<void> _printTest() async {
    final receipt = ReceiptData(
      companyInfo: const CompanyInfo(
        name: 'Example Co',
        address1: '123 Street',
        phone: '1234567890',
        taxNo: 'TRN123',
        email: 'sales@example.com',
      ),
      salesmanName: 'John',
      routeName: 'Route A',
      invoiceNumber: 'INV-001',
      dateTime: DateTime.now(),
      customerPhone: '9876543210',
      paymentMethod: 'cash',
      customerName: 'Customer Name',
      customerAddress: 'Address',
      customerCode: 'C001',
      customerTRN: 'TRN456',
      items: [
        ReceiptItem(
          productCode: 'P1',
          name: 'Product One',
          quantity: 2,
          price: 10.0,
          netTotal: 20.0,
          vatAmount: 1.0,
          total: 21.0,
        ),
      ],
      totalBeforeTax: 20.0,
      taxAmount: 1.0,
      roundOff: 0.0,
      totalAmount: 21.0,
    );

    try {
      await _printer.printReceipt(
        receipt,
        printerSize: PrinterSize.threeInch,
        design: const PrinterDesignSettings(),
      );
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: const Text('Receipt sent to printer'),
            behavior: SnackBarBehavior.floating,
            backgroundColor: Colors.green.shade700,
          ),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Print error: $e'),
            behavior: SnackBarBehavior.floating,
            backgroundColor: Colors.red.shade700,
          ),
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Scaffold(
      appBar: AppBar(
        title: const Text('Bluetooth Thermal Printer'),
        centerTitle: true,
        elevation: 0,
        scrolledUnderElevation: 2,
      ),
      body: ListView(
        padding: const EdgeInsets.all(20),
        children: [
          ValueListenableBuilder<bool>(
            valueListenable: _printer.isConnected,
            builder: (_, connected, __) => Card(
              child: Padding(
                padding: const EdgeInsets.all(20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    Row(
                      children: [
                        Container(
                          padding: const EdgeInsets.all(10),
                          decoration: BoxDecoration(
                            color: connected
                                ? Colors.green.withOpacity(0.15)
                                : theme.colorScheme.surfaceContainerHighest,
                            borderRadius: BorderRadius.circular(12),
                          ),
                          child: Icon(
                            connected ? Icons.print : Icons.print_disabled,
                            size: 28,
                            color: connected
                                ? Colors.green.shade700
                                : theme.colorScheme.onSurfaceVariant,
                          ),
                        ),
                        const SizedBox(width: 16),
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                connected ? 'Printer connected' : 'No printer',
                                style: theme.textTheme.titleMedium?.copyWith(
                                  fontWeight: FontWeight.w600,
                                ),
                              ),
                              const SizedBox(height: 2),
                              Text(
                                connected
                                    ? 'Ready to print receipts'
                                    : 'Scan and tap a device to connect',
                                style: theme.textTheme.bodySmall?.copyWith(
                                  color: theme.colorScheme.onSurfaceVariant,
                                ),
                              ),
                            ],
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 20),
                    FilledButton.icon(
                      onPressed: _printer.isScanning.value ? null : _scan,
                      icon: _printer.isScanning.value
                          ? SizedBox(
                              width: 20,
                              height: 20,
                              child: CircularProgressIndicator(
                                strokeWidth: 2,
                                color: theme.colorScheme.onPrimary,
                              ),
                            )
                          : const Icon(Icons.search, size: 20),
                      label: Text(
                        _printer.isScanning.value ? 'Scanning...' : 'Scan for printers',
                      ),
                      style: FilledButton.styleFrom(
                        padding: const EdgeInsets.symmetric(vertical: 14),
                      ),
                    ),
                    if (connected) ...[
                      const SizedBox(height: 12),
                      FilledButton.tonalIcon(
                        onPressed: _printTest,
                        icon: const Icon(Icons.receipt_long, size: 20),
                        label: const Text('Print test receipt'),
                        style: FilledButton.styleFrom(
                          padding: const EdgeInsets.symmetric(vertical: 14),
                        ),
                      ),
                    ],
                  ],
                ),
              ),
            ),
          ),
          const SizedBox(height: 28),
          ValueListenableBuilder<List<fbp.ScanResult>>(
            valueListenable: _printer.scanResults,
            builder: (_, results, __) {
              return Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Padding(
                    padding: const EdgeInsets.only(left: 4, bottom: 8),
                    child: Text(
                      'Available devices',
                      style: theme.textTheme.titleSmall?.copyWith(
                        color: theme.colorScheme.onSurfaceVariant,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),
                  if (results.isEmpty)
                    Card(
                      child: Padding(
                        padding: const EdgeInsets.symmetric(
                          vertical: 24,
                          horizontal: 20,
                        ),
                        child: Row(
                          children: [
                            Icon(
                              Icons.bluetooth_searching,
                              size: 40,
                              color: theme.colorScheme.outline,
                            ),
                            const SizedBox(width: 16),
                            Expanded(
                              child: Text(
                                'No devices found. Tap "Scan for printers" above.',
                                style: theme.textTheme.bodyMedium?.copyWith(
                                  color: theme.colorScheme.onSurfaceVariant,
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    )
                  else
                    ...results.map((r) {
                      final name = r.device.platformName.isNotEmpty
                          ? r.device.platformName
                          : 'Unknown device';
                      return Card(
                        margin: const EdgeInsets.only(bottom: 8),
                        child: ListTile(
                          contentPadding: const EdgeInsets.symmetric(
                            horizontal: 16,
                            vertical: 4,
                          ),
                          leading: CircleAvatar(
                            backgroundColor: theme.colorScheme.primaryContainer,
                            child: Icon(
                              Icons.print,
                              color: theme.colorScheme.onPrimaryContainer,
                            ),
                          ),
                          title: Text(
                            name,
                            style: const TextStyle(fontWeight: FontWeight.w500),
                          ),
                          subtitle: Padding(
                            padding: const EdgeInsets.only(top: 4),
                            child: Text(
                              '${r.device.remoteId.str}  ·  RSSI ${r.rssi}',
                              style: theme.textTheme.bodySmall,
                            ),
                          ),
                          trailing: const Icon(Icons.chevron_right),
                          onTap: () => _connect(r.device),
                        ),
                      );
                    }),
                ],
              );
            },
          ),
        ],
      ),
    );
  }
}
2
likes
145
points
23
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter package for MF Bluetooth Printer — print receipts to Bluetooth thermal printers via ESC/POS.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, flutter_blue_plus, image, intl, permission_handler

More

Packages that depend on mf_bluetooth_printer