universal_barcode_scanner 2.3.0 copy "universal_barcode_scanner: ^2.3.0" to clipboard
universal_barcode_scanner: ^2.3.0 copied to clipboard

Barcode and QR code scanner for Flutter, on Android, iOS, Linux, macOS, web and Windows, from one widget and one callback.

Universal Barcode Scanner Versions #

2.3.0 #

Added #

  • The embedded view hands the app its camera frames, in grey, for it to read what is not a code, such as the machine readable zone of a passport or an identity card: onFrame receives a ScanFrame with the luminance under the scan window, at most every frameInterval (200 ms by default) and none while reading is paused. On every platform: the camera's own frames on Android, iOS and macOS, the page's on the web, Windows and Linux.
  • ScanFormat.none reads no code at all, for a view that only hands its frames on.

Compatibility #

  • A view without onFrame asks the platform for nothing more and behaves as before.
  • ScanFormat has a new value: a switch over it that names every value without a default branch must now handle ScanFormat.none.

2.2.4 #

Changed #

  • The badge row carries a PayPal donation badge, funding points pub.flutter-io.cn at the same donation page, and the README ends on the other packages COMAPPS publishes. Nothing about the library changed.

2.2.3 #

Changed #

  • The scanner page and the embedded view on the web, Windows and Linux draw a lighter scan window, the same in both: cut out of the dimmed surround with rounded corners and marked by four thin corner lines, and its line sweeps from edge to edge with a faint trail behind it, in three seconds, rather than glowing. In the embedded view a wide window is narrower, 72 % of the view rather than 85 %, so it stays clear of a column of buttons, and takes at most 60 % of the view's height rather than 80 %, so a low view no longer fills with it.
  • The example is drawn light, and ends on an event check-in: the embedded view reads tickets at a gate, counts the guests in, and turns away a ticket already used or bought for another evening, with the validator. It ships tickets to try: tapping one hands it to the gate through scanImage, and another device can scan them with its camera.
  • The pub.flutter-io.cn screenshots open on a cover.

2.2.2 #

Changed #

  • The README and the ScanContent docs match a code's content with a typed variable, case WifiContent wifi:, rather than the shorter case WifiContent(:final ssid): pattern fewer readers know.
  • The README links to a guided tour of the package on YouTube.

2.2.1 #

Fixed #

  • The sound of a code refused in a browser was too low for a phone's speaker, and went unheard in Chrome on Android. It is now two beeps at 480 Hz, rich in overtones, rather than 330 Hz.
  • On Windows, a code refused sounded like a code read: both were the system's alert sound, the only one Flutter plays there. beep now plays the same tones as in a browser, made by the package and played through the system's PlaySound.

2.2.0 #

Added #

  • UniversalBarcodeScanner.scanImage reads every code in an image, given as bytes: a photo, a file, an asset. No camera and no permission. ML Kit reads it on Android and Vision on iOS and macOS, turning a photo the way its EXIF says; the web, Windows and Linux read it with the scanner page's decoder. ScannerErrorCode.invalidImage says the bytes are no image. The package picks no file itself and adds no dependency.
  • ScanResult.content says what a code holds where its text follows a format phones know: a link, a Wi-Fi network, a vCard or MECARD contact, an e-mail, a phone number, a text message, a place or a calendar event, as a sealed ScanContent. Read from the text alone, the same on every platform.
  • validator on scan, scanResult, stream, resultStream and the embedded view decides which codes count. A code refused does not close the scanner and is not handed on: ScannerLabels.rejected is shown over the camera, whose edge flashes red twice with two short vibrations, or on the native screens of Android, iOS and macOS, read out by a screen reader, with a lower sound than for a code read when beep is on, and reading goes on. A code held in front of the camera is refused once.
  • The web, Windows and Linux pages and the embedded view flash the edge of the camera green once for each code accepted, validator or not.
  • The example reads an image the user picks with file_picker, or one of the pictures it ships, one per kind of content, and says what each code holds. It can accept only links or only products, to show the validator, and marks the codes it refuses, checked again when the choice changes. An integration test runs scanImage on a device.

