[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-9430":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":31,"readmeContent":32,"aiSummary":33,"trendingCount":16,"starSnapshotCount":16,"syncStatus":17,"lastSyncTime":34,"discoverSource":35},9430,"mobile_scanner","juliansteenbakker\u002Fmobile_scanner","juliansteenbakker","A universal Flutter barcode and QR code scanner using CameraX\u002FML Kit for Android, AVFoundation\u002FApple Vision for iOS & macOS, and ZXing for web.","https:\u002F\u002Fpub.dev\u002Fpackages\u002Fmobile_scanner",null,"Dart",1152,694,13,122,0,2,11,1,21.53,"BSD 3-Clause \"New\" or \"Revised\" License",false,"develop",true,[26,27,28,29,30],"android","dart","flutter","hacktoberfest","ios","2026-06-12 02:02:07","# mobile_scanner\n\n[![Pub Version](https:\u002F\u002Fimg.shields.io\u002Fpub\u002Fv\u002Fmobile_scanner.svg)](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fmobile_scanner)\n[![Pub Version Prerelease](https:\u002F\u002Fimg.shields.io\u002Fpub\u002Fv\u002Fmobile_scanner.svg?include_prereleases)](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fmobile_scanner)\n[![Build Status](https:\u002F\u002Fgithub.com\u002Fjuliansteenbakker\u002Fmobile_scanner\u002Factions\u002Fworkflows\u002Fcode-coverage.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fjuliansteenbakker\u002Fmobile_scanner\u002Factions\u002Fworkflows\u002Fcode-coverage.yml)\n[![Style: Very Good Analysis](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fstyle-very_good_analysis-B22C89.svg)](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fvery_good_analysis)\n[![Codecov](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fjuliansteenbakker\u002Fmobile_scanner\u002Fgraph\u002Fbadge.svg?token=RGE4XVOGJ5)](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fjuliansteenbakker\u002Fmobile_scanner)\n[![GitHub Sponsors](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fsponsors\u002Fjuliansteenbakker)](https:\u002F\u002Fgithub.com\u002Fsponsors\u002Fjuliansteenbakker)\n\nA fast and lightweight Flutter plugin for scanning barcodes and QR codes using the device’s camera. It supports multiple barcode formats, real-time detection, and customization options for an optimized scanning experience on multiple platforms.\n\n## Features\n\n- Fast barcode and QR code scanning\n- Supports multiple barcode formats\n- Real-time detection\n- Customizable camera and scanner behavior\n\nSee the [examples](example\u002FREADME.md) for runnable examples of various usages, such as the basic usage, applying a scan window, or retrieving images from the barcodes.\n\n## Platform Support\n\n| Android | iOS | macOS | Web | Linux | Windows |\n|---------|-----|-------|-----|-------|---------|\n| ✔       | ✔   | ✔     | ✔   | :x:   | :x:     |\n\n### Features Supported\n\nSee the example app for detailed implementation information.\n\n| Features     | Android            | iOS                | macOS              | Web |\n|--------------|--------------------|--------------------|--------------------|-----|\n| analyzeImage | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |\n| returnImage  | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |\n| scanWindow   | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: |\n| autoZoom     | :heavy_check_mark: | :x:                | :x:                | :x: |\n| lensType     | :heavy_check_mark: | :heavy_check_mark: | :x:                | :x: |\n\n## Installation\n\nAdd the dependency in your `pubspec.yaml` file:\n\n```\ndependencies:\n  mobile_scanner: ^\u003Clatest_version>\n```\n\nThen run:\n\n`flutter pub get`\n\n## Configuration\n\n### Android\nThis package uses by default the **bundled version** of MLKit Barcode-scanning for Android. This version is immediately available to the device. But it will increase the size of the app by approximately 3 to 10 MB.\n\nThe alternative is to use the **unbundled version** of MLKit Barcode-scanning for Android. This version is downloaded on first use via Google Play Services. It increases the app size by around 600KB.\n\n[You can read more about the difference between the two versions here.](https:\u002F\u002Fdevelopers.google.com\u002Fml-kit\u002Fvision\u002Fbarcode-scanning\u002Fandroid)\n\nTo use the **unbundled version** of the MLKit Barcode-scanning, add the following line to your `\u002Fandroid\u002Fgradle.properties` file:\n```\ndev.steenbakker.mobile_scanner.useUnbundled=true\n```\n\n### iOS\n\n\nSince the scanner needs to use the camera, add the following keys to your Info.plist file. (located in \u003Cproject root>\u002Fios\u002FRunner\u002FInfo.plist)\n\nNSCameraUsageDescription - describe why your app needs access to the camera. This is called Privacy - Camera Usage Description in the visual editor.\n\nIf you want to use the local gallery feature from [image_picker](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fimage_picker), you also need to add the following key.\n\nNSPhotoLibraryUsageDescription - describe why your app needs permission for the photo library. This is called Privacy - Photo Library Usage Description in the visual editor.\n\nExample,\n```\n\u003Ckey>NSCameraUsageDescription\u003C\u002Fkey>\n\u003Cstring>This app needs camera access to scan QR codes\u003C\u002Fstring>\n\n\u003Ckey>NSPhotoLibraryUsageDescription\u003C\u002Fkey>\n\u003Cstring>This app needs photos access to get QR code from photo library\u003C\u002Fstring>\n```\n\n\n### macOS\nEnsure that you granted camera permission in XCode -> Signing & Capabilities:\n\n\u003Cimg width=\"696\" alt=\"Screenshot of XCode where Camera is checked\" src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F24459435\u002F193464115-d76f81d0-6355-4cb2-8bee-538e413a3ad0.png\">\n\n### Web\n\nAs of version 5.0.0 adding the barcode scanning library script to the `index.html` is no longer required,\nas the script is automatically loaded on first use.\n\n#### Providing a mirror for the barcode scanning library\n\nIf a different mirror is needed to load the barcode scanning library,\nthe source URL can be set beforehand.\n\n```dart\nimport 'package:flutter\u002Ffoundation.dart';\nimport 'package:mobile_scanner\u002Fmobile_scanner.dart';\n\nfinal String scriptUrl = \u002F\u002F ...\n\nif (kIsWeb) {\n  MobileScannerPlatform.instance.setBarcodeLibraryScriptUrl(scriptUrl);\n}\n```\n\n## Usage\n\n### Simple\n\nImport the package with `package:mobile_scanner\u002Fmobile_scanner.dart`. The only required parameter is `onDetect`, which returns the scanned barcode or qr code.\n\n```dart\nMobileScanner(\n  onDetect: (result) {\n    print(result.barcodes.first.rawValue);\n  },\n),\n```\n\n### Advanced\n\nIf you want more control over the scanner, you need to create a new `MobileScannerController` controller. The controller contains multiple parameters to adjust the scanner.\n```dart\nfinal MobileScannerController controller = MobileScannerController(\n  cameraResolution: size,\n  detectionSpeed: detectionSpeed,\n  detectionTimeoutMs: detectionTimeout,\n  formats: selectedFormats,\n  returnImage: returnImage,\n  torchEnabled: true,\n  invertImage: invertImage,\n  autoZoom: autoZoom,\n);\n```\n\n```dart\nMobileScanner(\n  controller: controller,\n  onDetect: (result) {\n    print(result.barcodes.first.rawValue);\n  },\n);\n```\n\n#### Switching lens types\n\nOn devices with multiple cameras (normal, wide, zoom), you can switch between lens types:\n\n```dart\n\u002F\u002F Toggle through available lens types (normal -> wide -> zoom -> normal)\nawait controller.switchCamera(const ToggleLensType());\n\n\u002F\u002F Or select a specific lens type\nawait controller.switchCamera(\n  const SelectCamera(lensType: CameraLensType.wide),\n);\n\n\u002F\u002F Get supported lens types for the current camera\nfinal Set\u003CCameraLensType> supportedLenses = await controller.getSupportedLenses();\n```\n\n#### Lifecycle changes\n\nIf you want to pause the scanner when the app is inactive, you need to use `WidgetsBindingObserver`.\n\nFirst, provide a `StreamSubscription` for the barcode events. Also, make sure to create a `MobileScannerController` with `autoStart` set to false, since we will be handling the lifecycle ourself.\n\n```dart\nfinal MobileScannerController controller = MobileScannerController(\n  autoStart: false,\n);\n\nStreamSubscription\u003CObject?>? _subscription;\n```\n\nThen, ensure that your `State` class mixes in `WidgetsBindingObserver`, to handle lifecyle changes, and add the required logic to the `didChangeAppLifecycleState` function:\n\n```dart\nclass MyState extends State\u003CMyStatefulWidget> with WidgetsBindingObserver {\n  \u002F\u002F ...\n\n  @override\n  void didChangeAppLifecycleState(AppLifecycleState state) {\n    \u002F\u002F If the controller is not ready, do not try to start or stop it.\n    \u002F\u002F Permission dialogs can trigger lifecycle changes before the controller is ready.\n    if (!controller.value.hasCameraPermission) {\n      return;\n    }\n\n    switch (state) {\n      case AppLifecycleState.detached:\n      case AppLifecycleState.hidden:\n      case AppLifecycleState.paused:\n        return;\n      case AppLifecycleState.resumed:\n        \u002F\u002F Restart the scanner when the app is resumed.\n        \u002F\u002F Don't forget to resume listening to the barcode events.\n        _subscription = controller.barcodes.listen(_handleBarcode);\n\n        unawaited(controller.start());\n      case AppLifecycleState.inactive:\n        \u002F\u002F Stop the scanner when the app is paused.\n        \u002F\u002F Also stop the barcode events subscription.\n        unawaited(_subscription?.cancel());\n        _subscription = null;\n        unawaited(controller.stop());\n    }\n  }\n\n  \u002F\u002F ...\n}\n```\n\nThen, start the scanner in `void initState()`:\n\n```dart\n@override\nvoid initState() {\n  super.initState();\n  \u002F\u002F Start listening to lifecycle changes.\n  WidgetsBinding.instance.addObserver(this);\n\n  \u002F\u002F Start listening to the barcode events.\n  _subscription = controller.barcodes.listen(_handleBarcode);\n\n  \u002F\u002F Finally, start the scanner itself.\n  unawaited(controller.start());\n}\n```\n\nFinally, dispose of the the `MobileScannerController` when you are done with it.\n\n```dart\n@override\nFuture\u003Cvoid> dispose() async {\n  \u002F\u002F Stop listening to lifecycle changes.\n  WidgetsBinding.instance.removeObserver(this);\n  \u002F\u002F Stop listening to the barcode events.\n  unawaited(_subscription?.cancel());\n  _subscription = null;\n  \u002F\u002F Dispose the widget itself.\n  super.dispose();\n  \u002F\u002F Finally, dispose of the controller.\n  await controller.dispose();\n}\n```\n\n## Known Limitations\n\n### `rawBytes` on iOS and macOS\n\nApple's Vision framework does not provide a direct API for reading the raw payload bytes of a scanned barcode. The `rawBytes` field is populated on a best-effort basis using two strategies, each with constraints.\n\n#### QR codes\n\nTwo strategies are used in combination. For Byte-mode segments the error-corrected bit stream from `CIQRCodeDescriptor` is parsed directly. For all other modes the decoded string from `payloadStringValue` is re-encoded to Latin-1 as a fallback.\n\n| Scenario                                        | `rawBytes` result                                              |\n|-------------------------------------------------|----------------------------------------------------------------|\n| Byte mode (UTF-8, arbitrary binary data)        | Correct — parsed directly from bit stream                      |\n| Numeric mode (digits only)                      | Correct — recovered via string fallback                        |\n| Alphanumeric mode (uppercase + allowed symbols) | Correct — recovered via string fallback                        |\n| Kanji mode                                      | `null` — Japanese characters cannot round-trip through Latin-1 |\n\n#### Aztec, DataMatrix, PDF417 and linear formats (Code 128, EAN, etc.)\n\nApple Vision decodes the payload as a string internally using a Latin-1 (ISO-8859-1) interpretation of the raw bytes. `rawBytes` is recovered by re-encoding that string back to Latin-1.\n\n| Byte value range                                            | `rawBytes` result                                                                                            |\n|-------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|\n| `0x00`–`0x7F` (ASCII)                                       | Correct                                                                                                      |\n| `0xA0`–`0xFF` (upper Latin-1, includes `ø`, `é`, `ü`, etc.) | Correct                                                                                                      |\n| `0x80`–`0x9F` (Windows-1252 special range)                  | `null` — Apple maps these to Unicode code points above U+00FF, which cannot be round-tripped through Latin-1 |\n\nThis means arbitrary binary payloads that happen to contain bytes in the `0x80`–`0x9F` range will result in `rawBytes` being `null` for those formats.\n\n#### Android and Web\n\n`rawBytes` is fully supported for all formats and encoding modes via MLKit (Android) and the ZXing-based library (Web).\n","mobile_scanner 是一个用于扫描条形码和二维码的 Flutter 插件，支持 Android、iOS、macOS 和 Web 平台。它利用 CameraX\u002FML Kit（Android）、AVFoundation\u002FApple Vision（iOS & macOS）以及 ZXing（Web）等技术实现快速轻量级的扫描功能。核心功能包括支持多种条形码格式、实时检测及自定义相机和扫描器行为，从而提供优化的用户体验。适用于需要集成条码或二维码扫描功能的各种移动应用开发场景，如库存管理、票务验证和个人信息交换等。","2026-06-11 03:22:37","top_language"]