zebra_emdk_plugin 0.4.2 copy "zebra_emdk_plugin: ^0.4.2" to clipboard
zebra_emdk_plugin: ^0.4.2 copied to clipboard

PlatformAndroid

A Flutter plugin for Zebra Android devices using the EMDK SDK.

zebra_emdk_plugin #

A Flutter plugin for Zebra Android devices that wraps the Zebra EMDK SDK.

Supports barcode scanning, scanner configuration (full decoder params), profile management (MX/StageNow), LED/beep/vibrate notifications, and OEM device info queries.

⚠️ Important: This plugin is Zebra-only. Always gate usage on await EmdkManager().isSupported() — it returns false on non-Zebra devices (and the plugin stays loaded without crashing).


Features #

Feature Description
EMDK Manager Initialize the EMDK service and listen for open/close events
Barcode Manager Enumerate/filter scanners, init by friendly name, scanner config, read control, scan data & status events
Notification Manager Enumerate/filter notification devices, trigger LED, beep, and vibrate notifications
Profile Manager Apply MX profiles asynchronously with a serialised queue, query OEM content-provider URIs, map hardware keys
Key Event Manager Listen to physical button presses (P-buttons, triggers, volume keys, etc.) via MX KeyMappingMgr

Setup #

1. Add the Zebra EMDK Maven repository #

In your app's android/build.gradle.kts, add:

allprojects {
    repositories {
        google()
        mavenCentral()
        maven {
            url = uri("https://zebratech.jfrog.io/artifactory/EMDK-Android/")
        }
    }
}

2. Add the dependency #

dependencies:
  zebra_emdk_plugin: ^0.4.1

3. Add the EMDK compile-only dependency (required) #

EMDK is a device-provided system library — you compile against it but it is never packaged. Flutter's generated GeneratedPluginRegistrant instantiates this plugin (which references EMDK types), so your app must have EMDK on its compile classpath. In your app's android/app/build.gradle.kts:

dependencies {
    compileOnly("com.symbol:emdk:11.0.134")
}

Without this, the app fails to build with class file for com.symbol.emdk.EMDKManager not found.

4. Update AndroidManifest.xml #

Add the following to your app's android/app/src/main/AndroidManifest.xml:

<manifest ...>
    <!-- Required EMDK permissions -->
    <uses-permission android:name="com.symbol.emdk.permission.EMDK" />
    <uses-permission android:name="com.zebra.provider.READ" />

    <!-- Required for Android 11+ package visibility -->
    <queries>
        <package android:name="com.symbol.emdk.emdkservice" />
        <package android:name="com.zebra.zebracontentprovider" />
        <provider android:authorities="oem_info" />
    </queries>

    <application ...>
        <uses-library android:name="com.symbol.emdk" android:required="false" />
        ...
    </application>
</manifest>

Usage #

Initialize EMDK and scan a barcode #

import 'package:zebra_emdk_plugin/zebra_emdk_plugin.dart';

final emdk = EmdkManager();

// 1. Bail out cleanly on non-Zebra devices.
if (!await emdk.isSupported()) return;

// 2. Start listening for the open event before initializing.
emdk.onOpened.listen((_) async {
  final bm = emdk.barcodeManager;

  // 3. Get all connected scanners and init the first one.
  final scanners = await bm.getConnectedScanners();
  if (scanners.isNotEmpty) {
    await bm.initScanner(scanners.first.friendlyName!);
  }

  // 4. Listen for scan data and start reading.
  bm.onData.listen((collection) {
    final barcode = collection.scanData?.firstOrNull?.data;
    print('Scanned: $barcode');
  });

  await bm.enableRead();
});

// 5. Request the EMDK Manager from the OS.
await emdk.initialize();

Trigger a notification (beep + LED + vibrate) #

final nm = emdk.notificationManager;

// Init the first connected notification device
final devices = await nm.getConnectedDevices();
if (devices.isNotEmpty) {
  await nm.initDevice(devices.first.friendlyName!);
}

await nm.notify(
  NotificationCommand(
    beep: NotificationBeepParams(pattern: [
      NotificationBeep(time: 100, frequency: 2500),
    ]),
    led: NotificationLEDParams(
      color: 0x00FF00, onTime: 200, offTime: 200, repeatCount: 3,
    ),
    vibrate: NotificationVibrateParams(time: 500),
  ),
);

