/home/u882525311/domains/blog.codevisionarystudio.com/public_html/wp-content/mu-plugins Building an Event Check-In App with Flutter and a Mobile Scanner – blog.codevisionarystudio.com

Building an Event Check-In App with Flutter and a Mobile Scanner

Hey there, Flutter enthusiasts! Have you ever been to an event where the check-in process was a mess, with long lines and delays? I certainly have, and it’s always frustrating. That’s why I decided to tackle this common problem by building an event check-in app using Flutter and the mobile_scanner package. Imagine breezing through event check-ins by simply scanning a QR code—no more paper tickets, no more waiting. Plus, we’ll be storing the scanned data in Firebase Firestore in real-time, so it’s not only efficient but also highly reliable. Let’s dive into this exciting project and make event check-ins a breeze!

Setting Up the Environment

Before we jump into the code, let’s set up our Flutter environment. If you haven’t already, make sure you have Flutter installed on your machine. We’ll also need to add the necessary dependencies to our pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  mobile_scanner: ^1.0.0 
  firebase_core: ^2.0.0
  cloud_firestore: ^3.0.0
// You can chose to use latest version if available
Once you have your dependencies set, run 
flutter pub get 
This will install the required dependencies.

Creating the QR Scanner Widget

First, let’s create a custom QR scanner widget. This widget will use the mobile_scanner package to scan QR codes and pass the scanned data to a callback function. Here’s the complete code for our QrScannerWidget:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';

class QrScannerWidget extends StatefulWidget {
  final Function(String)? qrCodeCallback;

  const QrScannerWidget({Key? key, this.qrCodeCallback}) : super(key: key);

  @override
  QrScannerWidgetState createState() => QrScannerWidgetState();
}

class QrScannerWidgetState extends State<QrScannerWidget> with WidgetsBindingObserver {
  final MobileScannerController controller = MobileScannerController();
  StreamSubscription<BarcodeCapture>? _subscription;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _subscription = controller.barcodes.listen(_handleBarcode);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _subscription?.cancel();
    _subscription = null;
    controller.dispose();
    super.dispose();
  }

  void _handleBarcode(BarcodeCapture capture) {
    final Barcode? barcode = capture.barcodes.firstOrNull;
    if (barcode != null) {
      widget.qrCodeCallback?.call(barcode.rawValue ?? '');
    }
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (controller.value.isRunning) {
      switch (state) {
        case AppLifecycleState.resumed:
          controller.start();
          break;
        case AppLifecycleState.inactive:
        case AppLifecycleState.paused:
          controller.stop();
          break;
        case AppLifecycleState.detached:
          break;
        case AppLifecycleState.hidden:
          break;
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return MobileScanner(
      controller: controller,
      onDetect: _handleBarcode,
    );
  }
}

This widget sets up the MobileScannerController, listens for barcode captures, and handles the app lifecycle states to start and stop the scanner appropriately. Now, let’s integrate this widget into our main app.

Integrating the QR Scanner into the App

We’ll create a basic Flutter app with a button to start the scanner and display the scanned QR code data. Here’s how you can add the QrScannerWidget to your app:

import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Event Check-In')),
        body: ScannerScreen(),
      ),
    );
  }
}

class ScannerScreen extends StatefulWidget {
  @override
  _ScannerScreenState createState() => _ScannerScreenState();
}

class _ScannerScreenState extends State<ScannerScreen> {
  String scannedData = '';

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(scannedData.isEmpty ? 'Scan a QR code' : 'Scanned Data: $scannedData'),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              showDialog(
                context: context,
                builder: (_) => Dialog(
                  child: SizedBox(
                    height: 300,
                    child: MobileScanner(
                      controller: MobileScannerController(),
                      onDetect: (barcode, args) {
                        if (barcode.barcodes.isNotEmpty) {
                          setState(() {
                            scannedData = barcode.barcodes.first.rawValue ?? 'No Data';
                          });
                          Navigator.pop(context);
                        }
                      },
                    ),
                  ),
                ),
              );
            },
            child: Text('Start Scanner'),
          ),
        ],
      ),
    );
  }
}

