rishvi_zebra_scanner

pub.dev Flutter Android License

Banner

A Flutter plugin for Zebra Technologies barcode scanner devices. Uses the Zebra DataWedge API to deliver scan results to your Flutter app via a reactive stream.

Developed by Rishvi — Linnworks Certified Partners, specialising in warehouse management and Zebra hardware integrations.

Android only — designed for Zebra Android devices with DataWedge pre-installed.


Screenshots


About Zebra Devices

Zebra Technologies manufactures enterprise-grade Android mobile computers and barcode scanners used in warehouses, retail, logistics, and healthcare. Popular device families include:

Family Example Models Use Case
TC-series TC21, TC26, TC52, TC57, TC72, TC77 Warehouse / field mobility
MC-series MC2200, MC3300, MC9300 Retail / inventory
EC-series EC30, EC50, EC55 Enterprise compact
WT-series WT6300 Wearable / hands-free

All Zebra Android devices ship with DataWedge — Zebra's built-in barcode scanning middleware. This plugin communicates with DataWedge via broadcast intents, so no USB or Bluetooth pairing is needed.


How It Works

Zebra Device Hardware Trigger / Soft Trigger
        │
        ▼
  Zebra DataWedge (built-in middleware)
        │  broadcast intent
        ▼
  ZebraScannerPlugin (native Android)
        │  MethodChannel
        ▼
  ZebraScanner (Dart API)
        │  Stream<ScanResult>
        ▼
  Your Flutter App
  1. Your app calls ZebraScanner.initialize() — the plugin creates a DataWedge profile scoped to your app.
  2. When a barcode is scanned (hardware trigger or startScan()), DataWedge broadcasts the result.
  3. The plugin receives the broadcast and pushes a ScanResult onto scanResultStream.
  4. Your Flutter UI reacts to the stream.

Installation

1. Add the dependency

dependencies:
  rishvi_zebra_scanner: ^1.0.1

Then run:

flutter pub get

2. Fix manifest merge conflict (if needed)

If you see a build error about android:label, add tools:replace="android:label" to android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <application
        android:label="your_app_name"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        tools:replace="android:label">
        ...
    </application>
</manifest>

3. No other setup needed

  • The Zebra BarcodeScannerLibrary AAR is bundled inside the plugin — no manual Gradle changes.
  • The plugin self-registers via Flutter's v2 embedding — no MainActivity changes.
  • DataWedge profile ZebraFlutterProfile is created automatically on first initialize().

Quick Start

import 'package:rishvi_zebra_scanner/zebra_scanner_plugin.dart';

// 1. Initialize once (e.g. in initState)
await ZebraScanner.initialize();

// 2. Listen for scan results
ZebraScanner.scanResultStream.listen((ScanResult result) {
  print('Barcode : ${result.data}');
  print('Type    : ${result.type}');      // e.g. EAN-13, QR Code, Code 128
  print('Time    : ${result.timestamp}');
});

// 3. Trigger a soft scan (same as pressing the hardware trigger)
await ZebraScanner.startScan();

// 4. Stop scanning
await ZebraScanner.stopScan();

// 5. Clean up when done
ZebraScanner.dispose();

Complete Example

import 'package:flutter/material.dart';
import 'package:rishvi_zebra_scanner/zebra_scanner_plugin.dart';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({super.key});
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _barcode = 'Point scanner at a barcode';
  ScannerStatus _status = ScannerStatus.uninitialized;

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

  Future<void> _initScanner() async {
    await ZebraScanner.initialize();

    ZebraScanner.scanResultStream.listen((result) {
      setState(() => _barcode = result.data);
    });

    ZebraScanner.statusStream.listen((status) {
      setState(() => _status = status);
    });
  }

  @override
  Widget build(BuildContext context) {
    final isReady = _status == ScannerStatus.ready;
    final isScanning = _status == ScannerStatus.scanning;

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Zebra Scanner')),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(24),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                // Status indicator
                Chip(
                  label: Text(_status.name.toUpperCase()),
                  backgroundColor: isReady
                      ? Colors.green.shade100
                      : isScanning
                          ? Colors.blue.shade100
                          : Colors.grey.shade200,
                ),
                const SizedBox(height: 32),
                // Last scan result
                Text(
                  _barcode,
                  style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 48),
                // Controls
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    ElevatedButton.icon(
                      onPressed: isReady ? () => ZebraScanner.startScan() : null,
                      icon: const Icon(Icons.play_arrow),
                      label: const Text('Start'),
                    ),
                    const SizedBox(width: 16),
                    ElevatedButton.icon(
                      onPressed: isScanning ? () => ZebraScanner.stopScan() : null,
                      icon: const Icon(Icons.stop),
                      label: const Text('Stop'),
                      style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    ZebraScanner.dispose();
    super.dispose();
  }
}

