Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Printer integrations for Flutter

License

Notifications You must be signed in to change notification settings

gogovan/flutter-label-printer

Repository files navigation

flutter-label-printer

Integrate printers with Flutter apps.

Supported Platforms

  • Android: Android 7.0+
  • iOS:

Supported Printers, OS and connections

  • Hanin (HPRT) CPCL Printers
    • Android and iOS are supported
    • Bluetooth connection only
    • HM-A300L is tested
  • Hanin (HPRT) TSPL Printers
    • Android and iOS are supported
    • Bluetooth or USB connection
      • USB connection is only supported on Android
    • N41BT is tested
  • A special "printer" that print to an image instead of a hardware printer.
    • Android and iOS are supported
    • No connection needed
    • Useful for:
      • Send the image to printer instead of using printer commands for consistency and working around missing printer features.
      • Print to an image for preliminary testing and verification during development.

Setup

General

  1. Set minSdkVersion in your Android app build.gradle to at least 24.
android {
    // ...
    defaultConfig {
        applicationId "com.example.flutter_label_printer_example"
        minSdkVersion 24
        // ...
    }
    // ...
}
  1. Depending on the connection technology your printer device requires, do the following steps:

Bluetooth

If your device requires Bluetooth connection, add Bluetooth permissions/notices as required by the OS.

Android

  1. Add the following to your main AndroidManifest.xml. See Android Developers) and this StackOverflow answer for more information about permission settings. If your app also requires Location permissions, remove maxSdkVersion attribute for those permissions.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.flutter_label_printer_example">

    <uses-feature android:name="android.hardware.bluetooth" android:required="true" />

    <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"
        android:usesPermissionFlags="neverForLocation" tools:targetApi="s" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
        android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
        android:maxSdkVersion="30" />
    <!-- ... -->
</manifest>

iOS

  1. Include usage description keys for Bluetooth into info.plist. iOS XCode Bluetooth permission instruction

USB

If your device requires USB connection, add USB permissions/notices as required by the OS.

Only Android is supported.

  1. Add the following to your main AndroidManifest.xml. See Android Developers for more information about permission settings.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.flutter_label_printer_example">

    <uses-feature android:name="android.hardware.usb.host" android:required="true" />

    <uses-permission android:name="hk.gogovan.flutter_label_printer.USB_PERMISSION" />
</manifest>

Usage

Connect your printer and basic printing

  1. Use an instance of a class implementing PrinterSearcherInterface to search for compatible printers.
    • All classes implementing PrinterSearcherInterface provides a search method returning a Stream<List<PrinterSearchResult>>. listen to the stream to list all the available devices.
    • Save the subscription returned when listening to the stream. Call cancel on the subscription when you are done searching for printers.
      • You should cancel the stream before connecting the printer. Devices may misbehave if you start connecting to printers while a search is ongoing.
BluetoothPrinterSearcher _searcher = BluetoothPrinterSearcher();
StreamSubscription<List<PrinterSearchResult>> subscription = _searcher.search().listen((event) {
// event contains a list of `PrinterSearchResult`s
});
  1. Pass one of the returned PrinterSearchResult and use it to connect to a printer through an instance of a class implementing PrinterInterface. Each instance of PrinterInterface represent a single printer. If you wish to connect multiple printers, use multiple instances of PrinterInterface.
HaninTSPLPrinter? _printer;
_printer = HaninTSPLPrinter(result);
await _printer?.connect();
  1. Use the instance of PrinterInterface that has connected to a printer to send printing commands. printTestPage may be used to print a testing page.
await _printer?.printTestPage();
  1. When you are done, call disconnect to disconnect the device from your app.
await _printer?.disconnect();

Using print templates

  1. Connect your printer (See above steps 1 - 2).
    • The retrieved PrinterInterface must also implement TemplatablePrinterInterface. If your PrinterInterface does not additionally implement TemplatablePrinterInterface, templates are not supported on that printer.
  2. Create a Template by either of the following methods:
    1. Create a List<Command> and add the Commands manually. Then create Template with final template = Template(commands). See the Template class doc for supported commands.
    2. Import a YAML file and instantiate a Template with final template = Template.fromYaml(yamlString). See below for YAML format.
  3. Create a TemplatePrinter and use it to print the template.
final printer = TemplatePrinter(printer, template);
await printer.printTemplate();

Template YAML

example/assets/template_schema.json is a JSON Schema for YAML format supported by Template constructor. Refer to JSON Schema webpage for details.

VSCode Integration

Start your YAML with

# yaml-language-server: $schema=template_schema.json

and edit your YAML with VSCode that has YAML plugin installed.

Template YAML root

There are two properties at root, size and commands, taking an object and an array of object respectively. Both are required.

For each command, a table is provided listing support for each printing SDK. Legends is as follows: :x: Not supported. These parameters will be ignored if sent to unsupported printers. :o: Supported. :star: Required.

Size command

The size object set the printing area. This command create a canvas for drawing items to be printed. Call print to perform the actual printing.

Parameter Description Possible Values Hanin CPCL Hanin TSPL Image
paperType Type of paper. continuous for receipt papers. label for label papers.
originX Starting horizontal position of the printing area. Number
originY Starting vertical position of the printing area. Number
width Width of the printing area. Number
height Height of the printing area. Number

