An open API service indexing awesome lists of open source software.

https://github.com/shariaralphabyte/ultra_qr_scanner

Ultra QR Scanner ๐Ÿ“ฑโšก pub package GitHub Platform Ultra-fast, low-latency QR code scanner plugin for Flutter with native camera preview and performance optimization.
https://github.com/shariaralphabyte/ultra_qr_scanner

flutter flutter-dependencies flutter-package flutter-plugin

Last synced: 3 months ago
JSON representation

Ultra QR Scanner ๐Ÿ“ฑโšก pub package GitHub Platform Ultra-fast, low-latency QR code scanner plugin for Flutter with native camera preview and performance optimization.

Awesome Lists containing this project

README

          

# Ultra QR Scanner ๐Ÿ“ฑโšก
[![pub package](https://img.shields.io/pub/v/ultra_qr_scanner.svg)](https://pub.dev/packages/ultra_qr_scanner)
[![GitHub](https://img.shields.io/github/license/shariaralphabyte/screen_secure)](https://github.com/shariaralphabyte/ultra_qr_scanner/blob/main/LICENSE)
[![Platform](https://img.shields.io/badge/platform-Android%20%7C%20iOS-blue.svg)](https://pub.dev/packages/ultra_qr_scanner)

**Ultra-fast, low-latency QR code scanner plugin for Flutter with native camera preview and performance optimization.**

๐ŸŽฏ **Goal**: Open scanner โ†’ show camera preview โ†’ detect QR instantly โ†’ return result โ†’ done โœ…

## โœจ Features

๐Ÿš€ **Ultra-fast startup** - Preload scanner during app initialization for instant access
โšก **Native performance** - CameraX (Android) + AVCapture (iOS) with platform views
๐Ÿ“ธ **Live camera preview** - Real-time camera feed with customizable overlay
๐Ÿค– **Auto-start scanning** - Optional automatic scanning when widget appears
๐Ÿ‘† **Manual controls** - User-controlled start/stop with customizable UI
๐Ÿ“ฑ **Simple API** - Single scan or continuous stream modes
๐Ÿ”ฆ **Flash control** - Toggle flashlight on supported devices
๐Ÿ“ท **Camera switching** - Front/back camera support
๐Ÿ›ก๏ธ **Production ready** - Comprehensive error handling & memory management
๐ŸŽจ **Customizable UI** - Custom overlays, buttons, and scanning frames

## ๐Ÿš€ Performance Optimizations

| Feature | Description | Benefit |
|---------|-------------|---------|
| **Native Camera APIs** | CameraX on Android, AVCaptureSession on iOS | Maximum hardware utilization |
| **Platform Views** | Native camera preview rendering | Seamless integration with Flutter UI |
| **ML Frameworks** | MLKit Barcode Scanning (Android), Vision API (iOS) | Optimized QR detection |
| **Threading** | Background processing with main thread UI updates | Non-blocking UI performance |
| **Auto-start Mode** | Begin scanning immediately when widget appears | Zero user interaction needed |
| **Auto-stop** | Immediate camera shutdown after detection | Zero waste of resources |
| **Preloading** | Initialize during app startup | < 50ms to first scan |
| **Memory Management** | Proper cleanup and lifecycle handling | Leak-free operation |

## ๐Ÿ“Š Benchmarks

| Metric | Target | Typical Result |
|--------|--------|----------------|
| Cold Start Time | < 300ms | ~200ms |
| Auto-Start Time | < 100ms | ~50ms |
| QR Detection Speed | < 100ms | ~50ms |
| Memory Usage | < 50MB | ~35MB |
| Battery Impact | Minimal | 2-3% per hour |
| Frame Rate | 30 FPS | Stable 30 FPS |

## ๐Ÿ›  Installation

Add to your `pubspec.yaml`:

```yaml
dependencies:
ultra_qr_scanner: ^3.0.3
```

```bash
flutter pub get
```

## ๐Ÿƒโ€โ™‚๏ธ Quick Start

### 1. Initialize Scanner (Optional but Recommended)

```dart
import 'package:ultra_qr_scanner/ultra_qr_scanner.dart';

// Best practice: Initialize during app startup for faster access
void main() async {
WidgetsFlutterBinding.ensureInitialized();

// Request camera permission and prepare scanner
final hasPermission = await UltraQrScanner.requestPermissions();
if (hasPermission) {
await UltraQrScanner.prepareScanner();
}

runApp(MyApp());
}
```

### 2. Auto-Start Scanner (Recommended for Quick Scanning)

```dart
import 'package:ultra_qr_scanner/ultra_qr_scanner_widget.dart';

class QuickScannerPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Quick QR Scanner')),
body: Container(
width: 300,
height: 300,
child: UltraQrScannerWidget(
onCodeDetected:(code , type) {
print('QR Code detected: $qrCode');
Navigator.pop(context, qrCode);
},
showFlashToggle: true, // Show flash button
autoStop: true, // Auto-stop after detection
showStartStopButton: false, // Hide manual controls
autoStart: true, // Start scanning immediately
),
),
);
}
}
```

### 3. Manual Scanner (Traditional User-Controlled)

```dart
class ManualScannerPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Manual QR Scanner')),
body: Container(
width: 300,
height: 300,
child: UltraQrScannerWidget(
onCodeDetected:(code , type) {
print('QR Code detected: $qrCode');
Navigator.pop(context, qrCode);
},
showFlashToggle: true, // Show flash button
autoStop: true, // Auto-stop after detection
showStartStopButton: true, // Show start/stop button
autoStart: false, // Wait for user to start
),
),
);
}
}
```

### 4. Programmatic Scanning (Alternative)

```dart
// Single scan
Future scanQRCode() async {
try {
final qrCode = await UltraQrScanner.scanOnce();
if (qrCode != null) {
print('Scanned QR Code: $qrCode');
}
} catch (e) {
print('Scan failed: $e');
}
}

// Continuous scanning stream
StreamSubscription? _scanSubscription;

void startContinuousScanning() {
_scanSubscription = UltraQrScanner.scanStream().listen(
(qrCode) {
print('Detected QR Code: $qrCode');
},
onError: (error) {
print('Scan error: $error');
},
);
}

void stopScanning() {
_scanSubscription?.cancel();
UltraQrScanner.stopScanner();
}
```

## ๐ŸŽจ Widget Customization

### Scanning Modes

The widget supports two main scanning modes:

#### ๐Ÿค– **Auto-Start Mode** (Instant Scanning)
Perfect for quick scanning scenarios where you want immediate results:

```dart
UltraQrScannerWidget(
onCodeDetected:(code , type) => handleQRCode(qrCode),
autoStart: true, // Start scanning immediately
showStartStopButton: false, // Hide manual controls
autoStop: true, // Stop after first detection
showFlashToggle: true, // Optional flash control
)
```

#### ๐Ÿ‘† **Manual Mode** (User-Controlled)
Traditional scanning with user controls:

```dart
UltraQrScannerWidget(
onCodeDetected:(code , type) => handleQRCode(qrCode),
autoStart: false, // Wait for user action
showStartStopButton: true, // Show start/stop button
autoStop: true, // Stop after first detection
showFlashToggle: true, // Optional flash control
)
```

#### ๐Ÿ”„ **Hybrid Mode** (Best of Both)
Auto-start with manual controls available:

```dart
UltraQrScannerWidget(
onCodeDetected:(code , type) => handleQRCode(qrCode),
autoStart: true, // Start immediately
showStartStopButton: true, // But also show controls
autoStop: false, // Continuous scanning
showFlashToggle: true, // Flash control
)
```

### Widget Configuration Options

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `onQrDetected` | `Function(String)` | **Required** | Callback when QR code is detected |
| `autoStart` | `bool` | `false` | Start scanning automatically when widget appears |
| `showStartStopButton` | `bool` | `true` | Show/hide the start/stop scan button |
| `autoStop` | `bool` | `true` | Stop scanning after first QR code detection |
| `showFlashToggle` | `bool` | `false` | Show/hide flash/torch toggle button |
| `overlay` | `Widget?` | `null` | Custom overlay widget (uses default if null) |

### Custom Overlay Example

```dart
UltraQrScannerWidget(
onCodeDetected:(code , type) (qrCode) => handleQRCode(qrCode),
autoStart: true,
showStartStopButton: false,
overlay: Stack(
children: [
// Semi-transparent background
Container(color: Colors.black54),

// Custom scanning frame
Center(
child: Container(
width: 250,
height: 250,
decoration: BoxDecoration(
border: Border.all(color: Colors.green, width: 4),
borderRadius: BorderRadius.circular(20),
),
child: Stack(
children: [
// Corner decorations
...buildCornerDecorations(),

// Center dot
Center(
child: Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
),
),
),
],
),
),
),

// Custom instructions
Positioned(
top: 60,
left: 0,
right: 0,
child: Column(
children: [
Icon(Icons.qr_code_scanner, color: Colors.white, size: 48),
SizedBox(height: 16),
Text(
'Scan QR Code',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
'Position the QR code within the frame',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white70,
fontSize: 16,
),
),
],
),
),
],
),
)
```

### Usage Scenarios

#### ๐Ÿš€ **Instant QR Scanner (No UI Friction)**
```dart
// Perfect for: Payment apps, quick actions, URL scanning
UltraQrScannerWidget(
onCodeDetected:(code , type) => processPayment(code),
autoStart: true,
showStartStopButton: false,
autoStop: true,
)
```

#### ๐Ÿ“ท **Traditional Scanner (User Control)**
```dart
// Perfect for: Document scanning, batch operations, careful scanning
UltraQrScannerWidget(
onCodeDetected:(code , type) => addToList(code),
autoStart: false,
showStartStopButton: true,
autoStop: false, // Continuous scanning
)
```

#### ๐Ÿ” **Full-Featured Scanner**
```dart
// Perfect for: Professional apps, feature-rich scanning
UltraQrScannerWidget(
oonCodeDetected:(code , type) => handleCode(code),
autoStart: true,
showStartStopButton: true,
showFlashToggle: true,
autoStop: true,
)
```

## ๐Ÿ”ง Advanced Features

### Flash Control

```dart
// Toggle flashlight
await UltraQrScanner.toggleFlash(true); // Turn on
await UltraQrScanner.toggleFlash(false); // Turn off
```

### Camera Switching

```dart
// Switch between front and back camera
await UltraQrScanner.switchCamera('front'); // Use front camera
await UltraQrScanner.switchCamera('back'); // Use back camera
```

### Scanner Lifecycle Management

```dart
// Check if scanner is ready
if (UltraQrScanner.isPrepared) {
// Ready to scan
} else {
// Need to prepare first
await UltraQrScanner.prepareScanner();
}

// Manually stop scanner
await UltraQrScanner.stopScanner();
```

## ๐Ÿ”’ Permissions Setup

### Android

Add to `android/app/src/main/AndroidManifest.xml`:

```xml

```

Add to `android/app/build.gradle`:

```gradle
dependencies {
implementation 'androidx.camera:camera-camera2:1.2.3'
implementation 'androidx.camera:camera-lifecycle:1.2.3'
implementation 'androidx.camera:camera-view:1.2.3'
implementation 'com.google.mlkit:barcode-scanning:17.2.0'
}
```

### iOS

Add to `ios/Runner/Info.plist`:

```xml
NSCameraUsageDescription
Camera access is required to scan QR codes
```

Ensure minimum iOS version 11.0+ in `ios/Podfile`:

```ruby
platform :ios, '11.0'
```

## ๐Ÿ“ฑ Platform Support

| Platform | Camera API | ML Framework | Preview | Min Version | Status |
|----------|------------|--------------|---------|-------------|--------|
| **Android** | CameraX + PreviewView | MLKit Barcode | โœ… Native | API 21 (Android 5.0) | โœ… Fully Supported |
| **iOS** | AVCapture + PreviewLayer | Vision Framework | โœ… Native | iOS 11.0+ | โœ… Fully Supported |

## ๐ŸŽฏ Complete Example App

```dart
import 'package:flutter/material.dart';
import 'package:ultra_qr_scanner/ultra_qr_scanner.dart';
import 'package:ultra_qr_scanner/ultra_qr_scanner_widget.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Ultra QR Scanner Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: HomePage(),
);
}
}

class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}

class _HomePageState extends State {
String? lastQRCode;
bool useAutoMode = true;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ultra QR Scanner'),
centerTitle: true,
actions: [
IconButton(
icon: Icon(useAutoMode ? Icons.auto_awesome : Icons.touch_app),
onPressed: () {
setState(() {
useAutoMode = !useAutoMode;
});
},
tooltip: useAutoMode ? 'Switch to Manual' : 'Switch to Auto',
),
],
),
body: Center(
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Mode indicator
Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: useAutoMode ? Colors.green.shade100 : Colors.blue.shade100,
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: useAutoMode ? Colors.green : Colors.blue,
width: 2,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
useAutoMode ? Icons.flash_auto : Icons.touch_app,
color: useAutoMode ? Colors.green.shade700 : Colors.blue.shade700,
size: 20,
),
SizedBox(width: 8),
Text(
useAutoMode ? '๐Ÿš€ AUTO MODE' : '๐Ÿ‘† MANUAL MODE',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: useAutoMode ? Colors.green.shade700 : Colors.blue.shade700,
),
),
],
),
),

SizedBox(height: 10),

Text(
useAutoMode
? 'Scanning starts automatically when camera opens'
: 'Tap the Start Scan button to begin scanning',
style: TextStyle(fontSize: 16),
textAlign: TextAlign.center,
),

SizedBox(height: 20),

// Scanner Widget
Container(
width: 300,
height: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
blurRadius: 10,
offset: Offset(0, 4),
),
],
),
child: UltraQrScannerWidget(
onCodeDetected:(code , type) {
setState(() {
lastQRCode = code;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Scanned: $code'),
backgroundColor: Colors.green,
behavior: SnackBarBehavior.floating,
duration: Duration(seconds: 2),
),
);
},
showFlashToggle: true,
autoStop: true,
// Dynamic mode switching
autoStart: useAutoMode,
showStartStopButton: !useAutoMode,
),
),

SizedBox(height: 20),

// Results Display
Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey.shade300),
),
child: Column(
children: [
Text(
'Last Scanned Code:',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.grey.shade700,
),
),
SizedBox(height: 8),
Text(
lastQRCode ?? 'No QR code scanned yet',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.center,
),
],
),
),

SizedBox(height: 20),

// Mode comparison
Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'๐Ÿ’ก Scanning Modes:',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
SizedBox(height: 8),
Text('๐Ÿš€ Auto Mode: Instant scanning, no buttons needed'),
Text('๐Ÿ‘† Manual Mode: User-controlled start/stop'),
Text('โšก Both modes: Auto-stop after detection'),
Text('๐Ÿ”ฆ Flash control available in both modes'),
Text('๐Ÿ“ท Camera switching available in both modes'),
],
),
),
],
),
),
),
);
}
}
```

## ๐Ÿ” Error Handling

```dart
try {
await UltraQrScanner.prepareScanner();
final result = await UltraQrScanner.scanOnce();
// Handle success
} on UltraQrScannerException catch (e) {
// Handle scanner-specific errors
switch (e.code) {
case 'PERMISSION_DENIED':
// Show permission dialog
break;
case 'NO_CAMERA':
// Handle no camera available
break;
case 'NOT_PREPARED':
// Scanner needs initialization
break;
default:
print('Scanner error: ${e.message}');
}
} catch (e) {
// Handle other errors
print('General error: $e');
}
```

## ๐Ÿš€ Performance Tips

### 1. **Choose the Right Mode for Your Use Case**
```dart
// โœ… GOOD: Auto-mode for quick actions (payments, URLs)
UltraQrScannerWidget(
autoStart: true,
showStartStopButton: false,
autoStop: true,
)

// โœ… GOOD: Manual mode for careful scanning (documents, batch)
UltraQrScannerWidget(
autoStart: false,
showStartStopButton: true,
autoStop: false,
)
```

### 2. **Initialize Early (Optional but Recommended)**
```dart
// โœ… GOOD: Initialize during app startup for faster access
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (await UltraQrScanner.requestPermissions()) {
await UltraQrScanner.prepareScanner();
}
runApp(MyApp());
}
```

### 3. **Use Widget for Better Performance**
```dart
// โœ… RECOMMENDED: Use UltraQrScannerWidget
UltraQrScannerWidget(
onQrDetected: (code) => handleCode(code),
autoStart: true,
)

// โŒ ALTERNATIVE: Programmatic scanning (requires more setup)
final result = await UltraQrScanner.scanOnce();
```

## ๐Ÿ› Troubleshooting

### Common Issues

**1. Camera Permission Denied**
- Ensure permissions are added to AndroidManifest.xml (Android) and Info.plist (iOS)
- Request permissions before using scanner
- Test on physical device (camera not available in simulators)

**2. Black Screen in Auto Mode**
- Updated in v2.1.0 with better initialization timing
- Ensure proper widget constraints (width/height)
- Check console for platform view creation logs

**3. QR Codes Not Detected**
- Ensure good lighting conditions
- Check if QR code is clearly visible and not damaged
- Verify QR code format is supported
- Try manual mode if auto-mode has issues

**4. Controls Not Responding**
- Verify widget configuration parameters
- Check if scanner is properly initialized
- Ensure proper error handling in callbacks

### Platform-Specific Issues

**Android:**
- Minimum SDK version 21+ required
- Add camera dependencies to build.gradle
- Test on multiple device orientations

**iOS:**
- Minimum iOS 11.0+ required
- Test on physical device only (simulator has no camera)
- Ensure proper Info.plist configuration

## ๐Ÿ“ˆ What's New

### [3.0.3] - Latest
- ๐Ÿค– **Auto-start scanning mode** - Begin scanning immediately when widget appears
- ๐Ÿค– **Support Google 16KB Page size** - Support Google 16KB Page size
- ๐Ÿ‘† **Enhanced manual controls** - Better user-controlled scanning experience
- ๐ŸŽ›๏ธ **Flexible UI options** - Show/hide start/stop button independently
- โฑ๏ธ **Improved initialization** - Better timing for auto-start mode
- ๐Ÿ”ง **Better error handling** - More robust initialization and state management
- ๐Ÿ“ฑ **Enhanced examples** - Complete auto/manual mode demonstrations

### [2.0.0] - Previous Major Release
- ๐ŸŽ‰ **Live camera preview** with native platform views
- ๐Ÿ“ธ **Camera switching** between front/back cameras
- ๐Ÿ”ฆ **Flash/torch control** for better scanning in low light
- ๐ŸŽจ **Customizable overlays** and scanning frames
- ๐Ÿงน **Improved memory management** and lifecycle handling
- ๐Ÿš€ **Better performance** with native camera integration

## ๐Ÿค Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.

### Development Setup

```bash
git clone https://github.com/shariaralphabyte/ultra_qr_scanner.git
cd ultra_qr_scanner
flutter pub get
cd example
flutter run
```

### Running Tests

```bash
flutter test # Unit tests
flutter drive --target=test_driver/app.dart # Integration tests
```

## ๐Ÿ“„ License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## ๐Ÿ™ Acknowledgments

- [MLKit Barcode Scanning](https://developers.google.com/ml-kit/vision/barcode-scanning) for Android QR detection
- [Vision Framework](https://developer.apple.com/documentation/vision) for iOS QR detection
- [CameraX](https://developer.android.com/camerax) for Android camera handling
- [AVFoundation](https://developer.apple.com/av-foundation/) for iOS camera management
- Flutter team for platform views and native integration

## ๐Ÿ“ž Support

- ๐Ÿ“š [Documentation](https://pub.dev/documentation/ultra_qr_scanner/latest/)
- ๐Ÿ› [Issue Tracker](https://github.com/shariaralphabyte/ultra_qr_scanner/issues)
- ๐Ÿ’ฌ [Discussions](https://github.com/shariaralphabyte/ultra_qr_scanner/discussions)
- ๐Ÿ“ง Email: contact.shariar.cse@gmail.com

---


Made with โค๏ธ for the Flutter community


If this package helped you, please consider giving it a โญ on GitHub and a ๐Ÿ‘ on pub.dev