API Reference

ZebraScanner

Method / Property Returns Description
initialize() Future<bool> Creates the DataWedge profile and registers the scan receiver. Call once before scanning.
startScan() Future<bool> Fires the soft scan trigger — same as pressing the hardware button.
stopScan() Future<bool> Stops the soft scan trigger.
dispose() void Closes streams and releases all resources.
scanResultStream Stream<ScanResult> Emits a ScanResult on every successful scan.
statusStream Stream<ScannerStatus> Emits ScannerStatus changes.
currentStatus ScannerStatus The current scanner status.
isInitialized bool Whether initialize() has been called successfully.

ScanResult

Property / Method Type Description
data String The decoded barcode value.
type String? Barcode symbology — e.g. EAN-13, QR Code, Code 128.
timestamp DateTime When the scan occurred.
source String? Scan source — e.g. barcode_scan.
copyWith(...) ScanResult Returns a copy with the specified fields replaced.

ScannerStatus

Value Description
uninitialized initialize() has not been called yet.
ready Scanner is idle and ready to scan.
scanning Scan trigger is active.
error An error occurred — check logcat.
disabled Scanner disabled by DataWedge policy.

Extension helpers (via ScannerStatusExtension):

Property Type Description
statusLabel String Human-readable status string (e.g. "ready").
isReady bool true when status is ready.
isScanning bool true when status is scanning.
isInitialized bool true when status is not uninitialized.

Requirements

Requirement Value
Flutter SDK ≥ 3.0.0
Dart SDK ≥ 3.0.0
Android API 23+ (Android 6.0+)
Device Zebra Android device with DataWedge

Supported Zebra Devices

Any Zebra Android device with DataWedge installed. Tested on:

  • TC52, TC57, TC72, TC77 (TC-series)
  • MC3300, MC9300 (MC-series)
  • EC50, EC55 (EC-series)

For the full Zebra device catalogue visit zebra.com.


Supported Barcode Symbologies

All symbologies supported by Zebra DataWedge:

1D 2D
Code 39, Code 128, Code 93 QR Code, Data Matrix
EAN-8, EAN-13 PDF417, Aztec
UPC-A, UPC-E MaxiCode, DotCode
Interleaved 2 of 5, Codabar MicroQR, MicroPDF

Troubleshooting

Scanner not initializing

  • Confirm DataWedge is installed: Settings > Apps > DataWedge
  • Check logcat: adb logcat | grep ZebraScanner

No scan results received

  • Ensure initialize() was called before startScan()
  • Open the DataWedge app and confirm ZebraFlutterProfile exists and is enabled
  • Confirm the profile's Intent output action is com.symbol.datawedge.api.RESULT

Build error: Manifest merger failed on android:label

Build error: Could not resolve com.zebra:barcode-scanner-library

  • Run flutter clean && flutter pub get and rebuild
  • The plugin injects its Maven repo automatically — no manual Gradle changes needed

Project Structure

lib/
├── zebra_scanner_plugin.dart     # Public API — import this
└── src/
    ├── zebra_scanner.dart        # ZebraScanner class
    └── models/
        ├── scan_result.dart      # ScanResult model
        └── scanner_status.dart   # ScannerStatus enum

android/
├── src/main/kotlin/com/zebra_scanner/
│   └── ZebraScannerPlugin.kt    # Native plugin (auto-registered, no MainActivity needed)
├── maven/                        # Bundled Zebra BarcodeScannerLibrary AAR
└── build.gradle.kts

example/                          # Example app — 4 working demos

License

MIT — see LICENSE


About

Zebra Technologies

Zebra Technologies is the world's leading manufacturer of enterprise barcode scanners, mobile computers, and label printers. Zebra devices run Android and ship with DataWedge — a powerful scanning middleware that handles all hardware scanner communication.

This plugin bridges Zebra's DataWedge API with Flutter, so you can build warehouse, retail, and logistics apps using Flutter on Zebra hardware.

Rishvi

Rishvi is a UK-based Linnworks Certified Partner specialising in:

  • Flutter plugin development for Zebra hardware
  • Linnworks custom integrations and scripting
  • Warehouse management and e-commerce IT solutions

🌐 rishvi.co.uk

Libraries

zebra_scanner_plugin
Zebra Scanner Plugin
zebra_scanner_service