Apply an MX profile #

final pm = emdk.profileManager;

pm.onData.listen((result) {
  print('Profile result: ${result?.result?.statusCode?.value}');
});

// Pass only the inner <characteristic> block(s) — the plugin wraps them automatically
pm.processProfileAsync('''
  <characteristic type="PowerMgr">
    <parm name="ResetAction" value="1"/>
  </characteristic>
''');

Built-in MX profiles & convenience methods #

Common device-control operations are convenience methods on ProfileManager (the MxCommands extension) — no hand-written XML required:

final pm = emdk.profileManager;

// Paired enable/disable operations are setX...State(bool) setters:
pm.setBluetoothState(true);
pm.setNfcState(false);
pm.setBluetoothPairing(true);
pm.setNfcPairing(false);

// Scanner control, system-app enable/disable, and Zebra Enterprise Keyboard:
pm.resetScanner(); // also: disconnectScanner() / unpairScanner() / locateScanner()
pm.setSystemAppState(package: 'com.google.android.inputmethod.latin', enabled: false);
pm.enableEnterpriseKeyboard(currentLocale: 'pt_PT', showVirtualKeyboard: true);

// Individual UI / display / device-admin setters (true = enabled/visible, false = disabled/hidden):
pm.setStatusBarState(false);
pm.setNavigationBarState(false);
pm.setNotificationPullDownState(false);
pm.setRecentAppButtonState(false);
pm.setLargeScreenTaskbarState(false);
pm.setScreenBrightness(80);
pm.setScreenTimeout(600); // 65535 ≈ never
pm.setAutoRotateState(true);
pm.setScreenLockType(5);

// Launch an activity (implicit via action, or explicit via package/class):
pm.startActivity(actionName: 'android.settings.SETTINGS');
pm.startActivity(package: 'com.acme.app', className: 'com.acme.app.MainActivity');

// Destructive ops are exposed as methods too — guard them behind your own confirmation UI:
pm.reboot();
// pm.fullDeviceWipe(); // erases ALL data — irreversible

Query OEM device info #

Each secured OEMinfo URI needs an AccessMgr permission grant before it can be read. Request the permission once (fire-and-forget; result on onData), then read it with the matching getter:

final pm = emdk.profileManager;

// 1. Request the permissions you need (e.g. once after EMDK is ready).
pm.requestBluetoothMacPermission();
pm.requestBuildSerialPermission();
pm.requestProductModelPermission();
pm.requestWifiMacPermission();
pm.requestPeripheralBatteryInfoPermission();

// 2. Read the values with the named getters.
final btMac   = await pm.getBluetoothMac();
final serial  = await pm.getBuildSerial();
final model   = await pm.getProductModel();
final wifiMac = await pm.getWifiMac();
final battery = await pm.getPeripheralBatteryInfo();

print('BT: $btMac | Serial: $serial | Model: $model');

// Convenience: Zebra Bluetooth pairing barcode derived from the BT MAC.
final pairingCode = await pm.getPairingCode();

// Need a URI that has no named helper? Use the raw calls directly:
// pm.requestServicePermission('content://oem_info/oem.zebra.secure/bt_mac');
// final raw = await pm.resolveCursorUri('content://oem_info/oem.zebra.secure/bt_mac');

Get scanner configuration #

final config = await emdk.barcodeManager.getConfig();

// Modify and apply
final updated = ScannerConfig(
  ngSimulScanParams: NGSimulScanParams(
    ngSimulScanMode: NGSimulScanMode.multiBarcode,
    multiBarcodeParams: NGSimulScanMultiBarcodeParams(barcodeCount: 2),
  ),
);
await emdk.barcodeManager.setConfig(updated);

API Reference #

EmdkManager #

Member Description
isSupported() true only on a Zebra device with EMDK present; safe (never throws) on any device
initialize() Requests the EMDK Manager from the OS
dispose() Releases all EMDK resources
barcodeManager Lazy getter for BarcodeManager
notificationManager Lazy getter for NotificationManager
profileManager Lazy getter for ProfileManager
keyEventManager Lazy getter for KeyEventManager
onOpened Stream fired when EMDK is ready
onClosed Stream fired when EMDK is closed

BarcodeManager #

