Skip to main content

sprint_flutter 0.1.6 copy "sprint_flutter: ^0.1.6" to clipboard
sprint_flutter: ^0.1.6 copied to clipboard

sPrint for Flutter: Superroute's printing SDK. Find network, USB and Bluetooth printers, detect their language, print labels, PDF, HTML, images and raw bytes, and run a Superroute print node, on Andro [...]

sprint_flutter #

sPrint for Flutter: Superroute's printing SDK on Android, iOS, macOS, Windows and Linux. Find network, USB and Bluetooth printers, detect their command language (ZPL, TSPL, ESC/POS, CPCL and the vendor dialects), print labels, PDF, HTML, images and raw bytes, share printers with other devices on the LAN, and turn the device into a Superroute print node — with the same engine as every other sPrint platform.

import 'package:sprint_flutter/sprint_flutter.dart';

final printers = await PrinterRegistry.open('${dir.path}/printers.json');
await printers.save(const TargetPrinter(name: 'Labels', host: '192.168.1.40', language: Languages.zpl));
final result = await printers.print(PrintJob(type: JobTypes.label, label: LabelJob.parse(labelJson)));

final found = await Discovery.scanNetwork();

final node = await PrintNode.create(printers, state: savedState);
node.events.listen((e) { if (e is NodeStateEvent) save(e.state.json); });
await node.pair('K2M9XY'); // the code from the Print Nodes page
await node.start();

Platform notes:

  • Android: the plugin uses the sPrint Android library from https://goodneo-solutions.github.io/sprint-releases/maven (added to your app's repositories by the plugin). Ask for Bluetooth / USB permissions in your app.
  • iOS / macOS: Swift Package Manager is required (flutter config --enable-swift-package-manager); iOS 15+, macOS 13+. Add NSBluetoothAlwaysUsageDescription (Bluetooth LE printers) and NSLocalNetworkUsageDescription (network printers) to Info.plist.
  • Windows / Linux: the build downloads the sPrint C library of this version from the sprint-releases Release (checked against its SHA256SUMS.txt).

Licensed under the Superroute SDK License.

What a host app adds to the print node (docs/NODE-HOOKS.md in the sPrint repository): commands it answers, the commands poll, the server's printer settings (applied by the core: a locked language is refused by PrinterRegistry.save, the default paper fills a job that names none), languages chosen here, extra heartbeat fields, the jobs in flight and the ZPL media query.

final node = await PrintNode.create(printers, state: savedState,
    commandsEvery: const Duration(seconds: 15),
    onCommand: (cmd) async => switch (cmd.action) {   // null: the node answers
          'connectivity_test' => CommandAnswer(output: await checkServer()),
          _ => null,
        });
node.events.listen((e) {
  if (e is NodeSettingsEvent) showLocks(e.settings);      // languages, locks, paper
  if (e is NodePrintingEvent) showPrinting(e.printing);   // started / ended, cloud or peer
});
await node.setPrinterFields('Labels', {'language_kept': {'language': 'zpl', 'since': since, 'jobs': 12}});
final refused = await node.pushLanguages({'Labels': 'zpl'});
await node.pushLanguages({'Labels': 'tspl'}, corrections: ['Labels']); // the printer's own answer
final media = await SPrint.queryZplMedia(zebra);           // dpi, widthMm, lengthMm or null

The Android part of the plugin no longer applies the Kotlin Gradle Plugin itself (Flutter's built-in Kotlin guidance): with built-in Kotlin AGP compiles it, otherwise the Flutter Gradle Plugin applies Kotlin to it.

LAN peer printing #

Two devices on the same network print to each other's shared printers with no server: the peer-direct protocol 1.1.0 the SuperPrinter apps speak (mDNS _superprinter._tcp, HTTPS on port 17778 with a self-signed certificate keyed to the device's Ed25519 identity and pinned by fingerprint). Sharing is off by default, nothing is shared until named, and every new peer is approved by the owner unless the mode says otherwise.

Sharing this device's printers #

