Integrating our Flutter Barcode Scanner SDK – a step-by-step tutorial

Yurii October 3, 2024 11 mins read
app store

With our Flutter Barcode Scanner package, integrating barcode scanning functionalities into your cross-platform app written in Dart is a breeze. This tutorial will guide you through the process in just a few minutes, leveraging our Ready-to-Use UI Components to make the setup fast and seamless.

Setting up a Flutter app to scan 1D or 2D barcodes is straightforward. We’re going to follow these steps:

  1. Prepare the project.
  2. Install the SDK.
  3. Initialize the SDK.
  4. Implement the scanning modules.
  5. Start scanning barcodes!

With the SDK’s Ready-to-Use UI Components, you can even use an AR overlay to display multiple barcodes’ contents directly in the viewfinder, enhancing the scanning experience.

Flutter Barcode Scanner package tutorial

Requirements

To develop Flutter applications for Android and iOS, ensure you have the following:

  1. Flutter SDK: Download the latest version for your OS.
  2. Dart SDK: No separate installation needed, since it’s integrated with Flutter.
  3. The right IDEs for your target platforms:
    1. Android Studio to develop for Android. It includes the Android SDK and AVD Manager.
    2. Xcode for iOS development on macOS.
    3. You can also use Visual Studio Code, which supports Flutter plugins.

⚠️ A note to Windows users: A Mac is necessary to build and test iOS apps. Consider using a remote Mac service or a physical Mac as a build server.

1. Preparing the project

First, create a new directory for your project and navigate into it:

mkdir test-flutter
cd test-flutter

Create a new Flutter project:

flutter create test_barcode_scanner
cd test_barcode_scanner

Since we need access to the device camera to scan barcodes, let’s add the necessary camera permissions for Android and iOS.

Add camera permissions to android/app/src/main/AndroidManifest.xml:

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

And in ios/Runner/Info.plist:

<key>NSCameraUsageDescription</key>
<string>We need camera access to scan barcodes.</string>

2. Installing the SDK

Add the Scanbot Flutter Barcode Scanner package to your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
	barcode_scanner: ^5.1.0

Run the following commnand to install the packages:

flutter pub get

💡 Please refer to our changelog for the latest version of the Barcode Scanner SDK.

Now that the project is set up, we can integrate the barcode scanning functionalities.

3. Initializing the SDK

Initialize the SDK in main.dart:

import 'package:flutter/material.dart';
import 'package:barcode_scanner/scanbot_barcode_sdk_v2.dart';

const BARCODE_SDK_LICENSE_KEY = "";

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
    _initScanbotSdk();
  }

  Future<void> _initScanbotSdk() async {
    var config = ScanbotSdkConfig(
      licenseKey: BARCODE_SDK_LICENSE_KEY,
      loggingEnabled: true,
    );

    try {
      await ScanbotBarcodeSdk.initScanbotSdk(config);
      print('Scanbot SDK initialized successfully');
    } catch (e) {
      print('Error initializing Scanbot SDK: $e');
    }
  }
  
  @override
  Widget build(BuildContext context) {
  ...
}

💡 Without a license key, our SDK only runs for 60 seconds per session. This is more than enough for the purposes of our tutorial, but if you like, you can generate a license key using your applicationId.

4. Implementing the scanning modes

The SDK’s RTU UI components make it easy to deploy our Flutter Barcode Scanner package’s different scanning modes in your app. Let’s start with the simplest use case: single-barcode scanning.

Implement the barcode scanning functionality:

void _startBarcodeScanning() async {
  try {
    // Create the default configuration object.
    var configuration = BarcodeScannerConfiguration();

    // Initialize the use case for single scanning.
    var scanningMode = SingleScanningMode();
    // Enable and configure the confirmation sheet.
    scanningMode.confirmationSheetEnabled = true;
    scanningMode.sheetColor = ScanbotColor("#FFFFFF");

    // Hide/unhide the barcode image.
    scanningMode.barcodeImageVisible = true;

    // Configure the barcode title of the confirmation sheet.
    scanningMode.barcodeTitle.visible = true;
    scanningMode.barcodeTitle.color = ScanbotColor("#000000");

    // Configure the barcode subtitle of the confirmation sheet.
    scanningMode.barcodeSubtitle.visible = true;
    scanningMode.barcodeSubtitle.color = ScanbotColor("#000000");

    // Configure the cancel button of the confirmation sheet.
    scanningMode.cancelButton.text = "Close";
    scanningMode.cancelButton.foreground.color = ScanbotColor("#C8193C");
    scanningMode.cancelButton.background.fillColor = ScanbotColor("#00000000");

    // Configure the submit button of the confirmation sheet.
    scanningMode.submitButton.text = "Submit";
    scanningMode.submitButton.foreground.color = ScanbotColor("#FFFFFF");
    scanningMode.submitButton.background.fillColor = ScanbotColor("#C8193C");

    // Configure other parameters, pertaining to single-scanning mode as needed.

    configuration.useCase = scanningMode;

    // Set an array of accepted barcode types.
    // configuration.recognizerConfiguration.barcodeFormats = [
    //   scanbotV2.BarcodeFormat.AZTEC,
    //   scanbotV2.BarcodeFormat.PDF_417,
    //   scanbotV2.BarcodeFormat.QR_CODE,
    //   scanbotV2.BarcodeFormat.MICRO_QR_CODE,
    //   scanbotV2.BarcodeFormat.MICRO_PDF_417,
    //   scanbotV2.BarcodeFormat.ROYAL_MAIL,
    ///  .....
    // ];

    // Configure other parameters as needed.
  
    var result = await ScanbotBarcodeSdk.startBarcodeScanner(configuration);

    if(result.operationResult == OperationResult.SUCCESS)
    {
      // TODO: present barcode result as needed
      print(result.value?.items.first.type?.name);
    }
  } catch (e) {
    print('Error: $e');
  }
}

Now let’s go to the build method and add the button on the start screen so it calls our _startBarcodeScanning method when clicked:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Barcode Scanner'),
    ),
    body: Center(
      child: ElevatedButton(
        onPressed: _startBarcodeScanning,
        style: ElevatedButton.styleFrom(
          padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 40),
          textStyle: const TextStyle(fontSize: 18),
        ),
        child: const Text("Start single-barcode scanning"),
      ),
    ),
  );
}

If you like, you can build and run the app to see if everything is working correctly so far:

flutter run
Single-barcode scanning with the Flutter Barcode Scanner package tutorial

In the next step, we’re going to insert both the multi-barcode scanning and the AR overlay modules.

Let’s create two more methods, _startBarcodeMultiScanning and _startAROverlay:

void _startBarcodeMultiScanning() async {
  try {
    // Create the default configuration object.
    var configuration = BarcodeScannerConfiguration();

    // Initialize the use case for multiple scanning.
    var scanningMode = MultipleScanningMode();

    // Set the counting mode.
    scanningMode.mode = MultipleBarcodesScanningMode.COUNTING;

    // Set the sheet mode for the barcodes preview.
    scanningMode.sheet.mode = SheetMode.COLLAPSED_SHEET;

    // Set the height for the collapsed sheet.
    scanningMode.sheet.collapsedVisibleHeight = CollapsedVisibleHeight.LARGE;

    // Enable manual count change.
    scanningMode.sheetContent.manualCountChangeEnabled = true;

    // Set the delay before same barcode counting repeat.
    scanningMode.countingRepeatDelay = 1000;

    // Configure the submit button.
    scanningMode.sheetContent.submitButton.text = "Submit";
    scanningMode.sheetContent.submitButton.foreground.color =
        ScanbotColor("#000000");

    // Configure other parameters, pertaining to multiple-scanning mode as needed.

    configuration.useCase = scanningMode;

    // Set an array of accepted barcode types.
    // configuration.recognizerConfiguration.barcodeFormats = [
    //   BarcodeFormat.AZTEC,
    //   BarcodeFormat.PDF_417,
    //   BarcodeFormat.QR_CODE,
    //   BarcodeFormat.MICRO_QR_CODE,
    //   BarcodeFormat.MICRO_PDF_417,
    //   BarcodeFormat.ROYAL_MAIL,
    ///  .....
    // ];

    // Configure other parameters as needed.
  
    var result = await ScanbotBarcodeSdk.startBarcodeScanner(configuration);

    if(result.operationResult == OperationResult.SUCCESS)
    {
      // TODO: present barcode result as needed
      print(result.value?.items.first.type?.name);
    }
  } catch (e) {
    print('Error: $e');
  }
}
void _startAROverlay() async {
    try {
     // Create the default configuration object.
      var configuration = new BarcodeScannerConfiguration();

      // Configure the usecase.
      var usecase = new MultipleScanningMode();
      usecase.mode = MultipleBarcodesScanningMode.UNIQUE;
      usecase.sheet.mode = SheetMode.COLLAPSED_SHEET;
      usecase.sheet.collapsedVisibleHeight = CollapsedVisibleHeight.SMALL;

      // Configure AR Overlay.
      usecase.arOverlay.visible = true;
      usecase.arOverlay.automaticSelectionEnabled = false;

      // Set the configured usecase.
      configuration.useCase = usecase;

      // Set an array of accepted barcode types.
      // configuration.recognizerConfiguration.barcodeFormats = [
      //   BarcodeFormat.AZTEC,
      //   BarcodeFormat.PDF_417,
      //   BarcodeFormat.QR_CODE,
      //   BarcodeFormat.MICRO_QR_CODE,
      //   BarcodeFormat.MICRO_PDF_417,
      //   BarcodeFormat.ROYAL_MAIL,
      ///  .....
      // ];

      var result = await ScanbotBarcodeSdk.startBarcodeScanner(configuration);

      if (result.operationResult == OperationResult.SUCCESS) {
        // TODO: present barcode result as needed
        print(result.value?.items.first.type?.name);
      }
    } catch (e) {
      print('Error: $e');
    }
  }

