flutter_zxing 3.0.1
flutter_zxing: ^3.0.1 copied to clipboard
A barcode scanner and generator natively in Flutter with Dart FFI based on ZXing.
Changelog #
3.0.1 #
- Fixed
pod installfailing with "undefined methodpod_target_xcconfig' for an instance of Pod::Specification" while loading the iOS and macOS podspecs.Pod::Specificationonly defines a writer forpod_target_xcconfig, so reading the value back to merge theNDEBUGsettings into it raised aNoMethodError`. All the settings are now assigned in a single hash. This affected 2.4.0 and 3.0.0; apps that build through Swift Package Manager were never affected. - Android builds no longer write a
NT_GNU_BUILD_IDnote intolibflutter_zxing.so. The note is derived from the build environment, which kept the resulting APK from being byte-for-byte reproducible — something F-Droid now requires. Note that Firebase Crashlytics for NDK relies on that note to symbolicate native crashes, so a crash inside this library will now be reported without symbols. Thanks to @quandangv (#247).
3.0.0 #
Updates the bundled zxing-cpp from
v2.3.0 to v3.1.1 — 633 upstream commits, including a major release that
reworked the format API. Format, DecodeParams, EncodeParams and Code are
unchanged on the Dart side; the two behaviour changes below are the only ones
that can affect existing code.
Breaking #
- UPC-A and UPC-E now decode to 13 digits. ISO/IEC 15420 requires the
]E0content to be a 13-digit number, so a UPC-A that used to read as"725272730706"now reads as"0725272730706", and a UPC-E that used to read as its 8-digit form is expanded to the equivalent EAN-13.Code.formatstill reportsFormat.upca/Format.upce. Strip the leading zero if you need the old form. - Asking for a symbology now also matches its variants. zxing-cpp 3.x splits
formats into symbologies and variants, and a request for the symbology covers
all of them. In practice:
Format.qrCodealso detects Micro QR and rMQR symbols (reported asFormat.microQRCode/Format.rmqrCode), andFormat.pdf417also detects MicroPDF417 (reported asFormat.microPdf417). Filter onCode.formatif you need to accept only one of them.
Added #
- Four formats that zxing-cpp can detect but the plugin never exposed:
Format.dxFilmEdge,Format.dataBarLimited,Format.telepenandFormat.microPdf417. All four are read-only, so they are absent fromCodeFormat.supportedEncodeFormats, and all four are part ofFormat.any. ImageFormat.lumA, for 8-bit grayscale with an alpha byte.
Changed #
ImageFormat.rgbx,.xrgb,.bgrxand.xbgrfollow the upstream rename to.rgba,.argb,.bgraand.abgr. The old names still work and keep their values, but are deprecated.- Detection quality and speed from upstream: better Aztec and DataMatrix detectors, improved QR Code detection (notably Version 1 and multiple small symbols in one frame), and 10–40% faster scanning on ARM.
- The Android NDK is no longer pinned to 27.0.12077973. That pin existed because zxing-cpp v2.3.0 could not compile against the libc++ in NDK 28+; v3.1.1 can, and the plugin now builds with NDK 27, 28 and 29.
- Windows builds as C++20, which zxing-cpp 3.x requires.
Fixed #
DecodeParams.maxNumberOfSymbolsis clamped to 1–255. zxing takes auint8_t, so a larger value silently wrapped — 256 asked for no symbols at all.- Upstream fix for an out-of-bounds read in the MicroPDF417 decoder.
2.4.0 #
Bug-fix and correctness release. Every fix below is covered by the unit tests in
test/ or the FFI integration tests in example/integration_test/.
Fixed #
- Reading some image files crashed the app (#213).
rgbByteshanded the decoder the image's own storage, which for a palette, 1/2/4-bit or 16-bit image is not 8-bit RGB and is a fraction ofwidth * height * 3— a 1-bit PNG packs eight pixels per byte. The decoder then read far past the end of the allocation (EXCEPTION_ACCESS_VIOLATION_READon Windows). Such images are now converted first, so they scan instead of crashing. - A corrupt or truncated image file threw instead of reporting an error.
decodeImageprobes each format in turn and a malformed file can make one of those probes throw rather than decline. - iOS/macOS release builds could abort inside zxing (#237). The Swift
Package Manager build never defined
NDEBUG, so zxing's internalasserts stayed live in shipped apps —Assertion failed: (l1.isValid() && l2.isValid()), function intersect, file RegressionLine.h. Release and profile builds now compile them out, matching the CMake build used elsewhere. Debug builds keep the asserts. - Scanning silently never succeeded on some Android devices (#197). CameraX
reports the device's actual frame layout, and on some devices that is NV21;
ReaderWidgetmapped NV21 toImageFormat.rgb, so the luminance plane was decoded as RGB and nothing ever matched — with no error to show for it. A frame layout that cannot be scanned at all is now reported throughonScanFailureand logged, instead of failing silently forever. CameraPreviewcould be rebuilt against a disposed controller (#238, #212, #204).CameraPreviewrenders through aValueListenableBuilderbound to the controller, and nothing marked the widget dirty when the controller was swapped, so the preview stayed subscribed to a controller that was about to be disposed and the pending rebuild calledbuildPreview()on it.- A wedged camera teardown left the widget with no camera at all. Stopping the image stream and disposing the controller are now bounded by a timeout; previously an unresponsive platform call blocked the next camera from opening, with no way to recover.
- A device without a torch aborted camera setup (#219). Verified by a new
widget test:
setFlashModefailing now hides the flash button and leaves the camera running. - A failure to start the decoding isolate left the preview black forever.
Camera setup no longer waits on the isolate, and errors from either are
reported through
onControllerCreatedinstead of being swallowed. - Reopening the scanner could leave it with no camera (#160, #179, #163,
#153). After
initialize(),getMaxZoomLevel()was the one unguarded platform call, and several awaits ran before it. If the controller was disposed or replaced in that window it threwUninitialized CameraController, which aborted the rest of setup. Every step now re-checks that the controller is still current, and a failing zoom query falls back to no zoom instead of taking camera setup down with it. - The crop overlay was drawn against the screen, not the widget (#196).
ReaderWidgetsized its preview and cut-out fromMediaQuery.size, so any instance that is not full screen — inside aSizedBox, or aScaffoldbody under an app bar — drew the indicator at the wrong size and off-centre. It now lays out from its own constraints. - A gallery image could crash the app on Android (#187). Same out-of-bounds
read as #213: a picked image whose pixel layout is not 8-bit RGB produced a
buffer smaller than the decoder was told to read (
SIGSEGV / SEGV_ACCERR). - Android frame layout is now requested explicitly (#197).
ReaderWidgetasks forImageFormatGroup.yuv420on Android andbgra8888on iOS instead of letting the platform choose, so the buffer layout no longer varies by device. type 'ArgumentError' is not a subtype of type 'Code'(#221). Errors raised inside the decoding isolate — including the missing-native-library error behind that report — were sent back raw and then cast toCode. The real error is now rethrown with its own message.- Generated barcodes could come out scrambled. zxing enlarges a symbol that
does not fit the requested box (a long Code128 asked for 240x120 is emitted at
915x120), but the encoder only returned the pixel buffer, so it was rendered
with the requested size and produced an unreadable image.
EncodeResultnow reports the bitmap it actually produced andEncodeexposes it aswidth/height;WriterWidgetandpngFromBytesuse those values. - NV21 camera frames were decoded as RGB.
ReaderWidgetmappedImageFormatGroup.nv21toImageFormat.rgb, so the luminance plane was read as RGB pixels and nothing scanned. NV21 and YUV420 now both map toImageFormat.lum, and JPEG frames reportImageFormat.noneinstead of being scanned as raw pixels. - Reading an image file with default params produced garbage. The file and
URL readers always decode to RGB but left
DecodeParams.imageFormatat itslumdefault, soreadBarcodeImagePath(file, DecodeParams())handed the decoder mismatched pixels. The pixel format is now set to match the data. - A too-small image buffer was read out of bounds.
readBarcode/readBarcodestrusted the caller'swidth/heightand read past the end of a buffer that was smaller thanwidth * height * pixStride. The buffer length is now passed to the native side, which reports an error instead. - Barcode positions were wrong when a crop rect was used. Positions are reported by zxing relative to the cropped view; they are now translated back into full-image coordinates so overlays line up.
processCameraImagehung forever when called beforestartCameraProcessing(), or when the decoding isolate was stopped while a frame was in flight. Both now complete with aStateError.- Errors raised inside the decoding isolate surfaced as an unrelated
TypeError. The raw error object was sent back and then cast toCode. Errors are now wrapped and rethrown with their original message. processCameraImage/processCameraImageMultithrew a cast error whenDecodeParams.isMultiScandid not match the method that was called. The flag is now forced to match, andprocessCameraImageMultisetsCode.source.- Disposing one
ReaderWidgetbroke every other one on screen. The decoding isolate is shared, andstopCameraProcessing()tore it down unconditionally. It is now reference counted. - The result overlay never appeared in multi-scan mode with the default
cropPercent, and the crop cut-out was still drawn even though multi-scan scans the whole frame. Both overlays now follow the crop actually applied. - The built-in scan-mode dropdown did not change how frames were scanned.
ReaderWidgetreadwidget.isMultiScanwhile the dropdown updated internal state. It now uses the effective mode and syncs it indidUpdateWidget, which also makes changes tolensDirectionandresolutiontake effect. - Camera rows with padding were misread. Only the YUV420 luminance plane had
its row stride handled; BGRA8888 frames with
bytesPerRow > width * 4were passed through shifted. pngFromBytesproduced a wrong image for aUint8Listview into a larger buffer, and read past the end of a buffer that was too small. It now honours the view's offset and rejects inconsistent input with anArgumentError.- The debug image on a
Codewas garbage for non-luminance input. It was copied assuming one byte per pixel regardless of the source format; it is now converted to luminance, matching whatpngFromBytesexpects. - A memory leak in
readBarcodeswhen zxing found candidates but all of them failed validation: the native result array was allocated and never freed. WriterWidgetaccepted invalid input. A null text passed validation, and zero or negative width/height and negative margins reached the encoder.- Tapping a code in
MultiResultOverlayfired on any pointer event, because the callback was invoked fromCustomPainter.hitTest. It now uses a real tap gesture. - The web stub threw from
stopCameraProcessing, so disposing a widget on web raised; teardown calls are now no-ops and the rest report a descriptiveUnsupportedError. - Web/WasmGC resolution. The conditional import used the legacy
dart.library.html, which is absent when compiling to WasmGC, so the unsupported-platform stub was selected. It now usesdart.library.js_interop.
Changed #
XFileandCameraImageare re-exported: they appear in this package's own signatures, and importingpackage:camerafor them collided with this package'sImageFormat.DecodeParamsgainedcopyWith, and the file/URL readers no longer mutate theDecodeParamsinstance passed to them.- The file and URL readers report failures as a
Code/Codescarrying anerrorinstead of throwing. Code,Codes,PositionandEncodeimplementtoString().MultiScanPainterno longer takescontextoronCodeTap; tap handling moved toMultiResultOverlay, andshouldRepaintno longer returnstrueunconditionally.- The
cameradependency floor is raised to>=0.11.0, the release where Android moved to CameraX. The camera2 implementation it replaced crashed insideio.flutter.plugins.camera.Cameraon several devices (#205, #206), which nothing in this plugin could work around. Code.imageBytesis documented: it is the luminance the decoder scanned, cropped to the scan rect, and only populated while logging is enabled (#207).cropPercentis documented as the fraction of the frame that is kept, not the fraction cropped away (#151).- The zoom level is reset when switching cameras, instead of carrying the previous camera's factor over to one that may not support it.
- ZXScanner's README no longer links to App Store and Google Play pages that return 404; it explains how to build the app from source instead (#180).
- Android
compileSdkraised to 36 and Java compatibility to 11, matching the current Flutter defaults. The NDK stays pinned to 27.0.12077973, which is required: zxing-cpp v2.3.0 does not build against the libc++ in NDK 28+. - iOS podspec deployment target aligned with
Package.swift(13.0), and the placeholder metadata in both podspecs replaced. - README: every code sample was corrected -- none of them compiled against the real API -- and the platform minimums now match the build files.
- Replaced the empty unit-test file with real coverage, and extended the FFI integration tests to cover the fixes above, including reading a barcode from PNG (8-bit, grayscale, 1-bit, 16-bit), GIF, JPEG and BMP files.
- Added widget tests for the camera lifecycle — start-up, switching cameras, disposal and devices without a torch — driven by a fake camera platform.
2.3.1 #
- Fixed iOS/macOS barcode detection failing in stripped archives after the SPM migration.
2.3.0 #
- Migrated iOS and macOS projects from CocoaPods to Swift Package Manager (SPM).
- Improved camera handling: fixed
CameraControllerdisposal issues andstopImageStream()errors. - Enhanced flash/torch UI: hidden toggle button when flash is unavailable and improved state management.
- Added a second action button capability for better UI flexibility.
- Improved multiple concurrent isolates handling.
- Updated iOS deployment target to 13.0.
2.2.1 #
- Draw scan result rectangle in single scan mode when cropRect = 0
2.2.0 #
- Support 16KB page size on android
- minSdkVersion had to be bumped to API Level 23 (Android 6.0)
2.1.0 #
Enhance barcode scanning features and improve overlay customization
- Added vertical and horizontal crop offsets, downscaling option, and max symbol count to barcode decoding parameters.
- Refactored scanner overlay to use a new universal border with customizable cut-out size and offsets.
- Updated ReaderWidget to support new overlay features and adjusted padding in debug info widget.
- Removed deprecated dynamic and fixed scanner overlays.
2.0.2 #
- Added parameters
tryDownscaleandmaxNumberOfSymbolsto theReaderWidgetfor better performance and flexibility.
2.0.1 #
- Fixed windows compatibility issues
2.0.0 #
- Updated zxing-cpp to v2.3.0
1.9.1 #
- Increased minimum versions of
cameraandimagepackages to support newer APIs.
1.9.0 #
- Improved FFI interoperability: changed image data type from
Uint32ListtoUint8Listfor correct handling of binary (black & white) matrices between C++ (zxing-cpp) and Flutter. - Fixed issues when creating images from binary data in Flutter, ensuring proper grayscale and RGB handling.
- Updated integration tests to work with the new data format.
- Minor code cleanup and refactoring.
1.8.2 #
- Minor improvements
1.8.1 #
- Minor improvements
1.8.0 #
- Fixed Windows compatibility issues (thanks to @liff)
- Updated dependencies to the latest version
1.6.1 #
- Fixed iOS and macOS compatibility issues
1.6.0 #
- Updated camera to v0.11.0
1.5.2 #
- Fixed issue with recognizing the barcodes from the image
1.5.1 #
- Updated zxing-cpp to v2.2.1
1.5.0 #
- Updated zxing-cpp to v2.2.0
1.4.1 #
- Replaced 'hidden' with 'default' for improved compatibility with older Flutter versions
1.4.0 #
- Updated Image to v4
1.3.2 #
- Conditionally add namespace for AGP 8 support
- Set minimum Flutter version to 3.7.0
1.3.1 #
- Utilized Flutter version 3.1.0 or higher
1.3.0 #
- Updated zxing-cpp to v2.1.0
1.2.1 #
- Moved
melosto dev dependencies (thanks to @phlip9) - Updated dependencies to the latest version
1.2.0 #
- Downgraded image version from v3.4.0 to v3.3.0 to resolve iOS detection issue.
- Downgraded zxing-cpp from v3.0.0 to v2.0.0 to fix QR code decoding issues.
- Resolved multiple code scan issue that occurred when using image path by implementing a fix.
1.1.2 #
- Fixed issue with onControllerCreated callback is sometimes not called
1.1.1 #
- Allow to set camera lens direction
1.1.0 #
- Updated Image to v4
1.0.2 #
- Updated zxing cpp
1.0.1 #
- Added support for changing the camera
- Fixed issue with iPad
1.0.0 #
- Updated zxing-cpp to v2.0.0
- Added support for macOS, Linux, and Windows
- Added support for micro QR codes
- Added the following properties to Code:
- isInverted
- isMirrored
- duration
- Implemented image resizing before decoding
- Implemented multi result drawing
1.0.0-beta.9 #
- Corrected code position in Android when in portrait mode.
1.0.0-beta.8 #
- Implemented multi result drawing
readBarcodesnow returns aCodesobject instead of aList<Code>object
1.0.0-beta.7 #
- Resolved an issue with detecting and handling large images
1.0.0-beta.6 #
- Fixed compilation issue on Android
1.0.0-beta.5 #
- Fixed compilation issue on Android
1.0.0-beta.4 #
- Fixed compilation issue on Android
1.0.0-beta.3 #
- Added the following properties to Code:
- isInverted
- isMirrored
- duration
- Implemented image resizing before decoding
1.0.0-beta.2 #
- Minor improvements
1.0.0-beta.1 #
- Updated zxing-cpp to v2.0.0
- Added support for macOS, Linux, and Windows
- Added support for micro QR codes
- Zxing-cpp is now included as a submodule instead of a deep copy
0.10.0 #
- added
EncodeParams - replaced
inttype withEccLevelenum for error correction level - added
ratio,maxTextLength, andisSupportedEccLevelto Format for encoding barcodes - renamed
ParamstoDecodeParams - fixed issue where images were being inverted when using
zxmethods
0.9.1 #
- fixed memory leaks
0.9.0 #
Breaking changes
- fixed compilation errors on web
- added 'Params' class for using one parameters instead of many
- use 'zx' prefix for all functions
0.8.5 #
- added 'tryInverted' and 'tryHarder' parameters to the
ReaderWidget
0.8.4 #
- added 'bytes' parameter content without any modifications to the scan result
0.8.3 #
- bug fixes
0.8.2 #
- bug fixes
0.8.1 #
- bug fixes
0.8.0 #
- added ability to set localization messages for
writer_widget - fixed bug where iOS crashes when creating a new barcode
0.7.4 #
- updated readme
0.7.3 #
- encodeBarcode method now uses the named parameters instead of positional parameters
0.7.1 #
- updated dependencies to the latest version
0.7.0 #
- added barcode result point detection
- added tryHarder and tryRotate arguments to the readers
0.6.0 #
- updated zxing-cpp to v1.4.0
0.4.0 #
Breaking changes
- removed
FlutterZxingclass, call all methods directly - added read multiple barcodes methods
0.3.2 #
- fixed enabling/disabling of the logger
0.3.1 #
- fixed Chinese support
0.3.0 #
- added processCameraImage function
- added pinch to zoom sopport
- added flash sopport
- added custom scanner overlay support
0.2.0 #
- added 'readImagePath' function
- added 'readImagePathString' function
- added 'readImageUrl' function
0.1.3 #
- minor improvements
0.1.2 #
- minor fixes for analyzer options
0.1.1 #
- renamed 'ZxingReaderWidget' to 'ReaderWidget'
- renamed 'ZxingWriterWidget' to 'WriterWidget'
0.1.0 #
- renamed 'zxingRead' to 'readBarcode'
- renamed 'zxingEncode' to 'encodeBarcode'
- updated example project
0.0.2 #
- added ability to set the code format for reader
0.0.1 #
- Initial barcode scanner release.