final host = await PeerHost.create(printers, name: 'Front desk', state: saved); // saved: null the first time
host.events.listen((e) {
  switch (e) {
    case PeerStateEvent(:final state): save(state.toJson()); // the seed, mode, password hash, shared printers, trust list: store privately
    case PeerPendingEvent(:final pending): ask(pending);     // then host.decide(pending.id, approve: true / false)
    case PeerConnectedEvent(:final peer): print('${peer.name ?? peer.fingerprint} connected');
    case PeerDisconnectedEvent(:final peer, :final reason): print('${peer?.fingerprint} left: $reason');
    default:
  }
});
await host.setShared(['Labels']);        // registry printers, one by one
await host.setMode(PeerModes.approval);  // or open, or password with host.setPassword(…)
await host.setDiscoverable(true);        // advertised over mDNS
await host.start();
// host.pending(), host.sessions(), host.revoke(fingerprint), host.status(), host.stop(), host.dispose()

The host keeps no files: store the PeerHostState of every PeerStateEvent and hand it back next time (its seed is the device's identity, so peers that trust it keep trusting it). Jobs a peer sends print through the registry exactly as local jobs, on shared printers only.

Printing to another device #

final me = await PeerIdentity.fromSeed(storedSeed);  // or PeerIdentity.create(), then store me.seed
final found = await Peers.browse(timeout: const Duration(seconds: 3)); // name, fingerprint, mode, addr
final peer = found.first;
final session = await Peers.connect(peer.addr, me, fingerprint: peer.fingerprint, note: 'Warehouse tablet');
session.events.listen((e) { if (e is PeerEndedEvent) print('ended: ${e.reason}'); }); // revoked, expired, unreachable
if ((await session.status()).isPending) await session.waitApproval(); // the owner decides (two minutes at most)
final shared = await session.printers();             // only what the owner shares
final result = await session.print(PrintJob(type: JobTypes.label, label: label), printer: shared.first.name);
await printers.attachPeer(session);                  // targets "peer:<fingerprint>/<printer>" (session.targetNames())
await session.dispose();                             // disconnects

A refusal throws SPrintException with its code (BAD_PASSWORD, THROTTLED, …; denied / timeout from waitApproval). Without a fingerprint the first certificate seen is trusted: show session.fingerprint so the user can check it.

Platform requirements #

  • Android: mDNS goes through NsdManager, registered with the core when the plugin starts (Go cannot list interfaces or join multicast groups on Android 11+). The library's manifest brings INTERNET, ACCESS_NETWORK_STATE and CHANGE_WIFI_MULTICAST_STATE. The process must stay alive while sharing (a foreground service).

  • iOS: mDNS goes through Bonjour, registered with the core when the plugin starts. Info.plist needs these keys, or browsing finds nothing and the host reports advertiseError in its status:

    <key>NSLocalNetworkUsageDescription</key>
    <string>Finds and shares printers with other devices on this network.</string>
    <key>NSBonjourServices</key>
    <array>
        <string>_superprinter._tcp</string>
    </array>
    

    iOS asks the user for local-network access the first time; until it is granted, browsing answers nothing.

  • macOS: the core browses and advertises mDNS itself. A sandboxed app needs the com.apple.security.network.client and com.apple.security.network.server entitlements, and on macOS 15 and later the same NSLocalNetworkUsageDescription key.

  • Windows / Linux: the core browses and advertises mDNS itself; allow the app through the firewall on port 17778 (or the port you choose) to share.

Coming from superprinter_flutter #

import 'package:sprint_flutter/superprinter_compat.dart'; gives the same LocalPrinting, PrinterRegistry, TargetPrinter, … calls (and the printers already saved). See docs/MIGRATING-FROM-SUPERPRINTER-FLUTTER.md in the sPrint repository for the call-by-call mapping and the behaviour differences.

0
likes
140
points
0
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

sPrint for Flutter: Superroute's printing SDK. Find network, USB and Bluetooth printers, detect their language, print labels, PDF, HTML, images and raw bytes, and run a Superroute print node, on Android, iOS, macOS, Windows and Linux.

Topics

#printing #label #thermal #zpl #escpos

License

unknown (license)

Dependencies

ffi, flutter, shared_preferences

More

Packages that depend on sprint_flutter

Packages that implement sprint_flutter