Flutter蓝牙热敏打印机插件bluetooth_thermal_printer的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter蓝牙热敏打印机插件bluetooth_thermal_printer的使用

插件简介

bluetooth_thermal_printer 是一个用于Flutter应用的插件,允许通过蓝牙连接热敏打印机打印收据。它支持58mm和80mm的蓝牙打印机,并且不需要位置权限,符合Google的Android 10政策。

添加依赖

首先,在您的pubspec.yaml文件中添加以下依赖:

dependencies:
  bluetooth_thermal_printer: ^latest_version # 替换为最新版本号
  esc_pos_utils: ^latest_version # 用于生成打印内容
  image: ^latest_version # 如果需要打印图片

然后运行flutter pub get以安装这些依赖。

示例代码

主程序入口

下面是一个完整的示例代码,展示了如何使用这个插件进行蓝牙设备搜索、连接以及打印操作:

import 'dart:async';

import 'package:bluetooth_thermal_printer/bluetooth_thermal_printer.dart';
import 'package:esc_pos_utils/esc_pos_utils.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

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

class _MyAppState extends State<MyApp> {
  bool connected = false;
  List availableBluetoothDevices = [];

  Future<void> getBluetooth() async {
    final List bluetooths = await BluetoothThermalPrinter.getBluetooths;
    print("Print $bluetooths");
    setState(() {
      availableBluetoothDevices = bluetooths;
    });
  }

  Future<void> setConnect(String mac) async {
    final String result = await BluetoothThermalPrinter.connect(mac);
    print("state conneected $result");
    if (result == "true") {
      setState(() {
        connected = true;
      });
    }
  }

  Future<void> printTicket() async {
    String isConnected = await BluetoothThermalPrinter.connectionStatus;
    if (isConnected == "true") {
      List<int> bytes = await getTicket();
      final result = await BluetoothThermalPrinter.writeBytes(bytes);
      print("Print $result");
    } else {
      // Handle Not Connected Scenario
    }
  }

  Future<void> printGraphics() async {
    String isConnected = await BluetoothThermalPrinter.connectionStatus;
    if (isConnected == "true") {
      List<int> bytes = await getGraphicsTicket();
      final result = await BluetoothThermalPrinter.writeBytes(bytes);
      print("Print $result");
    } else {
      // Handle Not Connected Scenario
    }
  }

  Future<List<int>> getGraphicsTicket() async {
    List<int> bytes = [];
    CapabilityProfile profile = await CapabilityProfile.load();
    final generator = Generator(PaperSize.mm80, profile);

    // Print QR Code using native function
    bytes += generator.qrcode('example.com');

    bytes += generator.hr();

    // Print Barcode using native function
    final List<int> barData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 4];
    bytes += generator.barcode(Barcode.upcA(barData));

    bytes += generator.cut();

