Barcode Reader Integration Guide (Foundational Edition)
This guide walks you through building a barcode scanning app using the Dynamsoft Capture Vision Foundational API.
The Foundational API provides full control over barcode scanning performance and settings. Unlike the Ready-To-Use BarcodeScanner component (guide), you’ll build your own UI and configure the scanning workflow using the CaptureVisionRouter and CameraEnhancer APIs.
System Requirements
- Latest Flutter SDK
- Android: Android SDK (API Level 21+), platforms and developer tools
- Supported OS: Android 5.0 (API Level 21) and higher
- Supported ABI: armeabi-v7a, arm64-v8a, x86 and x86_64
- Development Environment: Android Studio Meerkat (2024.3.1); Java 17+; Gradle 8.0+
- iOS
- Supported OS: iOS 13+
- Supported ABI: arm64 and x86_64
- Development Environment: Xcode 13+ (Xcode 14.1+ recommended)
Adding the Library
Run the following in your project root:
flutter pub add dynamsoft_barcode_reader_bundle_flutter
flutter pub get
Adding
dynamsoft_barcode_reader_bundle_flutterautomatically includesdynamsoft_capture_vision_flutter, which is the library you’ll interact with directly.
Building the Barcode Reader
Configure the main.dart
Replace your main.dart with the following code:
import 'package:flutter/material.dart';
import 'package:dynamsoft_capture_vision_flutter/dynamsoft_capture_vision_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ScanBarcodes',
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange)),
home: const MyHomePage(title: 'ScanBarcodes'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// Create the CaptureVisionRouter instance. The CaptureVisionRouter is the class for managing the barcode scanning process.
final CaptureVisionRouter _cvr = CaptureVisionRouter.instance;
// Create the camera instance
final CameraEnhancer _camera = CameraEnhancer.instance;
final String _templateName = EnumPresetTemplate.readBarcodes;
// Define the result receiver for receiving the captured results.
late final CapturedResultReceiver _receiver = CapturedResultReceiver()
..onDecodedBarcodesReceived = (DecodedBarcodesResult result) async {
if (result.items?.isNotEmpty ?? false) {
// Stop capturing when dealing with the results.
_cvr.stopCapturing();
var displayString = result.items?.map((item) => "Format: ${item.formatString}\nText: ${item.text}").join('\n\n');
showTextDialog("Barcodes Count: ${result.items?.length ?? 0}", displayString ?? "", () {
_cvr.startCapturing(_templateName);
});
}
};
@override
void initState() {
super.initState();
// Request camera permission
PermissionUtil.requestCameraPermission();
// A valid license is required.
LicenseManager.initLicense('DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9').then((data) {
final (isSuccess, message) = data;
if (!isSuccess) {
print("license error: $message");
}
});
initSdk();
}
void initSdk() async {
// Bind the Camera instance with the CaptureVisionRouter instance.
await _cvr.setInput(_camera);
// Bind the result receiver with the CaptureVisionRouter instance.
_cvr.addResultReceiver(_receiver);
// Open the camera
_camera.open();
try {
// Start the capturing process.
await _cvr.startCapturing(_templateName);
} catch (e) {
showTextDialog("StartCapturing Error", e.toString(), null);
}
}
void showTextDialog(String title, String message, VoidCallback? onDismiss) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(title: Text(title), content: Text(message));
},
).then((_) {
//Callback when dialog dismissed
onDismiss?.call();
});
}
@override
void dispose() {
super.dispose();
// Stop capturing, close the camera, and remove the result receiver when disposing.
_cvr.stopCapturing();
_camera.close();
_cvr.removeResultReceiver(_receiver);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title)),
body: Center(child: CameraView(cameraEnhancer: _camera)),
);
}
}
- The license string here grants a time-limited free trial which requires network connection to work.
- You can request a 30-day trial license via the Request a Trial License link.
Related APIs:
LicenseManager- licensing.CameraEnhancer- camera operationsCaptureVisionRouter- manages the scanning workflowCapturedResultReceiver- receives processed results
Customize the Barcode Reader (Optional)
Although the default barcode reader template is optimized for common scenarios, you may customize performance or behavior as needed.
Specify Barcode Formats and Count
You can configure which barcode formats to read and how many barcodes to expect per frame.
Option 1. Using SimplifiedCaptureVisionSettings
Configure basic settings using the SimplifiedBarcodeReaderSettings class:
void initSdk() async {
//...
SimplifiedCaptureVisionSettings? settings = await _cvr.getSimplifiedSettings(_templateName);
// Set the expected barcode count to 0 when you are not sure how many barcodes you are scanning.
// Set the expected barcode count to 1 can maximize the barcode decoding speed.
settings.barcodeSettings!.expectedBarcodesCount = 0;
// set the barcode formats to just oned and qrCode so that the library only picks up those two types
settings.barcodeSettings!.barcodeFormatIds = EnumBarcodeFormat.oned |EnumBarcodeFormat.qrCode;
_cvr.updateSettings(settings, _templateName);
_cvr.startCapturing(_templateName);
//...
}
Option 2. Using a JSON Template
For advanced customization, create a JSON template that configures the barcode reader parameters:
{
"CaptureVisionTemplates": [
{
"Name" : "CV_0",
"ImageROIProcessingNameArray": ["TA_0" ]
}
],
"TargetROIDefOptions" : [
{
"Name" : "TA_0",
"TaskSettingNameArray": [ "BR_0" ]
}
],
"BarcodeReaderTaskSettingOptions": [
{
"Name" : "BR_0",
"BarcodeFormatIds" : ["BF_ONED", "BF_QR_CODE"],
"ExpectedBarcodesCount": 0
}
]
}
Apply the JSON template using the initSettings method:
void initSdk() async {
//...
_cvr.initSettings("{\"CaptureVisionTemplates\":[{\"Name\":\"CV_0\",\"ImageROIProcessingNameArray\":[\"TA_0\"]}],\"TargetROIDefOptions\":[{\"Name\":\"TA_0\",\"TaskSettingNameArray\":[\"BR_0\"]}],\"BarcodeReaderTaskSettingOptions\":[{\"Name\":\"BR_0\",\"BarcodeFormatIds\":[\"BF_ONED\",\"BF_QR_CODE\"],\"ExpectedBarcodesCount\":0}]}");
//...
_cvr.startCapturing("CV_0"); // Use the template name defined in the JSON
}
Once you have the JSON template completed, you must remove all the white spaces and then stringify the content of the JSON template in order to get the JSON string.
To learn how to create your own JSON template, please refer to this page.
Specify the Scan Region
Restricting the scan region can reduce processing time and avoid reading unwanted areas:
void initSdk() async {
final scanRegion = DSRect(left: 0.1, top: 0.4, right: 0.9, bottom: 0.6, measuredInPercentage: true);
_camera.setScanRegion(scanRegion);
}
Additional Customization
For more advanced customization options:
- UI Customization - Customize the camera view and overlay
- Advanced Features - Explore advanced barcode reading features
Run the Project
iOS
-
Install CocoaPods dependencies
Before the project can be deployed to an iOS device, the camera permissions and the developer signature must first be set. To add the camera permissions to the iOS portion of the app, we recommend first installing the pods dependencies to generate the .xcworkspace project under the ios folder (
ios/Runner.xcworkspace). Please run the following commands from the root directory:cd ios/ pod install --repo-update -
Configure the project in Xcode
Open Runner.xcworkspace in Xcode and:
- Add Privacy – Camera Usage Description under Project → Info
- Configure Signing & Capabilities
- Connect your device and run the project
Android
Run the app:
flutter run
Run on a specific device:
flutter run -d <DEVICE_ID>
List devices:
flutter devices
Full Sample Code
The full sample code is available here.
License
You can request a 30-day trial license via the Request a Trial License link.