Changed #

  • On iOS and macOS, the plugin's Swift package depends on FlutterFramework where Flutter provides it, from 3.44, as Flutter now asks of plugins. An older Flutter with Swift Package Manager turned on has no such package, and builds as before.
  • The embedded view takes a new continuous or validator without restarting the camera. The view always reads on, and the widget pauses it on the first code accepted when it is not continuous.

2.1.3 #

Fixed #

  • The pause button of the web, Windows and Linux scanner stops the scan line where it is, as the embedded and native views do, and resuming sets it off again from there. Reading was paused, but the line kept sweeping.

Changed #

  • The buttons over the camera no longer change colour under the mouse. In Chrome the tint could stay on a button once the mouse had left it for the camera. The hand and the tooltip still show over them.

2.1.2 #

Fixed #

  • ScannerBar.foregroundColor colours the back icon, as documented: the default chevron stayed white, and an Icon given as backIcon took the app's icon colour, dark on the bar with a light theme.

Changed #

  • The README lists the parameters of ScannerBar and ScannerButtonStyle.

2.1.1 #

Fixed #

  • On the web, Windows and Linux, a frame the decoder cannot read no longer sends every later frame to the app's thread: a worker is given up only after several unreadable frames in a row, or when it stops.
  • Where the browser has a barcode detector that does not read every format asked for, the bundled reader now runs in a worker, and no longer on the app's thread.

Changed #

  • Changing the formats while the scanner is open keeps the worker and the reader it compiled, rather than loading and compiling them again.
  • The bundled reader lets go of its encoded copy once compiled, and decodes it natively where the browser can.
  • Without createImageBitmap, the canvas a frame is copied through keeps its size from one frame to the next.
  • The page the web, Windows and Linux scanners run is tested in a browser, in CI, with a camera drawn on a canvas.

2.1.0 #

Changed #

  • The camera is now mirrored by default on a desktop and in a desktop browser, where it is a webcam facing the user; not on a phone or a tablet. flip is a bool?: pass false for the old behaviour. UniversalBarcodeScanner.flipsByDefault says what null does.
  • The web, Windows and Linux scanner decodes with zxing-cpp compiled to WebAssembly, through barcode-detector, in place of html5-qrcode, which has not had a release since April 2023. The browser's own detector is still used where there is one. On the web the decoding runs in a worker, off the app's thread. The WebAssembly is bundled: nothing is fetched from a CDN.
  • The page drives the camera itself: a resized window or view no longer restarts it, and only the camera turns when flipped, so the scan box and the page's messages stay the right way round.
  • ScannerBar.cancelLabel replaces the cancelLabel of scan and stream, which is deprecated and still wins when given. It also labels the bar's back button for a screen reader.
  • On Windows and Linux, a webview no longer in use is disposed rather than left loaded with a blank page. webview_all 1.4.3 or later.

Added #

  • ScanResult and BarcodeFormat: scanResult, resultStream and the embedded view's onResult say which symbology each code was printed in, on every platform. scan, stream and onScanned are unchanged.
  • buttons and buttonsAlignment on scan, stream and the embedded view: round buttons over the camera for the torch, pausing, each flip, the zoom and the other camera, down the right side by default. On scan and stream they are drawn on the web, Windows and Linux; the native screens of Android, iOS and macOS keep their own, and a torch asked for shows the native torch button. The embedded view is drawn by Flutter everywhere, so its buttons are too.
  • buttonStyle, a ScannerButtonStyle: the size, spacing, colours, focus ring, corners and tooltips of the buttons and of the close button.
  • The buttons, the close button and the bar's back button work with the mouse and the keyboard: the hand over them, a tooltip saying what each one does, Tab to move between them with a ring around the one reached, Enter or Space to press it. On the web they take the pointer from the camera's frame beneath, which kept every click and move to itself.
  • flipVertical, to show the camera upside down.
  • labels, a ScannerLabels: the words of the buttons, for screen readers, and of the page when the camera will not start. English by default; ScannerLabels.french, .dutch and .german are ready to use.
  • animate, on by default: the camera fades in once its first frame is on screen, and a flip turns it over through its middle. The native embedded views now say when their first frame is there. Off when the platform asks for reduced motion.
  • vibrate and beep, to signal each code read.
  • scanWindowSize on scan and stream, as the embedded view already had.
  • On ScannerController: isPaused, isTorchOn and zoom, which follow the view whoever changes it, and setZoom. The buttons show this state.
  • The example shows the symbology of each code, uses every button, and lets you pick where the buttons sit, how they look and in which language the scanner speaks. It is called Universal Barcode Scanner on every platform.