    return bytes;
  }

  Future<List<int>> getTicket() async {
    List<int> bytes = [];
    CapabilityProfile profile = await CapabilityProfile.load();
    final generator = Generator(PaperSize.mm80, profile);

    bytes += generator.text("Demo Shop",
        styles: PosStyles(
          align: PosAlign.center,
          height: PosTextSize.size2,
          width: PosTextSize.size2,
        ),
        linesAfter: 1);

    bytes += generator.text(
        "18th Main Road, 2nd Phase, J. P. Nagar, Bengaluru, Karnataka 560078",
        styles: PosStyles(align: PosAlign.center));
    bytes += generator.text('Tel: +919591708470',
        styles: PosStyles(align: PosAlign.center));

    bytes += generator.hr();
    bytes += generator.row([
      PosColumn(
          text: 'No',
          width: 1,
          styles: PosStyles(align: PosAlign.left, bold: true)),
      PosColumn(
          text: 'Item',
          width: 5,
          styles: PosStyles(align: PosAlign.left, bold: true)),
      PosColumn(
          text: 'Price',
          width: 2,
          styles: PosStyles(align: PosAlign.center, bold: true)),
      PosColumn(
          text: 'Qty',
          width: 2,
          styles: PosStyles(align: PosAlign.center, bold: true)),
      PosColumn(
          text: 'Total',
          width: 2,
          styles: PosStyles(align: PosAlign.right, bold: true)),
    ]);

    bytes += generator.row([
      PosColumn(text: "1", width: 1),
      PosColumn(
          text: "Tea",
          width: 5,
          styles: PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text: "10",
          width: 2,
          styles: PosStyles(
            align: PosAlign.center,
          )),
      PosColumn(text: "1", width: 2, styles: PosStyles(align: PosAlign.center)),
      PosColumn(text: "10", width: 2, styles: PosStyles(align: PosAlign.right)),
    ]);

    bytes += generator.row([
      PosColumn(text: "2", width: 1),
      PosColumn(
          text: "Sada Dosa",
          width: 5,
          styles: PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text: "30",
          width: 2,
          styles: PosStyles(
            align: PosAlign.center,
          )),
      PosColumn(text: "1", width: 2, styles: PosStyles(align: PosAlign.center)),
      PosColumn(text: "30", width: 2, styles: PosStyles(align: PosAlign.right)),
    ]);

    bytes += generator.row([
      PosColumn(text: "3", width: 1),
      PosColumn(
          text: "Masala Dosa",
          width: 5,
          styles: PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text: "50",
          width: 2,
          styles: PosStyles(
            align: PosAlign.center,
          )),
      PosColumn(text: "1", width: 2, styles: PosStyles(align: PosAlign.center)),
      PosColumn(text: "50", width: 2, styles: PosStyles(align: PosAlign.right)),
    ]);

    bytes += generator.row([
      PosColumn(text: "4", width: 1),
      PosColumn(
          text: "Rova Dosa",
          width: 5,
          styles: PosStyles(
            align: PosAlign.left,
          )),
      PosColumn(
          text: "70",
          width: 2,
          styles: PosStyles(
            align: PosAlign.center,
          )),
      PosColumn(text: "1", width: 2, styles: PosStyles(align: PosAlign.center)),
      PosColumn(text: "70", width: 2, styles: PosStyles(align: PosAlign.right)),
    ]);

    bytes += generator.hr();

    bytes += generator.row([
      PosColumn(
          text: 'TOTAL',
          width: 6,
          styles: PosStyles(
            align: PosAlign.left,
            height: PosTextSize.size4,
            width: PosTextSize.size4,
          )),
      PosColumn(
          text: "160",
          width: 6,
          styles: PosStyles(
            align: PosAlign.right,
            height: PosTextSize.size4,
            width: PosTextSize.size4,
          )),
    ]);

    bytes += generator.hr(ch: '=', linesAfter: 1);

    bytes += generator.text('Thank you!',
        styles: PosStyles(align: PosAlign.center, bold: true));

    bytes += generator.text("26-11-2020 15:22:45",
        styles: PosStyles(align: PosAlign.center), linesAfter: 1);

    bytes += generator.text(
        'Note: Goods once sold will not be taken back or exchanged.',
        styles: PosStyles(align: PosAlign.center, bold: false));
    bytes += generator.cut();
    return bytes;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Bluetooth Thermal Printer Demo'),
        ),
        body: Container(
          padding: EdgeInsets.all(20),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text("Search Paired Bluetooth"),
              TextButton(
                onPressed: () {
                  this.getBluetooth();
                },
                child: Text("Search"),
              ),
              Container(
                height: 200,
                child: ListView.builder(
                  itemCount: availableBluetoothDevices.length > 0
                      ? availableBluetoothDevices.length
                      : 0,
                  itemBuilder: (context, index) {
                    return ListTile(
                      onTap: () {
                        String select = availableBluetoothDevices[index];
                        List list = select.split("#");
                        String mac = list[1];
                        this.setConnect(mac);
                      },
                      title: Text('${availableBluetoothDevices[index]}'),
                      subtitle: Text("Click to connect"),
                    );
                  },
                ),
              ),
              SizedBox(
                height: 30,
              ),
              TextButton(
                onPressed: connected ? this.printGraphics : null,
                child: Text("Print Graphics"),
              ),
              TextButton(
                onPressed: connected ? this.printTicket : null,
                child: Text("Print Ticket"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

功能说明

  • getBluetooth: 搜索已配对的蓝牙设备。
  • setConnect: 连接到指定MAC地址的蓝牙设备。
  • printTicketprintGraphics: 分别用于打印普通票据和包含图形(如二维码、条形码)的票据。

注意事项

  • 请确保您的蓝牙打印机已经正确配对。
  • 在实际使用中,请根据具体需求调整打印内容。
  • 对于某些特殊字符或语言的支持,可以参考 esc_pos_utils 文档中的编码表设置。

希望这个指南能帮助您快速上手 bluetooth_thermal_printer 插件!如果有任何问题或建议,欢迎随时反馈。


更多关于Flutter蓝牙热敏打印机插件bluetooth_thermal_printer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter蓝牙热敏打印机插件bluetooth_thermal_printer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用Flutter蓝牙热敏打印机插件 bluetooth_thermal_printer 的代码示例。这个示例将展示如何连接到蓝牙热敏打印机、发送打印数据以及执行一些基本的打印操作。

首先,确保你已经在 pubspec.yaml 文件中添加了 bluetooth_thermal_printer 依赖:

dependencies:
  flutter:
    sdk: flutter
  bluetooth_thermal_printer: ^x.y.z  # 请替换为最新版本号

然后,运行 flutter pub get 来获取依赖。

以下是一个完整的示例代码,展示了如何使用该插件:

import 'package:flutter/material.dart';
import 'package:bluetooth_thermal_printer/bluetooth_thermal_printer.dart';

void main() {
  runApp(MyApp());
}

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

class _MyAppState extends State<MyApp> {
  BluetoothThermalPrinter? _printer;
  BluetoothDevice? _connectedDevice;
  List<BluetoothDevice> _devices = [];

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

  Future<void> initPrinter() async {
    _printer = BluetoothThermalPrinter();

    // 监听设备发现
    _printer!.scanResults!.listen((devices) {
      setState(() {
        _devices = devices;
      });
    });

    // 开始扫描设备
    await _printer!.startScan();
  }

  Future<void> connectToDevice(BluetoothDevice device) async {
    setState(() {
      _connectedDevice = device;
    });

    // 连接到设备
    await _printer!.connect(device.address);

    // 等待设备连接成功
    _printer!.isConnected!.listen((isConnected) {
      if (isConnected) {
        print("Connected to printer");
        // 打印测试文本
        printTestText();
      } else {
        print("Disconnected from printer");
      }
    });
  }

  Future<void> printTestText() async {
    if (_printer!.isConnected!.value!!) {
      String text = "Hello, this is a test print from Flutter!\n";
      await _printer!.printText(text);
      await _printer!.feedPaper(2); // 进纸两行
    } else {
      print("Printer is not connected");
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Bluetooth Thermal Printer Example'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              Text('Available Devices:'),
              SizedBox(height: 16),
              Expanded(
                child: ListView.builder(
                  itemCount: _devices.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text(_devices[index].name ?? 'Unknown Device'),
                      subtitle: Text(_devices[index].address),
                      onTap: () => connectToDevice(_devices[index]),
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

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

代码解释:

  1. 依赖导入:在 pubspec.yaml 中添加 bluetooth_thermal_printer 依赖。
  2. 初始化插件:在 initState 方法中初始化 BluetoothThermalPrinter 实例,并开始扫描蓝牙设备。
  3. 设备发现监听:通过 _printer!.scanResults!.listen 监听发现的设备,并更新设备列表。
  4. 连接设备:点击列表项时,调用 connectToDevice 方法连接到选定的蓝牙设备。连接成功后,会触发 isConnected 监听器。
  5. 打印文本:连接成功后,调用 printTestText 方法发送打印指令。
  6. 释放资源:在 dispose 方法中停止扫描并释放插件资源。

这个示例展示了基本的蓝牙热敏打印机连接和打印功能。你可以根据实际需求扩展此示例,例如添加更多打印格式、处理错误情况等。

回到顶部