walure_android_blt

A Flutter plugin for connecting to Bluetooth devices, specifically designed for POS (Point of Sale) systems and receipt printing. This plugin provides easy-to-use APIs for Bluetooth device discovery, connection management, and data transmission.

Features

  • πŸ” Bluetooth Device Discovery: Scan and discover nearby Bluetooth devices
  • πŸ”— Device Connection Management: Connect and disconnect from Bluetooth devices
  • πŸ“± Android Support: Full Android implementation with proper permission handling
  • πŸ–¨οΈ Receipt Printing: Built-in support for receipt printing with various formatting options
  • ⚑ Real-time Device Stream: Stream-based device discovery for real-time updates
  • πŸ›‘οΈ Error Handling: Comprehensive error handling with custom exception types
  • πŸ”’ Permission Management: Automatic handling of Bluetooth permissions for different Android versions

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  walure_android_blt: ^0.0.1

Then run:

flutter pub get

Android Setup

Permissions

The plugin automatically handles Bluetooth permissions, but make sure your android/app/src/main/AndroidManifest.xml includes:

<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_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Minimum SDK Version

Ensure your android/app/build.gradle has:

android {
    compileSdkVersion 34
    defaultConfig {
        minSdkVersion 21  // Required for Bluetooth functionality
    }
}

Usage

Basic Setup

import 'package:walure_android_blt/walure_android_blt.dart';

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _bluetoothPlugin = WalureAndroidBlt.instance;

  @override
  void initState() {
    super.initState();
    _initializeBluetooth();
  }

  Future<void> _initializeBluetooth() async {
    try {
      await _bluetoothPlugin.initBluetooth();
      print('Bluetooth initialized successfully');
    } catch (e) {
      print('Error initializing Bluetooth: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Bluetooth Printer Demo')),
        body: YourWidget(),
      ),
    );
  }
}

Device Discovery

class BluetoothDeviceList extends StatefulWidget {
  @override
  _BluetoothDeviceListState createState() => _BluetoothDeviceListState();
}

class _BluetoothDeviceListState extends State<BluetoothDeviceList> {
  final _bluetoothPlugin = WalureAndroidBlt.instance;

  @override
  void initState() {
    super.initState();
    _startScanning();
  }

  void _startScanning() async {
    try {
      await _bluetoothPlugin.scanBluetooth();
    } catch (e) {
      print('Error starting scan: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Available Devices')),
      body: StreamBuilder<List<BluetoothDevice?>?>(
        stream: _bluetoothPlugin.devices,
        builder: (context, snapshot) {
          if (snapshot.hasData && snapshot.data != null) {
            return ListView.builder(
              itemCount: snapshot.data!.length,
              itemBuilder: (context, index) {
                final device = snapshot.data![index];
                return ListTile(
                  title: Text(device?.name ?? 'Unknown Device'),
                  subtitle: Text(device?.id ?? ''),
                  trailing: ElevatedButton(
                    onPressed: () => _connectToDevice(device),
                    child: Text('Connect'),
                  ),
                );
              },
            );
          }
          return Center(child: CircularProgressIndicator());
        },
      ),
    );
  }

  Future<void> _connectToDevice(BluetoothDevice? device) async {
    try {
      final result = await _bluetoothPlugin.connectDevice(device);
      if (result?.bondState == BondState.bonded) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Connected to ${device?.name}')),
        );
      }
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Connection failed: $e')),
      );
    }
  }
}

Receipt Printing

class ReceiptPrinter {
  final _bluetoothPlugin = WalureAndroidBlt.instance;

  Future<void> printReceipt() async {
    try {
      // Initialize printer
      await _bluetoothPlugin.writeData(PrinterCommand.posSetPrintInit());

      // Print header
      await _bluetoothPlugin.writeData(PrinterCommand.posPrintTextLn(
        'My Store',
        align: PosAlign.center,
        nWidthTimes: 1,
        nHeightTimes: 1,
      ));

      // Print receipt details
      await _bluetoothPlugin.writeData(PrinterCommand.posPrintTextLn(
        "Receipt #12345\n"
        "Date: ${DateTime.now().toString()}\n"
        "Cashier: John Doe\n",
        align: PosAlign.left,
      ));

      // Print items
      await _bluetoothPlugin.writeData(PrinterCommand.posPrintTextLn(
        "Item Name    Qty    Price    Total\n"
        "Coffee       2      3.50     7.00\n"
        "Sandwich     1      5.00     5.00\n",
        align: PosAlign.left,
      ));

      // Print total
      await _bluetoothPlugin.writeData(PrinterCommand.posPrintTextLn(
        "Total: \$12.00",
        align: PosAlign.right,
      ));

      // Cut paper
      await _bluetoothPlugin.writeData(PrinterCommand.posSetPrtAndFeedPaper(48));
      await _bluetoothPlugin.writeData(Command.gsVmn);

    } catch (e) {
      print('Printing error: $e');
    }
  }
}

Custom Printer Commands

// Print with custom formatting
await _bluetoothPlugin.writeData(PrinterCommand.posPrintTextLn(
  'BOLD TEXT',
  nWidthTimes: 2,  // Double width
  nHeightTimes: 2, // Double height
  align: PosAlign.center,
));

// Print barcode
await _bluetoothPlugin.writeData(PrinterCommand.getCodeBarCommand(
  '123456789',
  65, // Code type
  2,  // Width
  50, // Height
  0,  // Font type
  2,  // Position
));

// Print QR code
await _bluetoothPlugin.writeData(PrinterCommand.getBarCommand(
  'https://example.com',
  3,  // Version
  1,  // Error correction level
  4,  // Magnification
));

API Reference

WalureAndroidBlt

The main class for interacting with Bluetooth devices.

Methods

  • initBluetooth() - Initialize Bluetooth functionality
  • scanBluetooth() - Start scanning for nearby devices
  • stopScanning() - Stop the current scan
  • connectDevice(BluetoothDevice device) - Connect to a specific device
  • disconnectDevice() - Disconnect from the current device
  • printTestData() - Print a sample receipt for testing

Properties

  • devices - Stream of discovered Bluetooth devices
  • getDiscoveredDevices() - Get list of currently discovered devices

BluetoothDevice

Represents a Bluetooth device.

Properties

  • id - Device MAC address
  • name - Device name
  • alias - Device alias (if available)
  • type - Device type
  • bondState - Bonding state (bonded, bonding, none)

PrinterCommand

Utility class for generating printer commands.

Common Methods

  • posSetPrintInit() - Initialize printer
  • posPrintTextLn(String text, {PosAlign align, int nWidthTimes, int nHeightTimes}) - Print text with line break
  • posSetPrtAndFeedPaper(int feed) - Feed paper
  • getCodeBarCommand(...) - Print barcode
  • getBarCommand(...) - Print QR code

Exception Types

  • BluetoothException - General Bluetooth-related errors
  • NotAvailableBltException - Bluetooth not available on device

Example App

The plugin includes a complete example app demonstrating:

  • Bluetooth initialization
  • Device scanning and listing
  • Device connection
  • Receipt printing
  • Error handling

To run the example:

cd example
flutter run

Requirements

  • Flutter 3.3.0+
  • Dart 3.1.5+
  • Android API level 21+ (Android 5.0+)

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 use the GitHub issue tracker.


Note: This plugin is specifically designed for Android and focuses on Bluetooth Classic (SPP) connections for POS printers. For iOS support or BLE connections, consider other plugins.