2.0.1 #

  • The README shows the embedded view at the top of the page, with the other two animations.

2.0.0 #

A rewrite: every platform was reworked, and the package no longer carries code or assets from the packages it started from.

Breaking changes #

1.x 2.0
Flutter 3.27 Flutter 3.35, which the Dart 3.9 floor already required
scanType: ScanType.barcode / .qr / .defaultMode scanWindow: ScanWindow.wide / .square / .square, or ScanWindow.none for no window
isShowFlashIcon showTorchButton
cancelButtonText cancelLabel
barcodeAppBar: BarcodeAppBar(appBarTitle:, enableBackButton:, backButtonIcon:) bar: ScannerBar(title:, showBackButton:, backIcon:), back button on by default
onBarcodeViewCreated: (BarcodeViewController c) {} onCreated: (ScannerController c) {}
scaleWidth, scaleHeight scanWindowSize, in logical pixels
scan(scanDelay:), UniversalBarcodeScanner(onClose:) Removed
A camera that could not be used left scan waiting scan throws a ScannerException; stream emits one and closes
A code reading -1 or -2 was taken for a cancel Every payload is a code
scanDelay delayed a single scan's result It is the least time between two codes of a continuous scan
An embedded view that is not continuous kept reporting It pauses on the first code until resumeScanning()
BarcodeViewController(id) could be built by hand ScannerController is abstract: the widget hands one to onCreated

Added #

  • The embedded view on every platform: iOS and macOS as native views, and the web, Windows and Linux as the bundled page in a view the size of the widget. It was Android only, although the README promised iOS.
  • ScannerException, with permissionDenied, cameraUnavailable and alreadyActive, instead of dialogs and futures that never completed.
  • ScanWindow.none: nothing drawn over the camera, the whole frame read.
  • onError on the embedded view, and ScannerController.dispose.
  • A close button over the web, Windows and Linux scanner when there is no bar, and Escape to close it.

Fixed #

  • A code held in front of the camera is reported once, and again after a second out of sight, with each code followed on its own. Continuous scans used to repeat it on every frame.
  • Two scans in a row no longer interfere: every scan carries a session, and the native scanner closes as soon as its route is popped.
  • stream returns every code on the web, Windows and Linux, and stream(context).first closes the scanner.
  • The web, Windows and Linux scanner decodes at the camera's resolution rather than at the size it is shown: small barcodes that never read now do.
  • iOS: no crash on launch under the scene life cycle, no crash on a late code, and a scanner closed while appearing or covered by another screen is dismissed.
  • Android: the scanner's buttons sit above the navigation bar on Android 15, a rotation no longer fails the permission request, and a frame in flight at closing no longer crashes.
  • Settings that some platforms ignored now apply everywhere: scanFormat, cameraFace and scanDelay on the web and desktop, and all of them in the Android embedded view.
  • An app created by Flutter 3.47 builds: the Android plugin compiles against API 36, as its dependencies require.

Changed #

  • Android is written in Kotlin, compiled with AGP 9's built-in Kotlin support where it is on.
  • Android analyses frames at about 1280 by 960, and iOS and macOS start the camera off the main thread.
  • Restricting scanFormat makes every platform faster.
  • The icons are drawn for the package, and LICENSE is MIT under its author alone. html5-qrcode's Apache 2.0 licence now ships next to it.

1.6.3 #

Changed #

  • The README carries its build badge again, pointed at the branch the repository actually builds from.
  • The example test looked for a card the list had never built. It asked for a title the rewritten example no longer uses, and the third card sits below the fold of the test window, where a ListView does not build it. The test scrolls to it now.

1.6.2 #

Changed #

  • homepage points at the demo, which runs the package in a browser.

1.6.1 #

