{"id":17088053,"url":"https://github.com/juliansteenbakker/mobile_scanner","last_synced_at":"2025-05-14T01:07:05.697Z","repository":{"id":37400949,"uuid":"456835736","full_name":"juliansteenbakker/mobile_scanner","owner":"juliansteenbakker","description":"A universal scanner for Flutter based on MLKit. Uses CameraX on Android and AVFoundation on iOS.","archived":false,"fork":false,"pushed_at":"2025-04-11T20:46:41.000Z","size":15096,"stargazers_count":979,"open_issues_count":226,"forks_count":549,"subscribers_count":15,"default_branch":"develop","last_synced_at":"2025-04-14T05:52:58.586Z","etag":null,"topics":["android","dart","flutter","hacktoberfest","ios"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/juliansteenbakker.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/funding.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["juliansteenbakker"]}},"created_at":"2022-02-08T07:57:56.000Z","updated_at":"2025-04-11T20:46:38.000Z","dependencies_parsed_at":"2023-10-12T18:54:21.839Z","dependency_job_id":"6eb3360a-8135-4910-bc65-a33e4814a6d7","html_url":"https://github.com/juliansteenbakker/mobile_scanner","commit_stats":{"total_commits":1104,"total_committers":76,"mean_commits":"14.526315789473685","dds":0.4936594202898551,"last_synced_commit":"8e983f1fbdd771a5e59dcd5309f273c39817fe5c"},"previous_names":[],"tags_count":68,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juliansteenbakker%2Fmobile_scanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juliansteenbakker%2Fmobile_scanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juliansteenbakker%2Fmobile_scanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juliansteenbakker%2Fmobile_scanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/juliansteenbakker","download_url":"https://codeload.github.com/juliansteenbakker/mobile_scanner/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248830389,"owners_count":21168272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","dart","flutter","hacktoberfest","ios"],"created_at":"2024-10-14T13:36:01.416Z","updated_at":"2025-05-14T01:07:05.687Z","avatar_url":"https://github.com/juliansteenbakker.png","language":"Dart","funding_links":["https://github.com/sponsors/juliansteenbakker"],"categories":["Dart"],"sub_categories":[],"readme":"# mobile_scanner\n\n[![Pub Version](https://img.shields.io/pub/v/mobile_scanner.svg)](https://pub.dev/packages/mobile_scanner)\n[![Pub Version Prerelease](https://img.shields.io/pub/v/mobile_scanner.svg?include_prereleases)](https://pub.dev/packages/mobile_scanner)\n[![Build Status](https://github.com/juliansteenbakker/mobile_scanner/actions/workflows/code-coverage.yml/badge.svg)](https://github.com/juliansteenbakker/mobile_scanner/actions/workflows/code-coverage.yml)\n[![Style: Very Good Analysis](https://img.shields.io/badge/style-very_good_analysis-B22C89.svg)](https://pub.dev/packages/very_good_analysis)\n[![Codecov](https://codecov.io/gh/juliansteenbakker/mobile_scanner/graph/badge.svg?token=RGE4XVOGJ5)](https://codecov.io/gh/juliansteenbakker/mobile_scanner)\n[![GitHub Sponsors](https://img.shields.io/github/sponsors/juliansteenbakker)](https://github.com/sponsors/juliansteenbakker)\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/README.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\n## Installation\n\nAdd the dependency in your `pubspec.yaml` file:\n\n```\ndependencies:\n  mobile_scanner: ^\u003clatest_version\u003e\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://developers.google.com/ml-kit/vision/barcode-scanning/android)\n\nTo use the **unbundled version** of the MLKit Barcode-scanning, add the following line to your `/android/gradle.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\u003e/ios/Runner/Info.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://pub.dev/packages/image_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\u003eNSCameraUsageDescription\u003c/key\u003e\n\u003cstring\u003eThis app needs camera access to scan QR codes\u003c/string\u003e\n\n\u003ckey\u003eNSPhotoLibraryUsageDescription\u003c/key\u003e\n\u003cstring\u003eThis app needs photos access to get QR code from photo library\u003c/string\u003e\n```\n\n\n### macOS\nEnsure that you granted camera permission in XCode -\u003e Signing \u0026 Capabilities:\n\n\u003cimg width=\"696\" alt=\"Screenshot of XCode where Camera is checked\" src=\"https://user-images.githubusercontent.com/24459435/193464115-d76f81d0-6355-4cb2-8bee-538e413a3ad0.png\"\u003e\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/foundation.dart';\nimport 'package:mobile_scanner/mobile_scanner.dart';\n\nfinal String scriptUrl = // ...\n\nif (kIsWeb) {\n  MobileScannerPlatform.instance.setBarcodeLibraryScriptUrl(scriptUrl);\n}\n```\n\n## Usage\n\n### Simple\n\nImport the package with `package:mobile_scanner/mobile_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#### 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?\u003e? _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\u003e with WidgetsBindingObserver {\n  // ...\n\n  @override\n  void didChangeAppLifecycleState(AppLifecycleState state) {\n    // If the controller is not ready, do not try to start or stop it.\n    // 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        // Restart the scanner when the app is resumed.\n        // 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        // Stop the scanner when the app is paused.\n        // Also stop the barcode events subscription.\n        unawaited(_subscription?.cancel());\n        _subscription = null;\n        unawaited(controller.stop());\n    }\n  }\n\n  // ...\n}\n```\n\nThen, start the scanner in `void initState()`:\n\n```dart\n@override\nvoid initState() {\n  super.initState();\n  // Start listening to lifecycle changes.\n  WidgetsBinding.instance.addObserver(this);\n\n  // Start listening to the barcode events.\n  _subscription = controller.barcodes.listen(_handleBarcode);\n\n  // 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\u003e dispose() async {\n  // Stop listening to lifecycle changes.\n  WidgetsBinding.instance.removeObserver(this);\n  // Stop listening to the barcode events.\n  unawaited(_subscription?.cancel());\n  _subscription = null;\n  // Dispose the widget itself.\n  super.dispose();\n  // Finally, dispose of the controller.\n  await controller.dispose();\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliansteenbakker%2Fmobile_scanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuliansteenbakker%2Fmobile_scanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliansteenbakker%2Fmobile_scanner/lists"}