Printing commands

Put all printing commands in the commands object. They will be sent to the printer in order.

Text

Command text adds text with styling.

Parameter Description Possible Values Hanin CPCL Hanin TSPL Image
text The text to print. Text
xPosition The x position of the text in the canvas. Number
yPosition The y position of the text in the canvas. Number
rotation Rotation of the text. Number ⭕ in 90 degrees increments ⭕ in 90 degrees increments
width Width of the text area. Number
height Height of the text area. Number
useImage Whether to use image to represent this text. [1] Boolean
style The style of the text. Accept an object.
style.bold Bold text and degree of boldness. Number
style.width Width of each character in text, as a multiplier. For image printer, the font size. Number
style.height Height of each character in text, as a multiplier. Number
style.align Alignment of text. [3] left, center or right.
style.font Font of text. [2]
style.reverse Reverse the color of the text. Boolean
style.padding Padding for the text. Particularly useful with style.reverse = true Number
style.lineSpacing Line spacing for text. [3] Number

[1] If the text command provided by the printer is insufficient, set useImage to true and flutter_label_printer will generate an image in the OS representing this text and send the image to the printer instead. While this is more flexible and can workaround missing features of the printer, it is also slower and may not be supported by printers that cannot print images. If this is used, attributes supported by the image printer, instead of your actual printer, is used.

[2] Either one of small, medium, large, vlarge, vvlarge, chinese, chineseLarge, ocrSmall, ocrLarge, square, triumvirate for Hanin TSPL and CPCL. For image printer, any font supported by the OS is supported.

[3] Should be used with width parameter.

Barcode

Command barcode prints a barcode.

Parameter Description Possible Values Hanin CPCL Hanin TSPL Image
type The barcode symbology of the barcode. Different for each printer. [1]
xPosition The x position of the barcode in the canvas. Number
yPosition The y position of the barcode in the canvas. Number
data Data encoded in the barcode. Text
height The height of the barcode. Number
barLineWidth The width of each narrow bar of the barcode. Number

[1] Supported barcodes:

Symbology Hanin CPCL Hanin TSPL Image
code39
code93
code128
code128m
codabar
ean2
ean5
ean8
ean13
ean128
msi
itf14
telepen
upca
upce

QR Code

Command qrcode prints a QR Code.

Parameter Description Possible Values Hanin CPCL Hanin TSPL Image
xPosition The x position of the barcode in the canvas. Number
yPosition The y position of the barcode in the canvas. Number
data Data encoded in the barcode. Text
unitSize The size of each unit (square) of the QR Code. Number

Line

Command line draws a line.

Parameter Description Possible Values Hanin CPCL Hanin TSPL Image
left x0 Number
top y0 Number
right x1 Number
bottom y1 Number
strokeWidth Stroke width of the line. Number

Rectangle

Command rectangle draws a rectangle.

Parameter Description Possible Values Hanin CPCL Hanin TSPL Image
left x0 Number
top y0 Number
right x1 Number
bottom y1 Number
strokeWidth Stroke width of the line. Number

Image

Command image prints an image.

Parameter Description Possible Values Hanin CPCL Hanin TSPL Image
path The file path to the image. Due to different paths in different OSes, avoid hardcoding a path. Use String Replacement (see below) instead. Text
xPosition The x position of the image in the canvas. Number
yPosition The y position of the image in the canvas. Number

Template String Replacement

Some strings in the template can be replaced with values retrieved at runtime. Pass the map of values to the replaceStrings parameter when constructing TemplatePrinter to enable:

final map = <String, String>{'name': 'John Doe', 'age': '23'};
final printer = TemplatePrinter(printer, template, replaceStrings: map);

To indicate replaceable strings in the template, wrap the key with double curly braces. e.g. The {{name}} in any strings in the template will be replaced by the value mapped to the key name in replaceStrings, i.e. John Doe in the above case. Keys are case-sensitive.

String replacement is supported on all fields that takes a String:

  • Text string
  • Barcode data
  • QR Code data
  • Image file path

Printer Hints

Some printers does not support all features available in the commands. flutter_label_printer provides a workaround method to support these features.

text_align

text_align allows text to be aligned according to the style.align parameter of the text command, even if the printer does not support it. Only Hanin TSPL is supported. Only support a single-line text with a monospaced font.

printer_hints:
  text_align:
    enabled: true # Set to true to enable this feature
    charWidth: 8 # The base character width of the font used, before any scaling introduced by `style.width` in the text command. This is used to calculate the width of the text.

Known Issues

Hanin CPCL

  • Currently in iOS it can only print very small images, otherwise the printer will be stuck and unable to do anything, and can only be fixed by restarting the printer.

Contributing

Adding a new printer

  1. Implement PrinterSearcherInterface for searching your printer.
  2. Implement PrinterSearchResult as the result object returned by your PrinterSearcherInterface.
  3. If your printer is intended to be used with the Templating system, implement PrinterTemplateInterface to support templating.
    1. Otherwise, Implement PrinterInterface for basic connectivity of your printer.
  4. When implementing the Templating system, avoid adding any printer-specific features into parameter classes. Convert parameter classes to a format for your printer in your printer instead.