Flutter蓝牙热敏打印机插件bluetooth_thermal_printer的使用
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地址的蓝牙设备。
- printTicket 和 printGraphics: 分别用于打印普通票据和包含图形(如二维码、条形码)的票据。
注意事项
- 请确保您的蓝牙打印机已经正确配对。
- 在实际使用中,请根据具体需求调整打印内容。
- 对于某些特殊字符或语言的支持,可以参考
esc_pos_utils
文档中的编码表设置。
希望这个指南能帮助您快速上手 bluetooth_thermal_printer
插件!如果有任何问题或建议,欢迎随时反馈。
更多关于Flutter蓝牙热敏打印机插件bluetooth_thermal_printer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于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();
}
}
代码解释:
- 依赖导入:在
pubspec.yaml
中添加bluetooth_thermal_printer
依赖。 - 初始化插件:在
initState
方法中初始化BluetoothThermalPrinter
实例,并开始扫描蓝牙设备。 - 设备发现监听:通过
_printer!.scanResults!.listen
监听发现的设备,并更新设备列表。 - 连接设备:点击列表项时,调用
connectToDevice
方法连接到选定的蓝牙设备。连接成功后,会触发isConnected
监听器。 - 打印文本:连接成功后,调用
printTestText
方法发送打印指令。 - 释放资源:在
dispose
方法中停止扫描并释放插件资源。
这个示例展示了基本的蓝牙热敏打印机连接和打印功能。你可以根据实际需求扩展此示例,例如添加更多打印格式、处理错误情况等。