Flutter打印机控制插件gpos720_printer的使用
Flutter 打印机控制插件 gpos720_printer 的使用
功能特性
下表列出了 gpos720_printer
插件支持的方法及其实现状态。
方法名称 | 实现状态 |
---|---|
checarImpressora | ✔️ |
avancaLinha | ✔️ |
imprimirTexto | ✔️ |
imprimirImagem | ✔️ |
imprimirImagemFiltrada | ✔️ |
imprimirCodigoDeBarra | ✔️ |
imprimirCodigoDeBarraImg | ✔️ |
imprimirTodasFuncoes | ✔️ |
imprimirEscPos | ❌ |
要求
- Android 最低 SDK 版本 >= 22。
- Flutter 版本 >= 2.0.0。
- Dart 版本 >= 2.12.0。
安装
步骤 1
在 /android/src/main/AndroidManifest.xml
文件中添加以下内容:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
...
<uses-feature android:name="android.hardware.usb.host" />
...
</manifest>
步骤 2
由于 Android Gradle 插件(AGP)不直接支持本地 AAR 依赖项,因此需要进行以下配置。
-
在
/android/app/libs/
目录下粘贴该库所需的两个 .aar 依赖项。你可以从 这里 下载它们。 -
然后在
android/app/build.gradle
中添加以下内容:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar'])
}
- 最后在
android/build.gradle
中添加以下内容:
allprojects {
repositories {
google()
mavenCentral()
flatDir {
dirs 'libs'
}
}
}
开始使用
只需实例化 Gpos720Printer
并调用所需的功能,如 此处示例项目 所示。
必须拥有 Gertec GPOS720 设备才能使用此插件。
实例化
实例化 Gpos720Printer
对象如下所示:
import 'package:gpos720_printer/gpos720_printer.dart';
void main() {
Gpos720Printer gpos720Printer = Gpos720Printer(finalizarImpressao: false);
}
可以传递可选布尔参数 finalizarImpressao
来在执行打印命令后调用 fimImpressao
函数。默认情况下,此参数设置为 false
,因此可能需要在执行所有所需的打印命令后调用 fimImpressao
。
文档
方法
Future<PrinterStatus> checarImpressora()
- 描述:检查打印机的状态。
- 返回值:一个表示打印机状态的
PrinterStatus
枚举。 - 异常:可能抛出
PlatformException
或MissingPluginException
。
Future<PrinterStatus> fimImpressao()
- 描述:打印所有缓冲的打印机命令。
- 返回值:一个表示打印机状态的
PrinterStatus
枚举。 - 异常:可能抛出
PlatformException
或MissingPluginException
。
Future<PrinterStatus> avancaLinha(int quantLinhas)
- 描述:添加行分隔符到当前打印输出。
- 返回值:一个表示打印机状态的
PrinterStatus
枚举。 - 参数
quantLinhas
: 指定所需的行数。
- 异常:可能抛出
PlatformException
或MissingPluginException
。
Future<PrinterStatus> imprimirTexto(String mensagem, {TextOptions? options, int size = defaultFontSize, Font? font, AlignmentTypes align = AlignmentTypes.left})
- 描述:打印文本。
- 返回值:一个表示打印机状态的
PrinterStatus
枚举。 - 参数
mensagem
: 需要打印的文本。options
(可选): 指定文本是否应以粗体、斜体或下划线形式呈现。size
(可选): 指定所需的字体大小。font
(可选): 指定用于文本的字体。align
(可选): 指定所需的对齐方式,默认为左对齐。
- 异常:可能抛出
PlatformException
或MissingPluginException
。
Future<PrinterStatus> imprimirImagem(Uint8List data, int width, int height, {AlignmentTypes align = AlignmentTypes.center})
- 描述:仅打印黑白原始图像。可以使用方法
binaryFilterWithDithering
应用二进制滤波器和抖动。 - 返回值:一个表示打印机状态的
PrinterStatus
枚举。 - 参数
data
: 包含黑白图像原始数据的Uint8List
。width
: 指定所需的宽度。height
: 指定所需的高度。align
(可选): 指定所需的对齐方式,默认为中心对齐。
- 异常:可能抛出
PlatformException
或MissingPluginException
。
Future<PrinterStatus> imprimirImagemFiltrada(Uint8List data, int width, int height, {AlignmentTypes align = AlignmentTypes.center, double? blackTolerance, double? ditheringTolerance})
- 描述:应用二进制滤波器和抖动并打印原始图像。
- 返回值:一个表示打印机状态的
PrinterStatus
枚举。 - 参数
data
: 包含图像原始数据的Uint8List
。width
: 指定所需的宽度。height
: 指定所需的高度。align
(可选): 指定所需的对齐方式,默认为中心对齐。blackTolerance
(可选): 表示使用黑色颜色的容忍度,默认值为 0.34。ditheringTolerance
(可选): 表示使用抖动表示颜色的容忍度,默认值为 0.67。
- 异常:可能抛出
PlatformException
或MissingPluginException
。
Future<PrinterStatus> imprimirCodigoDeBarra(String mensagem, int width, int height, BarcodeTypes barcodeType)
- 描述:打印各种类型的条形码。
- 返回值:一个表示打印机状态的
PrinterStatus
枚举。 - 参数
mensagem
: 指定条形码上的数据。width
: 指定所需的宽度。height
: 指定所需的高度。barcodeType
: 指定所需的条形码类型。
- 异常:可能抛出
PlatformException
或MissingPluginException
。
Future<PrinterStatus> imprimirCodigoDeBarraImg(String mensagem, int width, int height, BarcodeTypes barcodeType)
- 描述:将各种类型的条形码渲染为图像。
- 返回值:一个表示打印机状态的
PrinterStatus
枚举。 - 参数
mensagem
: 指定条形码上的数据。width
: 指定所需的宽度。height
: 指定所需的高度。barcodeType
: 指定所需的条形码类型。
- 异常:可能抛出
PlatformException
或MissingPluginException
。
Future<PrinterStatus> imprimirTodasFuncoes(Uint8List data, int width, int height)
- 描述:打印所有打印机功能。
- 返回值:一个表示打印机状态的
PrinterStatus
枚举。 - 参数
data
: 包含黑白图像原始数据的Uint8List
。width
: 指定所需的宽度。height
: 指定所需的高度。
- 异常:可能抛出
PlatformException
或MissingPluginException
。
配置参数
BarcodeTypes
一个枚举,用于指示要打印的条形码类型。点击 这里 查看可用类型。
AlignmentTypes
一个枚举,用于指示要打印的命令的所需对齐方式。点击 这里 查看可用类型。
Font
一个对象,用于指定要打印的字体。构造函数接收字体名称作为参数,并且字体必须在 /fonts
目录下的资源文件夹中可用。默认设置为 “NORMAL”。点击 这里 查看实现。
TextOptions
一个对象,用于指定所需的文本装饰。它可以添加粗体、斜体或下划线样式。默认情况下,所有样式都设置为 false
。点击 这里 查看实现。
输出
PrinterStatus
一个枚举,用于指示打印机的当前状态,可以通过 .getLabel
方法将其解析为字符串。点击 这里 查看实现。
图像工具
binaryFilterWithDithering
一个方法,应用于图像的二进制滤波器和抖动,将其转换为黑白图像,同时使用抖动来表示较暗的颜色。该方法接受以下参数:
image
: 一个包含图像的Uint8List
。blackTolerance
: 一个double
,表示使用黑色颜色的容忍度,默认值为 0.34。ditheringTolerance
: 一个double
,表示使用抖动表示颜色的容忍度,默认值为 0.67。
返回值:一个包含过滤后的图像的 Uint8List
。点击 这里 查看实现。
TODO
- 实现插件测试。
- 打印原始 ESC/POS 命令。
示例代码
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:gpos720_printer/alignment_types.dart';
import 'package:gpos720_printer/barcode_types.dart';
import 'package:gpos720_printer/constants.dart';
import 'package:gpos720_printer/font_model.dart';
import 'package:gpos720_printer/gpos720_printer.dart';
import 'package:gpos720_printer/image_utils.dart';
import 'package:gpos720_printer/printer_status.dart';
import 'package:gpos720_printer/text_options.dart';
import 'package:flutter/services'
show ByteData, MissingPluginException, PlatformException, Uint8List, rootBundle;
import 'dart:ui' as ui;
void main() {
runApp(const MyApp());
}
class SnapshotData {
String platformVersion;
Uint8List imageData;
Uint8List filteredImageData;
int imageWidth;
int imageHeight;
SnapshotData(this.platformVersion, this.imageData, this.filteredImageData, this.imageWidth, this.imageHeight);
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(useMaterial3: false),
home: const Example());
}
}
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
[@override](/user/override)
State<Example> createState() => _ExampleState();
}
class _ExampleState extends State<Example> with SingleTickerProviderStateMixin {
final Gpos720Printer gpos720PrinterPlugin = Gpos720Printer(finalizarImpressao: true);
final String loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Elementum pulvinar etiam non quam lacus. Vitae tortor condimentum lacinia quis vel eros. Massa sapien faucibus et molestie ac feugiat sed lectus vestibulum. Ullamcorper morbi tincidunt ornare massa eget egestas. Molestie at elementum eu facilisis sed odio morbi quis. Tincidunt ornare massa eget egestas purus viverra accumsan in. Augue ut lectus arcu bibendum at. Sem et tortor consequat id porta. Purus sit amet luctus venenatis lectus magna. Nunc lobortis mattis aliquam faucibus purus in massa tempor nec. Fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate sapien. Accumsan sit amet nulla facilisi morbi tempus. Imperdiet proin fermentum leo vel orci porta non. Amet mauris commodo quis imperdiet.";
final ScrollController _scrollbarController = ScrollController();
final double _toolbarHeight = 65;
late AnimationController _animationController;
late Animation<double> _animation, _invertedAnimation;
[@override](/user/override)
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(seconds: 3),
);
_animation = CurvedAnimation(
parent: _animationController,
curve: Curves.easeInOut,
);
_invertedAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(_animation);
_animationController.repeat(reverse: true);
}
[@override](/user/override)
void dispose() {
_animationController.dispose();
super.dispose();
}
Future<SnapshotData> loadAsyncData() async {
Completer<ui.Image> completer = Completer();
ui.decodeImageFromList((await rootBundle.load("assets/flutter.png")).buffer.asUint8List(), (result) {
completer.complete(result);
});
ui.Image image = await completer.future;
Uint8List imageData = (await image.toByteData(format: ui.ImageByteFormat.png))!.buffer.asUint8List();
Uint8List filteredImageData = await ImageUtils.binaryFilterWithDithering(imageData, blackTolerance: 0.34, ditheringTolerance: 0.67);
return SnapshotData(await gpos720PrinterPlugin.getPlatformVersion(), imageData, filteredImageData, image.width, image.height);
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('gpos720_printer'),
),
body: FutureBuilder<SnapshotData>(
future: loadAsyncData(),
builder: (BuildContext context, AsyncSnapshot<SnapshotData> snapshot) {
if (snapshot.hasData) {
return PrimaryScrollController(
controller: _scrollbarController,
child: Scrollbar(
thumbVisibility: true,
controller: _scrollbarController,
child: CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: snapshot.data!.imageHeight.toDouble() + _toolbarHeight,
toolbarHeight: _toolbarHeight,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
expandedTitleScale: 1,
centerTitle: false,
titlePadding: EdgeInsets.zero,
collapseMode: CollapseMode.parallax,
title: AnimatedBuilder(
animation: _scrollbarController,
builder: (BuildContext context, Widget? child) {
double percentage = ((_scrollbarController.offset - _scrollbarController.initialScrollOffset) / (159 - _toolbarHeight)).clamp(0, 1);
return Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: const EdgeInsets.symmetric(vertical: 15),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Text(
'Running on: ${snapshot.data!.platformVersion}',
style: const TextStyle(fontSize: 20),
),
decoration: ShapeDecoration(
shadows: [
BoxShadow(
color: Color.lerp(Colors.black, Colors.transparent, percentage)!,
offset: const Offset(2.0, 2.0),
blurRadius: 3.0,
),
],
color: Color.lerp(Colors.purple, Colors.transparent, percentage)!,
shape: const StadiumBorder()),
),
);
},
),
background: Container(
color: Colors.white,
padding: EdgeInsets.only(top: 8, right: 8, bottom: _toolbarHeight, left: 8),
child: Stack(
children: [
Image.memory(snapshot.data!.filteredImageData, opacity: _animation),
Image.memory(snapshot.data!.imageData, opacity: _invertedAnimation)
],
))),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 5),
sliver: SliverList(
delegate: SliverChildListDelegate([
methodCardBuilder(context, "checarImpressora", "Checks the printer’s status.", () async => gpos720PrinterPlugin.checarImpressora()),
methodCardBuilder(context, "avancaLinha", "Adds line breaks to the current printout.", () async {
return await gpos720PrinterPlugin.avancaLinha(5);
}),
methodCardBuilder(context, "imprimirTexto", "Prints text.", () async {
return await gpos720PrinterPlugin.imprimirTexto(loremIpsum, align: AlignmentTypes.right, size: defaultFontSize, font: Font(fontName: 'NORMAL'), options: TextOptions(bold: false, italic: false, underlined: false));
}),
methodCardBuilder(context, "imprimirImagem", "Prints raw black and white images only.", () async {
return await gpos720PrinterPlugin.imprimirImagem(snapshot.data!.filteredImageData, snapshot.data!.imageHeight, snapshot.data!.imageWidth, align: AlignmentTypes.center);
}),
methodCardBuilder(context, "imprimirImagemFiltrada", "Apply a binary filter with dithering and print the raw image.", () async {
return await gpos720PrinterPlugin.imprimirImagemFiltrada(snapshot.data!.imageData, snapshot.data!.imageHeight, snapshot.data!.imageWidth, align: AlignmentTypes.center, blackTolerance: 0.34, ditheringTolerance: 0.64);
}),
methodCardBuilder(context, "imprimirCodigoDeBarra", "Prints various types of barcodes.", () async {
return await gpos720PrinterPlugin.imprimirCodigoDeBarra("0123456789", 200, 100, BarcodeTypes.upcA);
}),
methodCardBuilder(context, "imprimirCodigoDeBarraImg", "Prints various types of barcodes, rendering them as images.", () async {
return await gpos720PrinterPlugin.imprimirCodigoDeBarraImg("https://www.google.com/", 200, 200, BarcodeTypes.qrCode);
}),
methodCardBuilder(context, "imprimirTodasFuncoes", "Prints all printer functions.", () async {
return await gpos720PrinterPlugin.imprimirTodasFuncoes(snapshot.data!.filteredImageData, snapshot.data!.imageHeight, snapshot.data!.imageWidth);
}),
SizedBox.fromSize(size: ui.Size(MediaQuery.of(context).size.width, snapshot.data!.imageHeight - _toolbarHeight))
])),
)
],
),
),
);
} else if (snapshot.hasError) {
final ScrollController scrollbarController = ScrollController();
return Center(
child: Scrollbar(
thumbVisibility: true,
controller: scrollbarController,
child: SingleChildScrollView(
controller: scrollbarController,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Padding(
padding: EdgeInsets.only(bottom: 12.0),
child: Icon(Icons.error, color: Colors.red, size: 90),
),
Text('${snapshot.error!}', style: const TextStyle(fontSize: 15), textAlign: TextAlign.center)
],
),
),
),
));
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 50,
height: 50,
margin: const EdgeInsets.only(bottom: 12.0),
child: const CircularProgressIndicator(),
),
const Text(
'Loading...',
style: TextStyle(fontSize: 30),
)
],
));
}),
);
}
Widget methodCardBuilder(BuildContext context, String title, String subtitle, Future<PrinterStatus> Function() method) {
return Card(
child: ListTile(
title: Text(title),
subtitle: Text(subtitle),
trailing: ElevatedButton(
child: const Text("Print"),
onPressed: () async {
try {
_dialogBuilder(context, (await method()).getLabel);
} on PlatformException catch (e) {
_dialogBuilder(context, "${e.code}\n\n${e.message ?? 'Empty message'}\n\n${e.details ?? 'Empty stacktrace'}", success: false);
} on MissingPluginException catch (e) {
_dialogBuilder(context, "Not implemented.\n\n${e.message ?? 'Empty message'}", success: false);
} catch (e) {
_dialogBuilder(context, e.toString(), success: false);
}
},
),
),
);
}
Future<void> _dialogBuilder(BuildContext context, String message, {bool success = true}) {
final ScrollController scrollbarController = ScrollController();
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
titlePadding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
contentPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 5),
actionsPadding: EdgeInsets.zero,
insetPadding: const EdgeInsets.all(20),
title: success
? Text('Printing success', style: TextStyle(color: Colors.green[700], fontWeight: FontWeight.bold))
: Text('Printing failure', style: TextStyle(color: Colors.red[700], fontWeight: FontWeight.bold)),
content: Scrollbar(
controller: scrollbarController,
thumbVisibility: true,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: SingleChildScrollView(
controller: scrollbarController, child: Text(message)),
)),
actions: <Widget>[
TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.labelLarge,
),
child: const Text('Close'),
onPressed: () {
Navigator.of(context).pop();
},
),
]);
},
);
}
Future<Uint8List> convertUiImageToUint8List(ui.Image image) async {
final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
if (byteData != null) {
return byteData.buffer.asUint8List();
}
throw "The image could not be converted to png";
}
}
更多关于Flutter打印机控制插件gpos720_printer的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter打印机控制插件gpos720_printer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用gpos720_printer
插件来控制Gpos720打印机的示例代码。这个插件通常用于在Flutter应用中实现蓝牙或USB连接的打印机控制功能。
首先,你需要在pubspec.yaml
文件中添加gpos720_printer
依赖:
dependencies:
flutter:
sdk: flutter
gpos720_printer: ^最新版本号 # 请替换为实际最新版本号
然后运行flutter pub get
来获取依赖。
接下来,在Flutter项目的Dart代码中,你可以使用以下示例来初始化打印机并发送打印命令:
import 'package:flutter/material.dart';
import 'package:gpos720_printer/gpos720_printer.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Gpos720 Printer Example'),
),
body: Center(
child: PrintButton(),
),
),
);
}
}
class PrintButton extends StatefulWidget {
@override
_PrintButtonState createState() => _PrintButtonState();
}
class _PrintButtonState extends State<PrintButton> {
String _printResult = '';
void _printText() async {
// 初始化打印机实例,这里假设是通过蓝牙连接
Gpos720Printer printer = Gpos720Printer();
// 连接到打印机(这里只是一个示例,具体连接逻辑可能需要根据实际情况调整)
// 假设这里已经成功连接
bool isConnected = await printer.connect("蓝牙设备地址"); // 替换为实际的蓝牙设备地址
if (isConnected) {
try {
// 打印文本
await printer.printText("Hello, Gpos720 Printer!\n");
await printer.printText("This is a test print.\n");
// 打印条码
await printer.printBarcode(barcodeData: "123456789012", barcodeType: BarcodeType.CODE128, width: 3, height: 100, position: BarcodePosition.CENTER);
// 切割纸张
await printer.cutPaper();
setState(() {
_printResult = 'Print Success!';
});
} catch (e) {
setState(() {
_printResult = 'Print Failed: ${e.message}';
});
} finally {
// 断开连接
await printer.disconnect();
}
} else {
setState(() {
_printResult = 'Failed to connect to printer.';
});
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
onPressed: _printText,
child: Text('Print'),
),
Text(_printResult),
],
);
}
}
注意事项:
-
连接逻辑:
- 示例中的
printer.connect("蓝牙设备地址")
是一个占位符。你需要根据实际的蓝牙连接逻辑进行实现。 - 如果打印机是通过USB连接,你可能需要使用不同的插件或方法来实现连接。
- 示例中的
-
权限:
- 确保你的应用在
AndroidManifest.xml
和Info.plist
中添加了必要的权限,比如蓝牙权限。
- 确保你的应用在
-
错误处理:
- 示例中包含了基本的错误处理逻辑,但在实际应用中,你可能需要更详细的错误处理。
-
插件版本:
- 确保你使用的
gpos720_printer
插件版本与你的Flutter SDK版本兼容。
- 确保你使用的
-
依赖项:
- 某些功能可能需要额外的依赖项或原生代码支持,请参考插件的官方文档进行配置。
这个示例提供了一个基本的框架,你可以根据自己的需求进行修改和扩展。