zebra_emdk_plugin 0.4.2
zebra_emdk_plugin: ^0.4.2 copied to clipboard
A Flutter plugin for Zebra Android devices using the EMDK SDK.
0.4.1 #
New
-
Named permission-request helpers on
ProfileManager, one per OEMinfo URI inContentUris— thin wrappers overrequestServicePermission(uri)that pair with the existingget…()readers:requestBluetoothMacPermission()(pairs withgetBluetoothMac())requestBuildSerialPermission()(pairs withgetBuildSerial())requestProductModelPermission()(pairs withgetProductModel())requestWifiMacPermission()(pairs withgetWifiMac())requestPeripheralBatteryInfoPermission()(pairs withgetPeripheralBatteryInfo())
All are fire-and-forget (result on
onData). Call the matchingrequest…Permission()once before reading a secured URI, so the AccessMgr grant is in place before the firstget…().
0.4.0 #
Architecture
- Pigeon transport. The Dart↔Kotlin bridge was migrated from hand-rolled
MethodChannel/EventChannelto type-safe Pigeon 27.x (@HostApi+@EventChannelApi). Public API names (EmdkManager,BarcodeManager,NotificationManager,ProfileManager,KeyEventManager) are unchanged. - Pure Zebra plugin. This package is strictly a Zebra EMDK wrapper. Any cross-SDK neutral interface / device routing belongs in a separate aggregator package.
New
-
EmdkManager.isSupported()— returnsfalse(never throws) on non-Zebra devices. -
ZebraEmdkLog.enabled— opt-in diagnostic logging (off by default; never logs scan data). -
MxCommandsextension onProfileManager— ready-made MX device-control commands, no hand-written XML required:- paired enable/disable as
setX(bool)setters:setBluetoothState,setNfcState,setBluetoothPairing,setNfcPairing; - scanner control:
resetScanner,disconnectScanner,unpairScanner,locateScanner; setSystemAppState({package, enabled})(AppMgr system-app enable/disable);enableEnterpriseKeyboard({currentLocale, showVirtualKeyboard});startActivity({actionName, package, className});- destructive
reboot()/fullDeviceWipe()(guard behind your own confirmation UI); - individual UiMgr/DisplayMgr/DevAdmin setters (one option per call, replacing all-or-nothing
restriction blobs):
setStatusBarState,setNavigationBarState,setNotificationPullDownState,setRecentAppButtonState,setLargeScreenTaskbarState,setBluetoothPairingPopupState(bool),setScreenBrightness,setScreenTimeout(int),setAutoRotateState(bool),setScreenLockType(int).
The underlying XML builders live in
MxProfiles(bluetoothState(bool),statusBarState(bool),screenBrightness(int),systemAppState({package, enabled}), …). - paired enable/disable as
Crash-safety / correctness
- The native layer never crashes the host: every host-API call is wrapped in
catch (Throwable)(soNoClassDefFoundErroron a non-Zebra device becomes a typed Dart error), all EMDK events are marshalled to the Android main thread, and EMDK listeners load lazily. - Scanner/notification teardown corrected to Zebra's documented order
(
cancelRead → removeListeners → disable → release, each best-effort). - Plugin manifest declares
<uses-library android:required="false">so host apps install on non-Zebra devices; consumer R8 rules (-dontwarn com.symbol.emdk.**) ship viaconsumerProguardFiles.
Breaking / migration
- List getters (
getConnectedScanners,getSupportedScanners,getConnectedDevices,getSupportedDevices) now return non-nullLists (empty instead ofnull). - Host app must add the Zebra EMDK Maven repo +
compileOnly("com.symbol:emdk:11.0.134")toandroid/app/build.gradle.kts(see README §3).
0.3.1 #
Improvements
- Migrate to Built-in Kotlin: Removed the explicit Kotlin Gradle Plugin (KGP) application from
android/build.gradle.kts. The Kotlin plugin is now provided automatically by the Flutter Gradle plugin on Flutter 3.44+ / AGP 9.kotlinOptions { jvmTarget = ... }was replaced with the top-levelkotlin { compilerOptions { jvmTarget = JvmTarget.JVM_17 } }block. This silences theWARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP)produced by recent Flutter versions.
Breaking changes
- Minimum supported Flutter bumped to 3.44.0 and Dart to 3.12.0.
Example app
- Split the
enablePairing/disablePairinghelpers intoenableBtPairing/disableBtPairing(Bluetooth,BluetoothMgr.AllowPairing) andenableNfcPairing/disableNfcPairing(NFC tap-to-pair,NfcMgr.EnableTPP). Both are now toggled together when a scanner connects/disconnects.
0.3.0 #
New features
-
Hardware key listener (
KeyEventManager/KeyEventHandler): Listen to physical button presses on Zebra devices via the MXKeyMappingMgrCSP.EmdkManager.keyEventManager— new lazy getter that returns theKeyEventManager.KeyEventManager.onKeyDown— stream that emits aKeyIdentifierwhenever a mapped key is pressed.ProfileManager.addKeyListener(KeyIdentifier)— maps a key to send aKEY_DOWN_EVENTbroadcast to the app (fire-and-forget, result ononData).ProfileManager.resetAllKeyMappings()— resets all key mappings to factory defaults (fire-and-forget).KeyIdentifier— new enum covering all ~100 Zebra MX key identifiers (number keys, alpha keys, function keys, P-buttons, trigger buttons, volume, navigation, and device-specific keys) with exact MX XML string values.
-
onDetachedFromEnginecleanup:ZebraEmdkPlugin.onDetachedFromEnginenow callsemdkManagerHandler.cleanup(), which disposes theKeyEventHandlerbroadcast receiver and releases the EMDK manager. This preventsServiceConnectionLeakedandIntentReceiverLeakedlogcat errors on hot restart or Activity destroy. -
Application context fix:
EmdkManagerHandler.initializeHandlernow callscontext.applicationContextinstead of using the raw Activity context, preventing EMDK service binding and BroadcastReceiver from being tied to the Activity lifecycle.
Improvements
-
Profile queue deadlock fix (
ProfileManagerHandler):executeNextProfilenow captures the nextpendingProfilesentry and sets the lock state insidesynchronized, then callsprocessProfileAsyncoutside the lock. Previously, if the EMDK callback fired on the same thread, it could deadlock on the same monitor. -
Profile
onDataordering fix: TheonDataevent is now fired before the completed profile is removed from the queue and the next one is dispatched. This guarantees that listeners always receive the result of the profile that just ran before the next profile begins.
0.2.1 #
Improvements
-
Native error propagation: All four Kotlin handler
onMethodCallblocks are now wrapped in a top-leveltry/catch. Unhandled EMDK exceptions (ScannerException,NotificationException) and unexpected Java/Kotlin exceptions are no longer swallowed silently — they are forwarded to the Dart side as typedPlatformExceptionerrors with structuredcodeanddetails. -
Typed Dart exceptions from
ZepServiceBase.invokeMethod: Instead of returningnullon failure,invokeMethodnow decodes the incomingPlatformExceptioncode and rethrows the matching Dart exception:Native exception codeDart exception ScannerExceptionSCANNER_EXCEPTIONScannerExceptionNotificationExceptionNOTIFICATION_EXCEPTIONNotificationExceptionEMDK feature failure EMDK_EXCEPTIONEMDKExceptionAny other exception NATIVE_EXCEPTIONPlatformException -
New exception classes:
EMDKException— thrown when the EMDK manager fails to open or a feature instance cannot be acquired. Carries an optionalEMDKResultspayload.NotificationException— thrown when a notification device operation fails (enable, notify). Carries aNotificationResultsresult code.
-
EventChannel error guard:
ZepServiceBasenow attaches a.handleError()handler to the raw event stream so unhandled EventChannel errors are logged instead of crashing the stream. -
initScanner/initDevicecleanup on failure: In the exampleEmdkwrapper, calls toinitScannerandinitDevicenow catch exceptions and calldeinitScanner/deinitDeviceto ensure the native side is always left in a clean state.
0.2.0 #
Breaking changes
-
Android — modular handler architecture: The monolithic
ZebraEmdkPlugin.kt(single class implementing all EMDK features) has been replaced with dedicated handler classes, each owning its own MethodChannel and EventChannel:EmdkManagerHandler— EMDK lifecycleBarcodeManagerHandler— scanner discovery, read control, config, and data eventsNotificationManagerHandler— notification device discovery and triggeringProfileManagerHandler— MX profile processing and OEM content-provider queriesExtensions.kt— shared Kotlin helpersZebraEmdkPlugin.ktis now a thin entry-point that delegates toEmdkManagerHandler
-
Dart — service layer renamed and restructured: All service files have been renamed and the channel naming convention changed:
emdk_manager_service.dart→emdk_manager.dart(classEmdkManagerService→EmdkManager)barcode_manager_service.dart→barcode_manager.dart(classBarcodeManagerService→BarcodeManager)notification_manager_service.dart→notification_manager.dart(classNotificationManagerService→NotificationManager)profile_manager_service.dart→profile_manager.dart(classProfileManagerService→ProfileManager)scanner_service.dartremoved — scanner operations (enableRead,disableRead,initScanner,deinitScanner,getConfig,setConfig,onStatus,onData) now live directly onBarcodeManagernotification_device_service.dartremoved — notification device operations (initDevice,deinitDevice,notify,getDeviceInfo) now live directly onNotificationManageroem_info_service.dartremoved — OEM queries now exposed throughProfileManager.resolveCursorUri(uri)andProfileManager.requestServicePermission(uri)platform_service_base.dartreplaced byzep_service_base.dart(ZepServiceBase) with new channel naming:zep/methods/<handler>andzep/events/<handler>
-
BarcodeManagerAPI changes:setScannerTypeByFriendlyName(name)→initScanner(name)dispose()removed — usedeinitScanner()- New method:
getConnectedScanners()— returns only currently-connected scanners onStatusandonDatastreams moved fromScannerServicetoBarcodeManager
-
NotificationManagerAPI changes:setNotificationDeviceByFriendlyName(name)→initDevice(name)dispose()removed — usedeinitDevice()getNotificationDeviceInfo()→getDeviceInfo()- New method:
getConnectedDevices()— returns only currently-connected notification devices notify(command)moved fromNotificationDeviceServicetoNotificationManager
-
ProfileManagerAPI changes:processProfileAsync(profileName, xmlData)→processProfileAsync(characteristics)— takes the XML characteristics string directly; the profile wrapper and name are now generated internally on the native side- New method:
requestServicePermission(uri)— explicitly request access to a content-provider URI - New method:
resolveCursorUri(uri)— query any Zebra OEMinfo content-provider URI directly
New features
- Profile processing queue (
ProfileManagerHandler): MX profiles are now processed through a serialisedLinkedHashMapqueue. ConcurrentprocessProfileAsynccalls no longer race — each profile waits for the previous one to finish before being submitted toprocessProfileAsyncon the native EMDK.
Example app
- Renamed from
ZebraEMDK/zebra_emdk.darttoEmdk/emdk.dart - EMDK now auto-initialises in
initState()instead of requiring a manual button press - Dark-mode UI redesign with Material 3
- Dispose is now async (
_disposeEmdk) onProfileDatastream is now listened to in the examplecontent_uris.dartandmx_profiles.dartcorrectly moved from the plugin package into the example app
0.1.0 #
- Initial release of
zebra_emdk_plugin. - EMDK Manager: initialize and listen for open/close events.
- Barcode Manager: enumerate supported scanners, select scanner by friendly name, listen for connection changes.
- Scanner: initialize, enable/disable read, get/set configuration (with full decoder params), listen for scan data and status events.
- Notification Manager: enumerate supported notification devices, select device by friendly name.
- Notification Device: initialize, trigger LED, beep, and vibrate notifications.
- Profile Manager: initialize, apply profiles asynchronously via
processProfile, and listen for results. - OEM Info: read Bluetooth MAC, serial number, product model, Wi-Fi MAC, peripheral battery info, and peripheral device info.