In this code, we create a ScannerScreen widget that includes a button to open the QR scanner and display the scanned data. We use the MobileScanner widget from the mobile_scanner package to scan QR codes.

Enhancing the Scanner UI

To provide a better user experience, let’s make the scanner appear as a centered overlay when activated. Here’s how we can enhance our UI:

@override
Widget build(BuildContext context) {
  return Stack(
    children: [
      // Other UI elements can go here
      if (!controller.value.isRunning)
        Positioned.fill(
          child: Align(
            alignment: Alignment.center,
            child: ClipRect(
              child: OverflowBox(
                alignment: Alignment.center,
                child: SizedBox(
                  width: MediaQuery.of(context).size.width * 0.8 + 20,
                  height: MediaQuery.of(context).size.width * 0.8 * 0.5 + 20,
                  child: QrScannerWidget(
                    qrCodeCallback: (code) {
                      setState(() {
                        scannedData = code;
                      });
                    },
                  ),
                ),
              ),
            ),
          ),
        ),
    ],
  );
}

This code snippet ensures that the scanner appears in a focused area in the center of the screen, improving user interaction.

Integrating Firebase Firestore

Now, let’s integrate Firebase Firestore to store the scanned data. First, set up Firebase in your Flutter app by following the instructions on the Firebase website. Then, initialize Firebase in your main.dart:

import 'package:firebase_core/firebase_core.dart';

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

<strong>Next, add functionality to save scanned data to Firestore:</strong>

import 'package:cloud_firestore/cloud_firestore.dart';

void saveScannedData(String data) async {
  await FirebaseFirestore.instance.collection('attendees').add({
    'qr_data': data,
    'timestamp': FieldValue.serverTimestamp(),
  });
}

<strong>Modify the QrScannerWidget to save the data after scanning:</strong>
void _handleBarcode(BarcodeCapture capture) {
  final Barcode? barcode = capture.barcodes.firstOrNull;
  if (barcode != null) {
    final data = barcode.rawValue ?? '';
    widget.qrCodeCallback?.call(data);
    saveScannedData(data);
  }
}

With this integration, each scanned QR code is stored in Firebase Firestore, making it accessible in real-time across multiple devices.

Handling Common Challenges

Camera Permissions
Ensure that your app requests camera permissions properly. Update AndroidManifest.xml and Info.plist:

For Android:

<uses-permission android:name="android.permission.CAMERA"/>

For iOS, add the following to Info.plist:

<key>NSCameraUsageDescription</key>

<string>We need camera access to scan QR codes.</string>
Optimizing Performance

Optimize scanning performance by adjusting camera settings and handling various lighting conditions effectively. You can also provide feedback to the user if the QR code is not readable.

Error Handling

Implement error handling to deal with potential issues such as unreadable codes or no camera access. Here’s an example of adding error messages:

void _handleBarcode(BarcodeCapture capture) {
  final Barcode? barcode = capture.barcodes.firstOrNull;
  if (barcode != null) {
    final data = barcode.rawValue ?? '';
    widget.qrCodeCallback?.call(data);
    saveScannedData(data);
  } else {
    setState(() {
      scannedData = 'Error scanning QR code';
    });
  }
}

Conclusion

And there you have it! We’ve built a functional event check-in app using Flutter and the mobile_scanner package. This app scans QR codes and displays the scanned data, providing a smooth and efficient check-in process.

You can extend this app by integrating a database to store scanned data for future reference or adding additional features like attendee verification and real-time updates. The possibilities are endless!

Happy coding, and I hope you find this tutorial helpful! If you have any questions or feedback, please leave a comment below. Stay tuned for more Flutter tutorials!


Comments

One response to “Building an Event Check-In App with Flutter and a Mobile Scanner”

  1. Hi, this is a comment.
    To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard.
    Commenter avatars come from Gravatar.

Leave a Reply

Your email address will not be published. Required fields are marked *