Fixed #

  • The web scanner said nothing when the camera did not start. The rejection from getUserMedia was swallowed, so a refused permission, a machine with no camera and a camera held by another application all gave the same black rectangle, with the reason only in the console. The page now says which of the three it was and what to do about it.
  • The scanner bar title was underlined in yellow on the web. ScannerChrome is built without Material, so a TextStyle there has to set decoration as well: setting only the colour, the size and the weight left the ambient fallback style and its double underline in place.

Changed #

  • The example is one screen rather than three buttons: what the last scan returned with its length and a count, a card per mode saying what that mode hands back, and the embedded view marked mobile only on the web, where the scanner runs in a frame of its own. It also says that a browser needs permission and HTTPS before any of it works.
  • homepage points at the package's card on comapps.web.app, where the example runs in the browser.

1.6.0 #

Changed #

  • Windows and Linux keep the scanner webview between two scans instead of building one each time. Reopening the scanner was paying for the engine, the page, its script and a fresh camera request every single time, which is why the second scan was as slow as the first while a browser was instant. The webview is let go after a minute without a scanner on screen.
  • The bundled page can be resumed. Stopping it and delivering a code both latched it shut, so a page kept for reuse would have come back dead.

1.5.2 #

Fixed #

  • backgroundColor now reaches the web and desktop scanner. The page those two load paints its own background and covers the whole route, so setting the colour behind it changed nothing: it is handed to the page itself, the way the scan line colour already was.
  • backgroundColor reaches the Windows and Linux page at all. It stopped at the delegation from the shared page to the desktop one.

1.5.1 #

Added #

  • scan and stream take a backgroundColor, which is what the page paints behind the camera. 1.5.0 replaced a Scaffold with a black box, so a scanner opened inside a light application turned its own background black with no way to say otherwise. Black stays the default, since that is what a camera page usually wants.

1.5.0 #

Changed #

  • The package no longer imports package:flutter/material.dart anywhere. Every file is on package:flutter/widgets.dart, the layer both material.dart and the material_ui package are built on, so the scanner composes with either and imposes neither on the app that embeds it.
  • The scanner bar is drawn by the package rather than taken from Material. It is black with white text, which suits a camera, and BarcodeAppBar gains backgroundColor and foregroundColor to say otherwise. An application that passed a BarcodeAppBar had a bar coloured by its own theme until now, so this one looks different until those two are set.
  • The back button has no ripple. Drawing one would mean picking a design system, which is what this release is getting rid of.
  • The scanner route is a PageRouteBuilder rather than a MaterialPageRoute, so it fades in instead of using the platform's own page transition.
  • While the native scanner opens, the route behind it is black with a plain spinner rather than a Scaffold with a Material one.

1.4.0 #

Changed #

  • Android scans with CameraX and ML Kit. Google Mobile Vision, the play-services-vision library the scanner read barcodes with until now, has been deprecated since 2021 and receives neither fixes nor model updates. The Dart API is unchanged.
  • The ML Kit model is bundled rather than fetched, so the scanner reads a code on a device with no Google Play services and downloads nothing before the first scan.
  • minSdkVersion moves from 16 to 21, the floor CameraX and ML Kit share. It is below the one Flutter itself sets, so an app on a current Flutter has nothing to change.
  • A pinch follows the gesture instead of applying its scale once the gesture ends.
  • A tap focuses the camera where it landed.

Fixed #

  • The embedded view draws the camera inside the widget. Its preview is a TextureView, which a Flutter platform view composes into its texture; a SurfaceView is drawn straight to the window instead, beside the widget rather than in it.

Removed #

  • The camera pipeline Mobile Vision came with: CameraSource, CameraSourcePreview, the graphic overlay and the barcode trackers, about 1700 lines that CameraX replaces.
  • The box drawn around a detected code, and the tap that chose between several. The screen returns on the first code read, so the box was on screen for a frame.
  • android.permission.FLASHLIGHT and android:largeHeap from the plugin manifest. The torch goes through CameraX, and the heap belongs to the app rather than to one of its plugins.
  • jcenter(), read-only since 2021, and the material and legacy-support-v4 dependencies that a single Snackbar held on to.

