qrscan 1.2.3 copy "qrscan: ^1.2.3" to clipboard
qrscan: ^1.2.3 copied to clipboard

One-shot Flutter QR/barcode scanner: open camera, first decode, string back. Android CameraX+ZXing, iOS Vision. Not a widget.

Language: English | 中文简体

qrscan #

License Pub

Open camera. First decode. String back. Close.

qrscan.gif

dependencies:
  qrscan: ^1.2.3
import 'package:qrscan/qrscan.dart' as scanner;

String? code = await scanner.scan();
String? wechat = await scanner.scan(looks: ScanLooks.wechat);
String? alipay = await scanner.scan(looks: ScanLooks.alipay);

This is not an embedded camera widget. Preview / scan window / overlay / torch API / continuous scan → mobile_scanner.

This is not a hardware gun. Keyboard wedge → a TextField. OEM broadcast PDA → pda_scanner.

  • Android CameraX 1.4 + ZXing 3.5.3
  • iOS AVFoundation + Vision
  • Dart 3 / Flutter 3.10+ / Android embedding v2
  • Five functions: scan / scanPhoto / scanPath / scanBytes / generateBarCode

Android #

minSdk 21. Camera permission is requested when scan() runs. Do not add storage permissions.

Host MainActivity must be embedding v2 (FlutterActivity). The scanner follows device orientation.

iOS #

<key>NSCameraUsageDescription</key>
<string>Scan QR codes and barcodes</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Read a code from a photo</string>

Minimum iOS 12. Landscape only if the host already lists it in UISupportedInterfaceOrientations.

Usage #

String? cameraScanResult = await scanner.scan();
String? wechat = await scanner.scan(looks: ScanLooks.wechat);
String? alipay = await scanner.scan(looks: ScanLooks.alipay);
String? branded = await scanner.scan(color: Color(0xFF00C853), hint: '对准条码或二维码');
String? photoScanResult = await scanner.scanPhoto();
String? fromPath = await scanner.scanPath(path);
String? fromBytes = await scanner.scanBytes(bytes);
Uint8List qrPng = await scanner.generateBarCode('https://github.com/wu9007/qrcode_scanner');
Call Returns
scan({color, hint}) Decoded string, or null if the user cancels. Camera only — not the gallery. color / hint optional
scanPhoto() System picker → decode, or null if cancelled
scanPath(path) Decode a local file
scanBytes(bytes) Decode image bytes
generateBarCode(code) QR PNG as Uint8List (UTF-8 payload)

That is the whole API. There is no widget, no scan-area crop, no front-camera switch, no stream, no format filter. Overlay is cosmetic — decode still uses the full frame.

Copy this button #

Drop-in widget (also in example/lib/scan_button.dart):

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:qrscan/qrscan.dart' as scanner;

class ScanButton extends StatelessWidget {
  const ScanButton({
    super.key,
    this.looks = scanner.ScanLooks.wechat,
    this.label = '扫一扫',
    this.onCode,
  });

  final scanner.ScanLooks looks;
  final String label;
  final ValueChanged<String>? onCode;

  Future<void> _scan(BuildContext context) async {
    try {
      final String? code = await scanner.scan(looks: looks);
      if (code != null) onCode?.call(code);
    } on PlatformException catch (e) {
      if (!context.mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(e.code)),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return FilledButton(
      style: FilledButton.styleFrom(
        backgroundColor: looks.color,
        foregroundColor: Colors.white,
        minimumSize: const Size.fromHeight(48),
      ),
      onPressed: () => _scan(context),
      child: Text(label),
    );
  }
}

// WeChat:  ScanButton(looks: ScanLooks.wechat, label: '扫一扫', onCode: ...)
// Alipay:  ScanButton(looks: ScanLooks.alipay, label: '扫码', onCode: ...)
// Own:     ScanButton(looks: ScanLooks(color: Color(0xFFFF6A00), hint: '对准条码'), ...)

Errors from scan() #

Cancel is null. Real failures throw PlatformException:

Dart constant code When
CameraAccessDenied PERMISSION_NOT_GRANTED User denied camera
CameraStartFailed CAMERA_START_FAILED No back camera / driver error
CameraInUse CAMERA_IN_USE Another app already holds the camera
NoActivity NO_ACTIVITY Plugin has no Activity / cannot present

Decoder #

QR is tried first (with TRY_HARDER), then other 2D, then 1D. A dense QR is not returned as UPC-E. There is no formats: argument — if you must restrict symbologies, use mobile_scanner.

Latin-1 QR (ISO-8859-1, no ECI) is not forced to UTF-8. Byte segments that are valid UTF-8 with high bits stay UTF-8 (typical Chinese QR). generateBarCode writes UTF-8.

Decoder order is covered by tool/decoder-harness (63 fixtures in CI). Album photos that are stored rotated are retried at 90° steps on Android and iOS. iOS also honors EXIF orientation and inverts like Android.

When not to use this #

You want Use instead
Embedded preview / scan window / overlay / continuous scan / web / desktop mobile_scanner
Only 1D / only QR / a format list mobile_scanner formats:
Camera on a phone or a PDA (rear camera) this plugin — scan()
Industrial PDA laser that broadcasts an Intent pda_scanner
Gun set to keyboard (HID) wedge Any TextField. No plugin.

Three mutually exclusive paths: camera one-shot (this plugin, including PDA cameras) · OEM laser broadcast (pda_scanner) · HID keyboard (nothing). Mixing them is how field apps “break”.

0.3 → 0.4 #

Before After
Android only, embedding v1 leftovers Android + iOS, embedding v2
com.github.leyan95:android-zxingLibrary (JitPack, often missing) com.google.zxing:core:3.5.3 + CameraX 1.4
iOS was a TODO Vision actually scans
Storage permissions Camera + system photo picker
SDK <3.0.0 Dart 3 / Flutter 3.10+
Torch crash on devices with no flash CameraX enableTorch, toast if unavailable
Scanner locked portrait (tablets / landscape broken) Follows device rotation; overlay recenters
Dense QR read as UPC-E QR (TRY_HARDER) before 1D
Latin-1 QR forced to UTF-8 BYTE_SEGMENTS → ISO-8859-1 unless valid UTF-8
Camera busy / bind fail → black Activity CAMERA_IN_USE / CAMERA_START_FAILED to Dart

Public Dart API is unchanged. The two new error constants are optional.

License #

MIT. Created by Shusheng.

391
likes
140
points
325
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

One-shot Flutter QR/barcode scanner: open camera, first decode, string back. Android CameraX+ZXing, iOS Vision. Not a widget.

Homepage
Repository (GitHub)
View/report issues

Topics

#qr #barcode #qr-code #camera #scanner

License

MIT (license)

Dependencies

flutter

More

Packages that depend on qrscan

Packages that implement qrscan