Member Description
getSupportedScanners() All known scanners (connected or not)
getConnectedScanners() Currently-connected scanners only
initScanner(friendlyName) Initializes a scanner by friendly name
deinitScanner() Releases the active scanner
getScannerInfo() Info about the active scanner
enableRead() Arms the scanner to read
disableRead() Cancels a pending read
getConfig() Returns the current ScannerConfig
setConfig(config) Applies a ScannerConfig
onConnectionChange Stream of scanner connect/disconnect events
onStatus Stream of scanner state changes
onData Stream of ScanDataCollection scan results

NotificationManager #

Member Description
getSupportedDevices() All known notification devices
getConnectedDevices() Currently-connected notification devices only
initDevice(friendlyName) Enables a notification device by friendly name
deinitDevice() Disables the active notification device
getDeviceInfo() Info about the active notification device
notify(command) Triggers a NotificationCommand (LED/Beep/Vibrate)

ProfileManager #

Member Description
processProfileAsync(characteristics) Queues an MX XML characteristics block for processing
requestServicePermission(uri) Requests an AccessMgr content-provider permission
request{BluetoothMac,BuildSerial,ProductModel,WifiMac,PeripheralBatteryInfo}Permission() Named requestServicePermission helpers, one per OEMinfo URI; pair with the matching get…() reader
resolveCursorUri(uri) Reads a single-value Zebra OEMinfo URI
get{BluetoothMac,BuildSerial,ProductModel,WifiMac,PeripheralBatteryInfo}() Named resolveCursorUri readers for the common OEMinfo URIs
getPairingCode() Zebra Bluetooth pairing barcode payload derived from the BT MAC
addKeyListener(key) Maps a KeyIdentifier key to send a KEY_DOWN_EVENT broadcast
resetAllKeyMappings() Resets all key mappings to factory defaults
onData Stream of ProfileResultData results

KeyEventManager #

Member Description
onKeyDown Stream of KeyIdentifier? emitted on every mapped key press

KeyIdentifier #

Enum with ~100 named Zebra hardware keys. Common values:

Value Key
KeyIdentifier.p1p6 Programmable P-buttons
KeyIdentifier.scan Scanner trigger
KeyIdentifier.leftTrigger1, rightTrigger1 Side trigger buttons
KeyIdentifier.volumeUp, volumeDown Volume keys
KeyIdentifier.f1f12 Function keys
KeyIdentifier.enter, back, home System/navigation keys

See KeyIdentifier in key_identifiers.dart for the full list.


Listen to hardware key presses #

// 1. Map the keys you want to listen to (call after EMDK is ready)
emdk.profileManager.resetAllKeyMappings(); // optional: start clean
emdk.profileManager.addKeyListener(KeyIdentifier.p1);
emdk.profileManager.addKeyListener(KeyIdentifier.scan);

// 2. Subscribe to key-down events
emdk.keyEventManager.onKeyDown.listen((key) {
  if (key == KeyIdentifier.p1) print('P1 pressed');
  if (key == KeyIdentifier.scan) print('Scan pressed');
});

Error Handling #

Manager calls throw a typed Dart exception when the native EMDK reports a known error:

Dart exception When thrown
ScannerException A barcode scanner operation fails (e.g. initScanner, enableRead, setConfig)
NotificationException A notification device operation fails (e.g. initDevice, notify)
EMDKException The EMDK manager fails to open or a feature instance cannot be acquired
PlatformException Any unexpected native exception not mapped to an EMDK type
try {
  await emdk.barcodeManager.initScanner(friendlyName);
} on ScannerException catch (e) {
  print('Scanner error: ${e.result.value} — ${e.message}');
} on PlatformException catch (e) {
  print('Native error: ${e.code} — ${e.message}');
}

Platform Support #

Platform Supported
Android (Zebra devices)
iOS
Web
Windows / macOS / Linux

Minimum Android SDK: 24 (Android 7.0)


EMDK Version #

Built against EMDK 11.0.134 — the latest version published to the Zebra EMDK Maven repository.


License #

MIT — see LICENSE.

1
likes
155
points
248
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for Zebra Android devices using the EMDK SDK.

Repository (GitHub)
View/report issues

Topics

#zebra #emdk #barcode #scanner #android

License

MIT (license)

Dependencies

flutter, meta, plugin_platform_interface

More

Packages that depend on zebra_emdk_plugin

Packages that implement zebra_emdk_plugin