And let’s not forget to insert the buttons:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Barcode Scanner'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: _startBarcodeScanning,
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 40),
                textStyle: const TextStyle(fontSize: 18),
              ),
              child: const Text("Start single-barcode scanning"),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _startBarcodeMultiScanning,
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 40),
                textStyle: const TextStyle(fontSize: 18),
              ),
              child: const Text("Start multi-barcode scanning"),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _startAROverlay,
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 40),
                textStyle: const TextStyle(fontSize: 18),
              ),
              child: const Text("Start the AR overlay"),
            ),
          ],
        ),
      ),
    );
  }

Your final main.dart should look something like this:

import 'package:flutter/material.dart';
import 'package:barcode_scanner/scanbot_barcode_sdk_v2.dart';

const BARCODE_SDK_LICENSE_KEY = "";

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
    _initScanbotSdk();
  }

  Future<void> _initScanbotSdk() async {
    var config = ScanbotSdkConfig(
      licenseKey: BARCODE_SDK_LICENSE_KEY,
      loggingEnabled: true,
    );

    try {
      await ScanbotBarcodeSdk.initScanbotSdk(config);
      print('Scanbot SDK initialized successfully');
    } catch (e) {
      print('Error initializing Scanbot SDK: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Barcode Scanner'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: _startBarcodeScanning,
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 40),
                textStyle: const TextStyle(fontSize: 18),
              ),
              child: const Text("Start single-barcode scanning"),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _startBarcodeMultiScanning,
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 40),
                textStyle: const TextStyle(fontSize: 18),
              ),
              child: const Text("Start multi-barcode scanning"),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _startAROverlay,
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 40),
                textStyle: const TextStyle(fontSize: 18),
              ),
              child: const Text("Start the AR overlay"),
            ),
          ],
        ),
      ),
    );
  }

  void _startBarcodeScanning() async {
    try {
      // Create the default configuration object.
      var configuration = BarcodeScannerConfiguration();

      // Initialize the use case for single scanning.
      var scanningMode = SingleScanningMode();
      // Enable and configure the confirmation sheet.
      scanningMode.confirmationSheetEnabled = true;
      scanningMode.sheetColor = ScanbotColor("#FFFFFF");

      // Hide/unhide the barcode image.
      scanningMode.barcodeImageVisible = true;

      // Configure the barcode title of the confirmation sheet.
      scanningMode.barcodeTitle.visible = true;
      scanningMode.barcodeTitle.color = ScanbotColor("#000000");

      // Configure the barcode subtitle of the confirmation sheet.
      scanningMode.barcodeSubtitle.visible = true;
      scanningMode.barcodeSubtitle.color = ScanbotColor("#000000");

      // Configure the cancel button of the confirmation sheet.
      scanningMode.cancelButton.text = "Close";
      scanningMode.cancelButton.foreground.color = ScanbotColor("#C8193C");
      scanningMode.cancelButton.background.fillColor = ScanbotColor("#00000000");

      // Configure the submit button of the confirmation sheet.
      scanningMode.submitButton.text = "Submit";
      scanningMode.submitButton.foreground.color = ScanbotColor("#FFFFFF");
      scanningMode.submitButton.background.fillColor = ScanbotColor("#C8193C");

      // Configure other parameters, pertaining to single-scanning mode as needed.

      configuration.useCase = scanningMode;

      // Set an array of accepted barcode types.
      // configuration.recognizerConfiguration.barcodeFormats = [
      //   scanbotV2.BarcodeFormat.AZTEC,
      //   scanbotV2.BarcodeFormat.PDF_417,
      //   scanbotV2.BarcodeFormat.QR_CODE,
      //   scanbotV2.BarcodeFormat.MICRO_QR_CODE,
      //   scanbotV2.BarcodeFormat.MICRO_PDF_417,
      //   scanbotV2.BarcodeFormat.ROYAL_MAIL,
      ///  .....
      // ];

      // Configure other parameters as needed.
    
      var result = await ScanbotBarcodeSdk.startBarcodeScanner(configuration);

      if(result.operationResult == OperationResult.SUCCESS)
      {
        // TODO: present barcode result as needed
        print(result.value?.items.first.type?.name);
      }
    } catch (e) {
      print('Error: $e');
    }
  }

  void _startBarcodeMultiScanning() async {
    try {
      // Create the default configuration object.
      var configuration = BarcodeScannerConfiguration();

      // Initialize the use case for multiple scanning.
      var scanningMode = MultipleScanningMode();

      // Set the counting mode.
      scanningMode.mode = MultipleBarcodesScanningMode.COUNTING;

      // Set the sheet mode for the barcodes preview.
      scanningMode.sheet.mode = SheetMode.COLLAPSED_SHEET;

      // Set the height for the collapsed sheet.
      scanningMode.sheet.collapsedVisibleHeight = CollapsedVisibleHeight.LARGE;

      // Enable manual count change.
      scanningMode.sheetContent.manualCountChangeEnabled = true;

      // Set the delay before same barcode counting repeat.
      scanningMode.countingRepeatDelay = 1000;

      // Configure the submit button.
      scanningMode.sheetContent.submitButton.text = "Submit";
      scanningMode.sheetContent.submitButton.foreground.color =
          ScanbotColor("#000000");

      // Configure other parameters, pertaining to multiple-scanning mode as needed.

      configuration.useCase = scanningMode;

      // Set an array of accepted barcode types.
      // configuration.recognizerConfiguration.barcodeFormats = [
      //   BarcodeFormat.AZTEC,
      //   BarcodeFormat.PDF_417,
      //   BarcodeFormat.QR_CODE,
      //   BarcodeFormat.MICRO_QR_CODE,
      //   BarcodeFormat.MICRO_PDF_417,
      //   BarcodeFormat.ROYAL_MAIL,
      ///  .....
      // ];

      // Configure other parameters as needed.
    
      var result = await ScanbotBarcodeSdk.startBarcodeScanner(configuration);

      if(result.operationResult == OperationResult.SUCCESS)
      {
        // TODO: present barcode result as needed
        print(result.value?.items.first.type?.name);
      }
    } catch (e) {
      print('Error: $e');
    }
  }

  void _startAROverlay() async {
    try {
     // Create the default configuration object.
      var configuration = new BarcodeScannerConfiguration();

      // Configure the usecase.
      var usecase = new MultipleScanningMode();
      usecase.mode = MultipleBarcodesScanningMode.UNIQUE;
      usecase.sheet.mode = SheetMode.COLLAPSED_SHEET;
      usecase.sheet.collapsedVisibleHeight = CollapsedVisibleHeight.SMALL;

      // Configure AR Overlay.
      usecase.arOverlay.visible = true;
      usecase.arOverlay.automaticSelectionEnabled = false;

      // Set the configured usecase.
      configuration.useCase = usecase;

      // Set an array of accepted barcode types.
      // configuration.recognizerConfiguration.barcodeFormats = [
      //   BarcodeFormat.AZTEC,
      //   BarcodeFormat.PDF_417,
      //   BarcodeFormat.QR_CODE,
      //   BarcodeFormat.MICRO_QR_CODE,
      //   BarcodeFormat.MICRO_PDF_417,
      //   BarcodeFormat.ROYAL_MAIL,
      ///  .....
      // ];

      var result = await ScanbotBarcodeSdk.startBarcodeScanner(configuration);

      if (result.operationResult == OperationResult.SUCCESS) {
        // TODO: present barcode result as needed
        print(result.value?.items.first.type?.name);
      }
    } catch (e) {
      print('Error: $e');
    }
  }
}

Now let’s build and run the app again so we can try out our new scanning modules.

5. Scanning some barcodes!

Now you can go ahead and scan 1D and 2D barcodes – one after the other, many at the same time, and even with an AR overlay that lets you preview their values!

Flutter Barcode Scanner package tutorial

And if you’re in need of some sample barcodes for testing purposes, we’ve got you covered:

Various barcodes for testing

If this tutorial has piqued your interest in integrating barcode scanning functionalities into your Flutter app, make sure to take a look at our SDK’s other neat features in our documentation.

Should you have questions about this tutorial or ran into any issues, we’re happy to help! Just shoot us an email via tutorial-support@scanbot.io.

Happy coding!