1.3.0 #

Added #

  • Swift Package Manager support on iOS and macOS, alongside the existing CocoaPods podspecs. Both build systems work; an app picks whichever it has enabled. This was the only thing left costing the package points on pub.flutter-io.cn, which reported the plugin as CocoaPods-only.

Removed #

  • The Objective-C shim on iOS. It forwarded registration to the Swift plugin, but nothing called it: the generated registrant has always referenced the Swift class directly. Swift Package Manager also refuses two languages in one target, so a dead file was standing in the way of a working one.

Changed #

  • The Apple sources moved to the layout Swift Package Manager expects, <platform>/universal_barcode_scanner/Sources/universal_barcode_scanner/, and the podspecs point at the new paths. Nothing changes for consumers.
  • The iOS icons are looked up through the bundle that the running build system provides, Bundle.module under Swift Package Manager and the class bundle under CocoaPods, rather than assuming the latter.

1.2.0 #

Added #

  • A sweeping line over the scan square on web, Windows and Linux, so those three look like the native scanners rather than a bare camera feed. It hangs inside the scan region the page already draws, so it tracks the square even when the library shrinks it to fit the video, and it holds still under prefers-reduced-motion.
  • lineColor now reaches web, Windows and Linux, where it used to be ignored. The web host passes it in the page's query string; the desktop hosts set it once the page is up.

Fixed #

  • On Windows and Linux the webview no longer fills the whole window with a stretched camera. The framing moved into the scanner page, where it belongs: the library derives the video and the whole shading overlay from the width it measures on its own container, so sizing the view from the host to a box the page did not lay out for stretched everything, turning the scan square into a narrow sliver. The page caps and centres itself, and the view simply fills what it is given.
  • The app bar title was forced to white on web and left to the theme everywhere else, so the same scanner showed a white title in a browser and a dark one on Windows. The plugin imposes no colour now: the app bar follows the host's AppBarTheme, as it should.
  • Resizing the window left the scanner on stale geometry. The library measures its container once, when starting, and sizes the video and the shading overlay from it; it never measures again, so a resized window showed the two at different sizes and offsets. The page watches its container now and restarts the scanner, debounced, when the width really changes.
  • The scan square is derived from the viewfinder instead of being fixed at 280 pixels. The library drops its shaded region altogether once the square is taller than the video, which is what happens on a narrow viewport: mobile web showed a bare camera, with no square and no line. The video is also centred when its ratio leaves room in the host box.
  • The scanner page no longer forces an aspect ratio on the camera. Forcing one sized the video to a shape the host box did not have, which overflowed and raised scrollbars over the preview. The page follows the camera's own ratio now, and hides any rounding leftover rather than scrolling it.

1.1.0 #

Linux, and one webview for both desktops.

Added #

  • Linux, through the same bundled html5-qrcode page Windows already used. It works because the plugin answers the page's camera permission request on the host side, which is what usually stops a webview from scanning on Linux: WebKitGTK denies a media request the embedder does not handle. Needs libwebkit2gtk-4.1-0, which most desktop installs already carry.

Changed #

  • Windows and Linux now share a single implementation, on webview_all in place of webview_windows. That package carries both a WebView2 and a WebKitGTK backend, and is the only Linux webview on pub.flutter-io.cn that surfaces the camera permission request instead of letting the engine deny it by default.
  • path is gone with it. It only existed to resolve the bundled page next to the executable, and webview_all loads it as a Flutter asset directly. What is left is webview_all and web.

Fixed #

  • The bundled page reached for window.chrome.webview and compared it to the string 'undefined', which threw a TypeError on any browser without it, Firefox included. It now feature-detects the JavaScript channel and falls back to the parent frame on the web.
  • The page posted the scanned code to '*', so an embedding parent on another origin would have received it. It names its own origin as the target now.

Known issue on Windows #

Building with Visual Studio 2026 fails on error STL1011, because the webview dependency pins the Windows Implementation Library at its 2022 release, whose headers still include <experimental/coroutine>. It is not specific to this release: webview_windows, used up to 1.0.0+1, pins the very same version. The README carries the one-line workaround until it is bumped upstream.

Note on 1.0.0 #

The 1.0.0 notes below claim no published Flutter webview grants camera access on Linux. That was wrong: it held for the two packages checked at the time, not for the ecosystem. webview_all does grant it, which is what made this release possible.

1.0.0+1 #

Add gitlab CI workfown

1.0.0 #

First release.

Barcode and QR code scanning on Android, iOS, macOS, web and Windows, from a single entry point: UniversalBarcodeScanner.scan for one code, UniversalBarcodeScanner.stream to keep reading, and the widget itself to embed the camera on Android and iOS.

macOS #

macOS is new, and native rather than a webview: AVCaptureSession for the camera and Vision's VNDetectBarcodesRequest for the decoding, which is the only path Apple offers there since AVCaptureMetadataOutput reads no barcodes on the Mac. It needs macOS 10.15, an NSCameraUsageDescription, and the com.apple.security.device.camera entitlement, all covered in the README. The embedded view stays Android and iOS only.

Linux is not covered. Neither published Linux webview lets a page reach the camera, since desktop_webview_window does not connect WebKitGTK's permission-request signal and webview_cef implements no CefPermissionHandler, and both engines deny by default. The native route is no better, camera_linux having stood at 0.0.8 since 2023. The scanner says so on Linux instead of raising a MissingPluginException.

Dependencies #

permission_handler is gone. It was pulled in for a single camera status read on Windows, and in return every app depending on this plugin inherited its Android module, whose current release forces compileSdk 37. The Windows scanner now simply asks through the webview's own permission prompt and remembers the answer for the scan. What is left is webview_windows, path and web.

Lineage #

The package is a derivative of simple_barcode_scanner by Kunchok Tashi, which embeds the Android and iOS scanner of flutter_barcode_scanner by Amol Gangadhare. Both are MIT, and their copyright notices are kept in LICENSE. Coming from either of them, the API is not the same: see the migration table in the README.

Fixed since the code it derives from #

  • On web the scanner registered a new platform view, built a new iframe and opened a new message listener on every rebuild, and never cancelled any of them. It now sets all three up once and tears them down with the widget.
  • On web a message from any origin was taken for a scan, so an embedded frame or a browser extension could feed the app a barcode of its choosing. Only messages from the page's own origin are read now.
  • On web the height of the scanner was decided from the viewport width, which squashed the preview on a wide, short window.
  • On Windows the webview was reinitialised and its message stream resubscribed on every rebuild, which delivered a scan several times over.
  • On Windows the camera permission was read asynchronously from build, so the result never arrived in time and the permission dialog was shown even when permission had already been granted.
  • On Windows the webview controller was disposed twice when leaving through the app bar.
  • UniversalBarcodeScanner.stream now closes its stream however the route is left, including a system back gesture. It used to leak the controller unless the app bar button was used.
  • Linux says it is unsupported instead of raising a MissingPluginException.
  • Cancelling a single scan returned the raw sentinel '-1' to the caller, which the documentation described as null. It is now null, and '-1' no longer leaks into a continuous stream either.
  • The native scanner kept a stream field it never assigned, so the cached broadcast stream it was meant to reuse was rebuilt on every call.

Renamed from the code it derives from #

The plugin used to register itself under another package's namespace, which made it impossible to depend on both in one app: two AARs declaring com.amolg.flutterbarcodescanner fail to merge, and two pods declaring SwiftFlutterBarcodeScannerPlugin fail to link. Everything now sits under be.comapps.universal_barcode_scanner, and the method channels, event channel and platform view type are named after this package.

1
likes
160
points
1.36k
downloads
screenshot

Documentation

API reference

Publisher

verified publishercomapps.be

Weekly Downloads

Barcode and QR code scanner for Flutter, on Android, iOS, Linux, macOS, web and Windows, from one widget and one callback.

Homepage
Repository (GitHub)
View/report issues

Topics

#barcode #qrcode #scanner #camera #reader

Funding

Consider supporting this project:

www.paypal.com

License

MIT (license)

Dependencies

flutter, flutter_plugin_android_lifecycle, web, webview_all

More

Packages that depend on universal_barcode_scanner

Packages that implement universal_barcode_scanner