# Scandit Developer Documentation > Developer Guides, API References, and Code Samples for building with Scandit Smart Data Capture This file contains all documentation content in a single document following the llmstxt.org standard. ## Configuring Input Data # Configuring Input Data This guide explains how to configure input data for the **Custom Data Transfer** feature. Input data determines the type and format of the information to be collected by the user during scanning. ## Types of Input Data There are three types of input data you must configure: | Input Type | Description | |-------------------|-------------| | **Standard Input** | Predefined or fixed input fields configured in advance. | | **User Session Input** | Data provided by the user once at the beginning of a scanning session. | | **User Scan Input** | Data provided by the user for each scanned barcode. | ## Standard Input Standard inputs are fixed values or predefined fields. They are useful when you need to always attach the same kind of information (e.g., device ID, operator ID). | Field | Description | |-------|-------------| | `type` | Always set to `standardInput` for this input type. | | `target` | Either of `picker`, `googleSheets`, or `share`. This defines where the data will be sent. Additional fields may be required depending on the target. | | `fields` | An array of **InputField** objects that define the data to be included. | ### Target | Target | Description | Additional Fields | |--------|-------------|-------------------| | `picker` | Data will be included in a CSV. | `format: 'csv'` | | `googleSheets` | Data will be sent to a Google Sheet. | `spreadSheetsId` (string) `sheetId` (Int) | | `share` | Data will be shared via Android's share functionality as a CSV file. | `format: 'csv'` | ### InputField | Field | Description | |-------|-------------| | `Type` | Defines the field type (`barcodeData`, `symbology`, `quantity`, `info`, `additionalInfo`, `generic`). | | `Key` | Identifier used for both display (label) and as the key in the output. | ## Example Configuration ```json { "type": "standard", "target": { "type": "googleSheets", "spreadSheetId": "My ID", "sheetId": 0 }, "fields": [ { "type": "barcodeData", "key": "name-of-barcode-column" }, { "type": "quantity", "key": "name-of-barcode-quantity" }, { "type": "generic", "key": "name-of-a-generic-column" } ] }, { "type": "userSession", "fields": [ { "type": "generic", "key": "STORE_NAME_1" }, { "type": "generic", "key": "STORE_NAME_2" } ] }, { "type": "userScanInput", "fields": [ { "type": "generic", "key": "SHELF_LOCATION" }, { "type": "quantity", "key": "QUANTITY_SCANNED" } ] } ``` --- ## Configuring Output Data # Configuring Output Data This guide explains how to configure output data for the **Custom Data Transfer** feature. Output configuration determines how scanned data and additional inputs are structured, transformed, and exported to external systems. ## Core Configuration | Field | Description | |-------|-------------| | `type` | Always set to `standard` for this configuration type. | | `behavior` | Defines how new data is written. Options: - `replace`: overwrite existing data - `append`: add new rows or entries. | | `target` | Defines the destination for the output (e.g., Google Sheets, CSV, API). | | `parserOptions` | (Optional) Array of parser configuration objects. | | `timestampOptions` | (Optional) Controls how timestamps are handled. | | `grouped` | Boolean (default: `true`). If `false`, the same barcode will be repeated when quantity > 1. | | `fields` | Array of **OutputField** objects that define which values should be exported. | ## OutputField Configuration Each `OutputField` defines a single column or output entry. | Field | Description | |-------|-------------| | `type` | Defines the source of the output value. Options: - `barcodeValue` - `inputValue` - `labelValue` | | `name` | String used as the column name in the output. | | `barcodeValue` | Configuration object (only if `type=barcodeValue`). Defines which aspect of the barcode to output. | | `inputValue` | String (only if `type=inputValue`). Refers to the key from an `InputField`. | | `labelValue` | String (only if `type=labelValue`). Refers to a label field name from `labelCaptureSettings`. | ### BarcodeValue Types When `type=barcodeValue`, the following `barcodeValue.type` options are available: | Type | Description | |------|-------------| | `barcodeData` | Raw scanned barcode data. | | `symbology` | Symbology type (e.g., QR, Code128). | | `symbolCount` | Number of symbols in the barcode. | | `quantity` | Quantity derived from scanning. | | `timestamp` | Timestamp of the scan (see `timestampOptions`). | | `parsed` | Parsed values based on `parserOptions`. | | `found` | Whether the item was found (configurable labels: `foundValue`, `notFoundValue`). | | `counted` | Counting status (configurable: `notInListValue`, `notInListAcceptedValue`, `notInListRejectedValue`, `receivedValue`, `notReceivedValue`). | * `timestampOptions`: Default date format for all dates used is `"yyyy-MM-dd'T'HH:mm:ss'Z'"` (ISO 8601). You can customize this format using the `format` field. * `parserOptions`: Supported parsers are `hibc`, `gs1AI`, `swissQR`, `vin`, and `iataBcbp`. Use the `options` object if you want to put extra options to parsers. ## Example Configuration ```json { "type": "standard", "behavior": "append", "target": { "type": "googleSheets", "spreadSheetId": "My spreadSheetId", "sheetId": 0 }, "parserOptions": [ { "parserType": "gs1AI", "options": { "strictMode": false, "allowMachineReadableCodes": true } } ], "fields": [ { "type": "barcodeValue", "name": "Barcode", "barcodeValue": { "type": "barcodeData" } }, { "type": "barcodeValue", "name": "Quantity", "barcodeValue": { "type": "quantity" } }, { "type": "barcodeValue", "name": "Count Status", "barcodeValue": { "type": "counted", "notInListValue": "Item not in list", "notInListAcceptedValue": "Item not in list - but accepted", "notInListRejectedValue": "Item not in list - and rejected", "receivedValue": "Received", "notReceivedValue": "Not Received" } }, { "type": "barcodeValue", "name": "parsed field", "barcodeValue": { "type": "parsed", "parsedValues": [ { "parserType": "swissQR", "keys": "QRCH/AltPmtInf/AltPmt/2", "options": { "parserOptionKey1": true, "parserOptionKey2": false }, } ] } }, { "type": "inputValue", "name": "StoreName1", "inputValue": "STORE_NAME_1" }, { "type": "inputValue", "name": "StoreName2", "inputValue": "STORE_NAME_2" }, { "type": "barcodeValue", "name": "The First Barcode PD splitted", "labelValue": "pd", "barcodeValue": { "type": "parsed", "parsedValues": [ { "parserType": "gs1AI", "keys": "02.GTIN" } ] } }, { "type": "labelValue", "name": "The First Barcode PD", "labelValue": "pd" } ] } ``` --- ## Custom Data Transfer # Custom Data Transfer The **Custom Data Transfer** feature in Scandit Express lets you import and export data using a configurable CSV file or Google Sheet. By aligning data formats between Scandit Express and your system, this feature ensures seamless integration into your workflow without the need for coding or reformatting. ## Key Benefits Traditionally, data captured with Scandit Express could only be exported: - Automatically into a text field (via virtual keyboard). - To certain Android apps using a special sharing method. - Through standardized CSV reports. Standardized reports often use fixed field names that may not match your system’s database structure. This required manual reformatting before the data could be consolidated, slowing down workflows and creating friction. **Custom Data Transfer eliminates this step** by letting you configure both input and output formats to match your system’s data structure. - **No reformatting required**: Align captured data directly with your system’s fields. - **Flexible import and export**: Use Google Sheets, CSV files, or manual lists created in Scandit Express. - **Improved efficiency**: Reduce time spent on post-processing, so employees can focus on scanning tasks. - **System-agnostic**: Works with any system, including legacy systems, without the need for integration or custom development. ## How It Works 1. **Configure field mappings**; - Define which data fields are relevant for your capture flow. - Match these fields to the structure of your system’s database. 2. **Import data** into Scandit Express. - Upload a CSV file. - Connect to a Google Sheet. - Or create a new list directly within the app. 3. **Capture and update data** using Scandit Express. 4. **Export data** in your configured format, ready to be consumed by your system without additional formatting. ## Example Workflow - A product list is exported from your system in CSV format. - The CSV is imported into Scandit Express using the Custom Data Transfer feature. - Employees capture or update data during scanning tasks. - The updated data is exported back to CSV or Google Sheets in the same format—ready to be re-imported into your system without adjustments. --- ## Bluetooth Device Pairing # Bluetooth Device Pairing ## Prerequisites Before you begin, ensure you have the following prerequisites: - The latest version of Xcode - An iOS project with a deployment target of iOS 14.0 or higher - A Scandit Express license key. Sign up for a [free trial](https://www.scandit.com/trial/) if you don't already have a license key. ## Installation To integrate the BLEScanner SDK into your Xcode project using Swift Package Manager, add the desired frameworks in the _Package Dependencies_ section of your project. Add our SPM package repository: ``` https://github.com/Scandit/blescanner-spm ``` Alternatively, if you prefer checking out git repositories via SSH: ``` git@github.com:Scandit/blescanner-spm.git ``` [CocoaPods](https://cocoapods.org/) is a dependency manager for Swift and Objective-C Cocoa projects. To integrate the BLEScanner SDK into your Xcode project using CocoaPods, specify it in your `Podfile`: ```ruby pod 'BLEScannerSDK' ``` You can download the framework from: ``` https://ssl.scandit.com/sdk/download/scandit-blescannersdk-ios-${VERSION}.zip ``` replacing `${VERSION}` with the version you want to download. ## Configuring the Host To use the SDK in your source code, import it as follows: ```swift import BLEScannerSDK ``` You can then use the `WedgeHost` initializer to set up a host: ```swift WedgeHost( hostName: String, projectCode: String, baseUrl: String, eventCallback: (WedgeHostEvent) -> Void ) ``` - **hostName:** The name you specify for the host. - **projectCode:** Your Scandit Express project code provided in the dashboard. - **baseUrl:** The base URL for the QR code that will be generated. You can use this to directly open your app by specifying a universal link. For example, if you want your host to redirect users to Scandit Express, you can specify `https://express.scandit.com/bluetooth` or `scanditExpress://bluetooth`. - **eventCallback:** The callback for events sent to the host (more details below). The host can provide you with the **connection QR code** as a `UIImage` using: ```swift host.makeQRCode().generateQRCode() ``` ### Receiving Events Hosts receive events in the `eventCallback`. Here's how an event is defined: ```swift public struct WedgeHostEvent { public let eventType: BLEScannerSDK.WedgeHostEventType public let data: String? } ``` ```swift public enum WedgeHostEventType: Int { case NONE case ADV_STARTED // ADV stands for advertising Bluetooth services case ADV_STOPPED case ADV_ABORTED case DEVICE_NAME_SET case DEVICE_BARCODE_RECEIVED case DEVICE_DISCONNECTED } ``` For example, when the host successfully receives a barcode, the `WedgeHostEvent` will look like this: ```swift WedgeHostEvent(eventType: .DEVICE_BARCODE_RECEIVED, data: "barcode data") ``` ## Debugging the Host You will need to run the host on a physical device since Bluetooth functionality does not work on the simulator. --- ## Device Pairing # Device Pairing **Device Pairing** in Scandit Express allows you to transfer scanned barcode data from one smart device (the sender) to another (the receiver) where your system application is running. This enables fast, flexible, and reliable data transfer between devices in real time—without needing to use additional hardware. Data can be transferred via Bluetooth for Native iOS apps and online connection for Web apps: - **Online Connection** - Works with web-based applications - Requires a stable internet connection - **Bluetooth** - Works with native iOS applications - No internet connection required ## Device Pairing Workflow Device Pairing connects two devices: - **Sender:** An iOS or Android device running Scandit Express to capture barcodes. - **Receiver:** A system device (iOS only) running a compatible app to receive data. 1. **Pairing** - On the receiver device, display a QR code (generated by your application through our SDK). - On the sender, open the native camera app and scan the QR code to pair the devices. 2. **Scanning** - Use the sender device to scan barcodes - Through the configuration you can choose to: - Automatically send each scan; or - Tap **“Send data to device”** to send all captured data at once 3. **Transfer** - Data is transmitted via Bluetooth or online connection - It is instantly entered into the target application on the receiver ## System Requirements * Sender Device * iOS or Android device running the Scandit Express app * Receiver Device - iOS (for Bluetooth) - Browser-based apps - Must support light integration with Scandit’s SDK ## Setup & Configuration - Scandit Express runs as a no-code scanning application on the sender device. - For Device Pairing to work, the **receiver application must integrate a lightweight SDK module** to enable data reception. :::note Apps that cannot be modified are **not supported** for pairing. ::: Only the receiving side needs code-level integration. Scandit Express remains a no-code scanning app. ## Try It Now [Online Connection Web Demo](https://barcode-link.demos.scandit.com/) --- ## Device Pairing for Web Apps # Device Pairing for Web Apps ## Prerequisites - A valid **Scandit License Key** - Access to the **Scandit Express** app on the sender device (iOS or Android) - A web application (receiver) where scanned data will be received - Node.js and npm installed on your development machine ## Installation Install the SDK via npm: ```bash npm install @scandit/web-barcode-link ``` ## Implementation 1. Import the SDK ```javascript import { BarcodeLink, BarcodeLinkMode, BarcodeLinkUiFlow } from '@scandit/web-barcode-link'; ``` 2. Initialize BarcodeLink ```javascript const barcodeLink = BarcodeLink.forLicenseKey('YOUR_SCANDIT_LICENSE_KEY'); ``` 3. Set the Scanning Mode ```javascript barcodeLink.setBarcodeLinkMode(BarcodeLinkMode.ContinuousScanning); ``` 4. Configure Symbologies (Optional) ```javascript barcodeLink.setSymbologies({ ean13Upca: { enabled: true }, code128: { enabled: true }, qr: { enabled: true } }); ``` 5. Add Event Listeners ```javascript barcodeLink.addListener({ onCapture: (barcodes) => { barcodes.forEach((barcode) => { console.log('Scanned:', barcode.data); // Handle the scanned data here }); } }); ``` 6. Start the UI Flow ```javascript await barcodeLink.initialize(new BarcodeLinkUiFlow()); ``` ## Terminate the Session ```javascript await barcodeLink.dispose(); ``` ## API Reference The `BarcodeLink` class is used to configure and initialize your Barcode Link instance. ### Creating an Instance ```ts const barcodeLink = BarcodeLink.forLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` Use `forLicenseKey(licenseKey: string): BarcodeLink` to create a new `BarcodeLink` instance with your Scandit license key. ### Configuration Methods #### `setBarcodeLinkMode(barcodeLinkMode: BarcodeLinkMode): BarcodeLink` ```ts barcodeLink.setBarcodeLinkMode(BarcodeLinkMode.ContinuousListBuilding); ``` Sets the scanning mode. **Available values:** | Value | Description | |-------------------------|------------------------------------------------------------| | `SingleScanning` | (Default) Scan one barcode and close the session | | `ContinuousScanning` | Send barcodes in real-time and manually close the session | | `SingleListBuilding` | Send a list of barcodes and close the session | | `ContinuousListBuilding`| Send multiple lists and manually close the session | #### `setListBehavior(listBehavior: BarcodeLinkListBehavior): BarcodeLink` ```ts barcodeLink.setListBehavior(BarcodeLinkListBehavior.Count); ``` Sets the behavior for how barcodes are listed. **Available values:** | Value | Description | |---------|-----------------------------------------------------| | `Unique`| (Default) Each barcode appears only once per list | | `Count` | Tracks how many times a barcode was scanned | :::note Only used in `SingleListBuilding` and `ContinuousListBuilding` modes. ::: #### `setPlatform(platform: BarcodeLinkPlatform): BarcodeLink` ```ts barcodeLink.setPlatform(BarcodeLinkPlatform.Web); ``` Sets the platform used for scanning. **Available values:** | Value | Description | |-----------|-----------------------------------------------------------| | `Express` | (Default) Launches the Scandit Express app | | `Web` | Opens a browser tab using the Scandit Web SDK | #### `setBarcodeRegexValidation(barcodeRegexValidation: RegExp): BarcodeLink` ```ts barcodeLink.setBarcodeRegexValidation(/\d+/); ``` Defines a regex to validate barcodes. Only matching barcodes are processed. By default no validation is applied. #### `setBarcodeTransformations(barcodeTransformations: unknown): BarcodeLink` ```ts barcodeLink.setBarcodeTransformations({ ... }); ``` Sets barcode transformation logic. Only used when `platform` is `BarcodeLinkPlatform.Express`. #### `setSymbologies(symbologies: BarcodeLinkConfiguration['symbologies']): BarcodeLink` ```ts barcodeLink.setSymbologies({ ean13upca: { enabled: true, }, }); ``` Enables specific symbologies for scanning. **[See all supported symbologies](https://docs.scandit.com/barcode-symbologies/)** ### Event Listeners #### `addListener(listener: BarcodeLinkListener): BarcodeLink` ```ts barcodeLink.addListener({ onCapture(barcodes) { console.log("Scanned:", barcodes); }, }); ``` Adds a listener for session events. **Available callbacks:** ##### `onCancel` ```ts barcodeLink.addListener({ onCancel() { console.log("Session closed."); }, }); ``` Called when the desktop closes the scanning session. Only available in `BarcodeLinkUiFlow`. ##### `onCapture` ```ts barcodeLink.addListener({ onCapture(barcodes: BarcodeLinkBarcode[], finished: boolean) { // Handle captured barcodes }, }); ``` Called when the remote device sends barcodes. - `finished`: Indicates if scanning has finished (used in continuous modes). ##### `onConnectionStateChanged` ```ts barcodeLink.addListener({ onConnectionStateChanged(connectionState: BarcodeLinkConnectionState) { switch (connectionState) { // Handle state changes } }, }); ``` Tracks connection state changes. Only available in `BarcodeLinkUilessFlow`. **Available connection states:** | Value | Description | |-----------------------------|------------------------------------------------| | `MainDeviceDisconnected` | Desktop disconnected from session | | `MainDeviceReconnected` | Desktop reconnected to session | | `MainDeviceConnectionFailed`| Reconnection failed repeatedly | | `RemoteDeviceConnected` | Smartphone connected to session | | `RemoteDeviceDisconnected` | Smartphone disconnected from session | #### `removeListener(listener: BarcodeLinkListener): BarcodeLink` ```ts barcodeLink.removeListener(myListener); ``` Removes a previously added listener. ### Initialization #### `initialize(flow: BarcodeLinkFlow): Promise` ```ts await barcodeLink.initialize(new BarcodeLinkUiFlow()); ``` Initializes Barcode Link using a specific flow. **Flow types:** ##### `BarcodeLinkUiFlow` - Initializes with a pre-built UI. - Shows a QR code for smartphone connection. ##### `BarcodeLinkUilessFlow` - Initializes a headless session. - Requires custom UI. - Provides a QR code object for manual rendering. Example: ```ts const qrcode = await barcodeLink.initialize(new BarcodeLinkUilessFlow()); const img = document.createElement("img"); img.src = qrcode.src; const a = document.createElement("a"); a.href = qrcode.href; a.append(img); document.body.append(a); ``` ### Disposing #### `dispose(): void` ```ts await barcodeLink.dispose(); ``` Closes the Barcode Link session, useful when unmounting components or ending a session manually. --- ## Find Items # Find Items Powered by [MatrixScan Find](https://www.scandit.com/products/matrixscan-find/), a feature available in the Scandit Smart Data Capture SDK, this mode enables you to speed up finding and picking workflows by scanning multiple items at once and highlighting the correct item(s) in real-time using an AR overlay. ## Create the Find List Using the Find mode in Scandit Express requires providing a list of barcodes to be found to the end-user. There are multiple ways to create this list, detailed below. ### Online Find List Generator We recommend that you start with creating a list with the barcodes to find (Find List) using our [Find List generator](https://express.scandit.com/find/list/generator/). Here is how it works: ![Find List Generator](/img/express/find-list-generator.png) ### Spreadsheet Find List You can also provide the Find List to your end-users as a spreadsheet. ### On Device A Find List can also be created on the device by scanning the barcodes to be found, for example by using a reference sheet. Select **Create List & Find** in the Scandit Express app and scan the barcodes to be found. The app will then create a Find List based on the scanned barcodes. ## Share the Find List Once the Find List is created, it can be shared with the end-users by either sharing a link (via text, Slack, email, etc.) or by integrating into your app. ### Share a Link You can also generate a URL in the format shown below and send it to the end-user. When the link is opened on the device, Scandit Express starts, the list of barcodes is shown and the user can start finding the barcodes with one click. The link to your Find List must be in the following format: ```http https://express.scandit.com/find/list?listName=&data= ``` Note the two query parameters that must be set in the URL: | Parameter | Description | | --- | --- | | `listName` | The name of the Find List. | | `data` | The list of barcodes to find, separated by commas. | Remember to use URL encoding for the list name and the list of barcodes: - For Excel, [ENCODEURL](https://support.microsoft.com/en-au/office/encodeurl-function-07c7fb90-7c60-4bff-8687-fac50fe33d0e) can be used. - For Google Sheets, [ENCODEURL](https://support.google.com/docs/answer/9199778?hl=en) can be used. - For JavaScript, [encodeURI()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI) can be used. - For Python, [urllib.parse.urlencode](https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlencode) can be used. ### Integrate into Your App You can also integrate the links for your Find List(s) (with the barcodes to find embedded in them) in your own application. Follow the instructions above to create your list, and then display the link in your app or your website. If a user clicks on the link it will start Scandit Express and show the list of codes that need to be found. To integrate specific barcodes to find, you need to: 1. Generate a JSON string. We encode your barcode values into a JSON object as shown below. The JSON object is directly encoded as a string into a QR-code to create the “Find Code”. ```json { "type":"findList", "listName": "Pick list 230523", "part": 1, "partsTotal": 1, "data": ["050755164998737161267150050464","267904872997493075660232174005","003599442103692589922600168806","794304938682592584917910934794","067998913805565298544505960433","429412684815666169331665683721","629486918747410911816814820923","918501883962214718784809774935","771678071143373996836361503435","535726211992040548851819865224"] } ``` The space in QR codes is limited, so if you have more codes that can fit into a single QR code you can create multiple codes. A good rule of thumb is to limit to 2000 barcode characters for a single QR code. Simply adjust the “partsTotal” field (`"partsTotal": 2`) and number each code using the `"part"` field accordingly (`"part": 1` and `"part": 2`). 2. Generate a QR code from the JSON string and display it to the user. Take the JSON created and generate a QR code from it. As an example you can check the implementation in our [spreadsheet template](https://docs.google.com/spreadsheets/d/1Aj0lDEaS6Kh3-8rWlxPOdnuoYcpzXH5OH4SsmvGIyaE/edit#gid=1367552303) (look at the hidden fields in column D-K). You can then display the QR in your app or website. From Scandit Express, the user can scan the QR with **Load List & Find** and start finding the barcodes. --- ## ID Check # ID Check The **ID Check** feature in Scandit Express enables scanning and verification of identity documents directly from the Scandit Express home screen. It is designed for use cases where verifying the **age** or **validity** of an ID is required, such as retail, hospitality, and regulated goods sales. This mode combines **ID validation**, **age verification**, and **export of scanned IDs** into a streamlined workflow that runs fully on-device. ## Getting Started From the Scandit Express **Home Screen**, select **ID Check** to launch the workflow. - The camera opens immediately in **ID Capture mode**. - Users scan the front of the ID document (back of document scanning is optional depending on configuration). - Validation and age verification checks are performed automatically. - A result screen confirms whether the ID passed or failed the configured checks. - The user can scan additional IDs or finish the session at any time. :::tip The camera stream pauses automatically after 30 seconds of inactivity to save battery. ::: ## Features - **ID Validation**: Detects whether an ID is valid, expired, or forged. - **Age Verification**: Compares the document’s date of birth against a configurable age limit. - **Configurable Document Types**: Supports a wide range of IDs (Driver Licenses, Passports, National IDs, Military IDs, etc.). See [Supported Documents](docs/sdks/android/id-capture/supported-documents.md). - **Persistence**: Optionally keep scanned IDs available across app sessions until cleared or exported. - **Export to CSV**: Scanned IDs can be exported as a CSV file with customizable columns. ## Configuration :::tip For configuration of the ID Check functionality, contact [Scandit Support](mailto:support@scandit.com). ::: ID Check is configured via the **Advanced** section of the Scandit Express settings. Configuration options include: | Configuration Key | Values | Behavior | |-----------------|-----------------|----------| | **enabled** | `true`, `false` | Whether ID Check is enabled and selected from the main menu or not. | | **idScanningMode** | `front and back`, `MRZ`, `PDF417`, `VIZ` | Specifies the scanning mode to use for ID documents and the area(s) of the documents to focus on. | | **supportedDocuments** | See [Supported Documents](docs/sdks/android/id-capture/supported-documents.md). | List of supported documents which can be scanned. By default all documents are enabled. | | **scanToFile** | See [Captured ID](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/captured-id.html) for a full list of all the possible fields. | | If this field is present it will be used to customize the output of this mode, i.e. `tableType` can be `custom` (choose which columns to export) or `full` (returns all fields). | | **enabledRejections** | See [ID Capture Settings](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectedDocuments) for more information. | Specifies any documents that should be automatically rejected, for example enforcing age limits or regional restrictions. | | **scannedBarcodePersistenceEnabled** | `true`, `false` | If true, save scanned ID(s) when exiting the mode. Next time the user is shown a dialog asking whether to continue with persisted IDs or start fresh. Clear persisted data after every successful export or when the app is closed. | ### Example Configuration ```json "idCheck": { "enabled": true, "idScanningMode": "front and back" | "MRZ" | "PDF417" | "VIZ", // defaults to "front and back" "supportedDocuments": [ // list of supported documents, default to all documents { "type": "ID_CARD", "region": "ITALY" }, { "type": "DRIVER_LICENSE", "region": "TRINIDAD_AND_TOBAGO" } ... ], "scanToFile": { // if not specified, the default is the full export "format": "csv", // optional, default csv "tableType": "full", // optional, default full. Values: full, custom "timestampOptions": { // Default date format for all dates, optional "format": "yyyy-MM-dd'T'HH:mm:ss'Z'" // default value }, "enabledRejections": { // if not specified, the default is "rejectExpiredIds": true "rejectExpiredIds": true, "rejectHolderBelowAge": 21, "rejectForgedAamvaBarcodes": true, "rejectIdsExpiringIn": { "days": 2, "months": 3, "years": 0 } }, "scannedBarcodePersistenceEnabled": true // default is false } ``` --- ## Available Configurations # Available Configurations There are many configuration options and functionalities available in Scandit Express. This section provides an overview of the different configuration options and how to set them up. ## Configuration Options ### Recognized Symbologies You can configure which [barcode symbologies](../../../barcode-symbologies) Scandit Express should recognize. By default, all symbologies are enabled. You can disable symbologies that are not needed to improve scanning performance. 1. Login to your [Scandit Dashboard](https://ssl.scandit.com/). 2. Click on the Project card you want to configure. 3. For each symbology, you can enable or disable it via the corresponding toggle. ![Symbology Configuration](/img/express/enabled_symbology.png) 4. [Reload the configuration](/hosted/express/getting-started/rollout.md#updating-configuration) in your app to apply the changes. If you want to further restrict what barcodes are accepted by Scandit Express, you can define a specific match as a regular expression. Only barcode data matching the specified regular expression will be accepted. The corresponding field is in the `barcodeRegexValidation` section. ![Barcode Regex Validation](/img/express/regex_validation.png) ### Keystroke Injection You can configure Scandit Express to inject additional keystrokes after a barcode is scanned. This is useful if you want to automate the process of entering data into a form or application. 1. Login to your [Scandit Dashboard](https://ssl.scandit.com/). 2. Click ont the Project card you want to configure. 3. Using the `appendKeyPress` section, you can define the keypresses that should be injected after a barcode is scanned. * `null` means no keypresses will be injected. * `enter` will inject an Enter keypress. * `\n` for Return Carriage. * `tab` for Tab. 4. [Reload the configuration](/hosted/express/getting-started/rollout.md#updating-configuration) in your app to apply the changes. ### Scanning Options Scandit Express supports different scanning options to optimize the scanning experience for different use cases. There are two options available by default: Accuracy and Speed. Two additional options, Batch and List, are available if you have purchased MatrixScan. #### Accuracy Use this mode to select one barcode out of many. This mode detects all barcodes available, then gives visual feedback on the screen (an augmented-reality overlay) so the user can select the target barcode. This mode scans one barcode at a time. #### Speed Use this mode to scan barcodes consecutively at high speed. This mode scans successive items at high speed without the need to keep tapping on the screen. #### Batch Use this mode to scan a batch of barcodes all at once. This mode scans all visible barcodes instantly. It’s perfect when all barcodes are visible and the volume is high. #### List The list mode icon allows the user to see the list of barcodes that have been scanned. List mode, when activated, works for barcodes scanned in any mode (basic speed scanning, accuracy, and batch). ### Activate via Hardware Button This feature is only supported for Android devices, and must be enabled by the Scandit Support team on your account. Contact us using this [webform](https://support.scandit.com/hc/en-us/requests/new) and include the following information: * Your Scandit account email address. * The project name you want to enable the feature for. * The device model(s) you want to enable the feature for. * The key code(s) you want to use to trigger the barcode scanner. :::tip You can identify the key code with key code identifier apps available in the Play Store, such as [KeyEvent Display](https://play.google.com/store/apps/details?id=aws.apps.keyeventdisplay). ::: ### Parse and Sort Data Scandit Express gives you several options to parse the scanned data for such formats as: * Health Industry Barcodes (HIBC) * GS1 Application Identifiers * VIN Numbers * Swiss QR Codes You can parse and sort the scanned data either directly from Scandit Express, using the **Scan barcodes** tile in the **Scan and Export** section, or through keyboard injection. All scanning modes will return parsed data. Please contact [Scandit Support](mailto:support@scandit.com) if you would like to have parser capabilities enabled in your account and we will support you with the necessary details for your specific use case. --- ## Inventory Count # Inventory Count Scandit Express an **Inventory Count** mode designed for fast, robust, and flexible item counting. This mode leverages **MatrixScan Count** and **SparkScan** to support real-world inventory, stock management, and audit scenarios. It can be launched directly from the home screen of Scandit Express. **Inventory Count** provides: - **Two scanning modes**: **MatrixScan Count** for batch scanning with progress tracking, and **SparkScan** for fast single-item scanning. - **Persistent scanned item list**: The scanned list remains available across sessions and workflows until explicitly cleared. - **List-based workflows**: Validate scanned items against a preloaded list of up to 120 barcodes. - **Flexible list loading**: Load lists via deep-link URLs or QR codes, including support for multiple QR codes for large lists. - **Duplicate handling**: Configure whether duplicates are allowed or restricted. - **Export to CSV**: Export results with full customization options. - **Status overlays**: Mark items as `Expired`, `Close to Expire`, or `Not Found`. - **Progress bar**: Shows scanning progress when working against a list. ## Getting Started On start, you will have two options: * **Count without List** which will allow you to start scanning products and then export a list of them. * **Load Order List** which allows you to load a predefined list of barcodes and then scan products to see if they are on the list. Lists can be loaded: - From a **deep-link URL** (e.g. `https://express.scandit.com/count/list?listName=myList&data=123,456,789`) - From a **QR code** encoding the same URL - From **multiple QR codes** (for very large lists) ### Scanning Modes There are two scanning modes available in Inventory Count, toggleable in the UI: - **MatrixScan Count**: Batch scanning with progress tracking. - **SparkScan**: Fast, single-item scanning. The scanned item list is **persistent across sessions and workflows**. Switching between modes or leaving the app does not clear it. :::tip If you need to customize the behavior of the Inventory Count feature, please contact [Scandit Support](mailto:support@scandit.com). ::: --- ## Scan Labels # Scan Labels Powered by [Smart Label Capture](/sdks/android/label-capture/intro/), a feature available in the Scandit Smart Data Capture SDK, this mode enables the simultaneous scanning of multiple barcodes and printed text on labels, streamlining data entry and reducing errors. By combining barcode recognition with OCR and built-in intelligence, it can understand the context of the data and extract only the relevant fields for your application. It is available via the **Scan Labels** option in the Express menu. When finished scanning, you can export the list of scanned details. ## Configuration Label scanning can be enabled and configured in your [Scandit Dashboard](https://ssl.scandit.com/dashboard/) by navigating to the **Modes > Label Scanning** section: Once enabled, you can select from a the following pre-defined label types, and the respective fields will be automatically detected when scanning: * **Smart Device**: Captures the UPC/EAN, IMEI1 and IMEI2, and Serial Number from mobile device labels. * **Price Weight**: This factory method is designed for price checking scenarios where both barcode and price text need to be captured from product labels. Returns `SKU` and `priceText` fields. * **VIN**: Captures the Vehicle Identification Number (VIN) from vehicle labels. :::tip If you need to customize the behavior of the Smart Label Capture feature, please contact [Scandit Support](mailto:support@scandit.com). ::: --- ## Installation # Installation Follow the steps below to get started with Scandit Express. :::note To use Scandit Express, you need to have a Scandit account. If you don't have one, you can [sign up for a free trial](https://ssl.scandit.com/dashboard/sign-up?p=express-trial). ::: 1. Sign up or Log in via the [Scandit Dashboard](https://ssl.scandit.com/) and select you project card. 2. Scan the QR code of the project using your smart device. You will be forwarded to the AppStore. 3. Install Scandit Express from there and your application will automatically be configured with the project of the scanned QR code. 4. Once installed, iOS will ask you to grant Scandit Express camera access. Camera access is required for barcode scanning. 5. Scandit Express will now be present whenever the keyboard is open. Click on the globe icon of the keyboard to switch between keyboards. 1. Sign up or Log in via the [Scandit Dashboard](https://ssl.scandit.com/) and select you project card. 2. Scan the QR code of the project using your smart device. You will be forwarded to the Play Store. 3. Install Scandit Express from there and your application will automatically be configured with the project of the scanned QR code. 4. Once installed, Android will ask you to grant Scandit Express camera access. Camera access is required for barcode scanning. 5. Scandit Express will now be present whenever the keyboard is open. Click on the globe icon of the keyboard to switch between keyboards. --- ## Production Rollout # Production Rollout For production use, Scandit Express is typically distributed via a mobile device management (MDM) or enterprise mobility management (EMM) system. This page will guide you rolling out Scandit Express using such a system for either Android or iOS. This involves adding Scandit Express to your MDM/EMM solution's app catalog, and setting the project code to synchronize the Scandit Express configuration automatically to all devices. :::note The screenshots in this guide are from MobileIron Cloud. However, these instructions apply to MDM/EMM solutions from most vendors. ::: ## iOS You can distribute Scandit Express directly from the Apple App Store. Search for "Scandit Express" in the admin console of your EMM/MDM solution and add it to your app catalog. ![Add Express to App Catalog](/img/express/rollout_ios_1.png) ### Set the Project Code To automatically synchronize your Scandit Express configuration with Scandit, you need to set the project code in the management console of your MDM/EMM solution. Once set, your users won't have to manually activate Scandit Express via QR code. Configuration changes are also automatically distributed to all devices. 1. Login to your [Scandit Dashboard](https://ssl.scandit.com/). 2. Click on your project card. 3. From the Project dashboard, click the **Copy Project Code** link. 4. In your MDM system, paste this value in the **iOS Managed App Configuration** section. ![Add Project Code](/img/express/rollout_ios_2.png) :::note If your MDM system requires an AppConfig configuration, you can generate one [here](https://appconfig.jamfresearch.com/generator) by selecting Scandit Express as: `com.scandit.KeyboardWedge2/current`. ::: ### 3rd-Party Instructions This section provides links to the relevant sections of the documentation for popular MDM/EMM solutions: | Solution | Links | |:---------|:------| | MobileIron Cloud | [App Catalog](http://mi.extendedhelp.mobileiron.com/45/all/en/desktop/App_Catalog.htm), [App Configuration](http://mi.extendedhelp.mobileiron.com/45/all/en/desktop/App_Configuration.htm) | | VMWare Airwatch | [Add Public Applications from an App Store](https://docs.vmware.com/en/VMware-AirWatch/9.1/vmware-airwatch-guides-91/GUID-AW91-Config_Public_Apps_WS1.html) | ## Android Scandit Express for Android supports MDM/EMM deployment via [Android Managed Configurations](https://developer.android.com/work/managed-configurations). :::warning Please note that Scandit Express might not be compatible with some Android for Work configurations (e.g. 3rd-party keyboards such as Scandit Express can typically not be installed in a work profile). Scandit recommends setting Android devices as either ["fully managed"](https://support.google.com/work/android/answer/9562029?hl=en&ref_topic=9563482&sjid=2353681360583047853-EU) and ["dedicated devices"](https://support.google.com/work/android/answer/9560920?hl=en&ref_topic=9563482&sjid=2353681360583047853-EU). ::: You can distribute Scandit Express directly from the Google Play Store. Search for "Scandit Express" in the admin console for your EMM/MDM solution and add it to your app catalog. ![Add Express to App Catalog](/img/express/rollout_android_1.png) ### Set the Project Code To automatically synchronize your Scandit Express configuration with Scandit, you need to set the project code in the management console of your MDM/EMM solution. Once set, your users won't have to manually activate Scandit Express via QR code. Configuration changes are also automatically distributed to all devices. 1. Login to your [Scandit Dashboard](https://ssl.scandit.com/). 2. Click on your project card. 3. The Android Scandit Express App specifies the following Application Restriction: ```xml ``` 4. The `deploymentCode` value needs to be set by the admin of the Managed Configuration to the project code, which can be obtained on the Scandit Express Dashboard by clicking the **Copy Project Code** link. 5. In your MDM system, paste this value in the **Manage Configurations** section. ![Add Project Code](/img/express/rollout_android_2.png) ### 3rd-Party Instructions This section provides links to the relevant sections of the documentation for popular MDM/EMM solutions: | Solution | Links | |:---------|:------| | MobileIron Cloud | [App Catalog](http://mi.extendedhelp.mobileiron.com/45/all/en/desktop/App_Catalog.htm), [App Configuration](http://mi.extendedhelp.mobileiron.com/45/all/en/desktop/App_Configuration.htm) | | VMWare Airwatch | [Add Public Applications from an App Store](https://docs.vmware.com/en/VMware-AirWatch/9.1/vmware-airwatch-guides-91/GUID-AW91-Config_Public_Apps_WS1.html) | | IMB MaaS 360 | [Adding a Google Play App to the App Catalog](https://www.ibm.com/support/knowledgecenter/en/SS8H2S/com.ibm.mc.doc/pag_source/tasks/pag_apps_add_google_play.htm) | | SOTI MobiControl | [Adding an Google Play Store Application to an Application Catalog Rule](http://www.soti.net/mc/help/v13/en/Content/Web/Rules/Plus/Plus_Web_ApplicationCatalog.htm#Play_Store_Apps) | ## Updating Configuration To update the configuration of Scandit Express on all devices, simply change the configuration in the Scandit Dashboard. The new configuration will be automatically distributed to all devices. Scandit Express automatically updates the license and configuration when restarted, but if you need to force a reload: 1. Open the user menu in the top right corner of the Scandit Express app. ![Open User Menu](/img/express/user_menu.png) 2. Tap on **Refresh Project**. ![Refresh Project](/img/express/refresh_project.png) --- ## Safari Browser Extension # Safari Browser Extension The **Safari Browser Extension** is an alternative to the Scandit Express Keyboard. It allows barcode data to be scanned and injected directly into web applications running inside Safari on iOS devices. Instead of typing from the Express Keyboard, users can trigger the scanner via a button next to text fields in a webpage. This is especially useful for workflows where scanning should be initiated directly from the application interface. ## Installation The Safari Browser Extension is bundled with the **Scandit Express** app as an extension (`.appex`). - When the Scandit Express app is installed, the Safari extension is also installed but must be enabled by the user. By default, Safari will ask for permission to run the extension on websites and users can choose: - **Allow Once** - **Always Allow** - **Deny** Once enabled, the extension is visible in the Safari toolbar. :::tip Both the extension icon and the pop-up UI can be customized. ::: ## How It Works When enabled, the extension automatically adds a **Scan** button next to input fields in Safari webpages. 1. The user taps the **Scan** button next to a text field. 2. Safari opens a deep link to the Scandit Express app. 3. The Express scanner is launched, and the scanned barcode is stored in shared storage. 4. Safari is brought back into focus. 5. The extension retrieves the scan result and inserts it into the selected input field. ## Configuration The Safari extension can be configured via the Scandit Dashboard from the **General > Browser Extension** section. ### Default Behavior By default, the extension attaches a scan button next to every `` field on the page. ### Restricting Buttons to Specific Fields Developers can limit the scan button to appear only for specific fields by providing CSS selectors. --- ## Scandit Express Scandit Express is an application that enables you to instantly add barcode scanning to any existing app or software tool on a smart device.It requires no software changes or coding effort, and is compatible with any app or system, even those that cannot be modified. By adding a keyboard that has a scan button above the standard keys (a keyboard wedge), it allows users to scan barcodes directly into any input field. Scandit Express is built for enterprise use and supports distribution through mobile device management (MDM) and enterprise mobility management (EMM) systems. ## Minimum Requirements | Platform | Minimum Version | Camera | |----------|------------------|--------| | Android | 9.0 | 720p, Autofocus and fixed-focus | | iOS | 12.0 | 720p, Autofocus and fixed-focus | ## UI/UX The Scandit Express user interface (UI) is designed to resemble a smartphone camera. It also includes features to reduce user workload and frustration, such as aiming assist, batch scanning, and visual, sound, and haptic feedback. There is also an advanced _Find_ mode that helps frontline workers and customers instantly locate items using an augmented-reality (AR) interface. ![Scandit Express](/img/express/express_ui.png) Depending on the mode selected, the user has a choice of scanning barcodes one by one or batch scanning many codes simultaneously. For batch scanning, users can scan as many barcodes as they want and verify them in a list, before inputting them into the desired field. ### Scanning Modes Scandit Express offers multiple scanning modes: * **Accuracy**: Scans one barcode out of many in the camera’s field of view. It detects all barcodes available and provides an AR overlay to help the user select one target barcode. * **Speed**: Scans multiple barcodes in quick succession. It removes the need to tap the screen repeatedly. * **Batch**: Scans all visible barcodes and stores them in a list. ## Security and Compliance Scandit Express follows the same [security and compliance standards](https://www.scandit.com/company/security/) as all other Scandit products. Your data belongs to you, and we will never collect it unless authorized by you. No keystrokes are recorded, no images captured for barcode decoding are stored on the device after the scan is complete, and no images are transmitted. Scandit Express is fully functional without network access. * Devices register with Scandit’s servers to track the total number of devices on which Scandit Express is used. * No personally identifiable information stored on the device (such as name, phone number, email address, or device ID) is ever processed or transmitted by Scandit Express. * All communication is encrypted. * No connectivity into your network and no access to your IT system is required. --- ## Configuring the Markdown Workflow # Configuring the Markdown Workflow Configure the Markdown workflow in the Scandit Express dashboard to help users efficiently manage tasks related to product recalls. The configuration can only be done via the Code Editor in the **Advanced** section of the dashboard: ## Configuration Options The Markdown workflow can be configured using the following options: | Option | Description | Example Value | |----------------------|---------------------------------------------------------------------------------------------------|------------------------------| | `type` | The type of workflow. This should always be set to `markdown`. | `markdown` | | `labelCaptureSettings` | Settings for label capture, including the fields to capture and their validation rules. | JSON, see example below | | `daysUntilExpiry` | Integer value representing the number of days until the item expires. | `3` | | `expiryDateField` | Object that contains name and other properties for the item. | `ExpiryDateField` | Each `expiryDateField` object must include the following properties: - `name`: The name of the field to capture (This should find a match the `labelCaptureSettings.labelDefinitions.fields[i].name`). - `expiredValue`: Message to be shown when item is expired. - `actionNeededValue`: Message to be shown when item is going to expire. - `noActionNeededValue`: Message to be shown when item is not close to expiry. ### Example Configuration ```json { "integration": { "integrations": [ { "name": "Markdown", "scenario": { "type": "markdown", "labelCaptureSettings": { "labelDefinitions": [ { "caching": true, "fields": [ { "fieldType": "customBarcode", "name": "Barcode", "patterns": [ "^2.*", "^02.*" ], "symbologies": [ "ean13Upca", "code128", "code39", "interleavedTwoOfFive", "ean8", "upce" ] }, { "fieldType": "expiryDateText", "name": "Expiry Date", "labelDateFormat": { "componentFormat": "MDY" } } ], "name": "text_semantics_label" } ] }, "daysUntilExpiry": 3, "expiryDateField": { "name": "Expiry Date", "expiredValue": "Remove from shelf!\nItem EXPIRED", "actionNeededValue": "50% off", "noActionNeededValue": "No action needed" } }, "inputs": [], "outputs": [] } ] } } ``` --- ## Built-in Workflows # Built-in Workflows Scandit Express’s built-in workflows are configurable, ready-to-deploy modes designed to accomplish a specific task. They provide actionable insights to the user through prompts or AR-guidance. There are four built-in workflows available in Scandit Express: ## Task Management Task Management is a workflow designed to help users efficiently manage tasks related to product recalls. It provides a streamlined process for capturing and acting on important product information. The user enters the recalled lot number(s) into Scandit Express. They then scan the item's barcode, lot number, and (optionally) the expiry date. Scandit Express analyzes the data and displays an on-screen prompt with the appropriate next steps. See [Task Management Configuration](./task-management.md) for details on how to configure this workflow. ## Markdown The Markdown workflow in Scandit Express is designed to streamline the process of marking down fresh items approaching their expiry dates. This workflow allows users to quickly and accurately capture the necessary information, reducing the time spent on manual checks. No integration is required — the markdown logic can be configured directly in the Scandit Express dashboard. Once set up, users hover the camera over an item’s barcode and expiry date and Scandit Express captures and interprets the data based on the configured logic. An AR overlay is then displayed, guiding the user on the appropriate action to take. See [Markdown Configuration](./markdown.md) for details on how to configure this workflow. ## Track and Trace Track and Trace is a workflow designed to enhance the visibility and management of pharmaceutical products throughout the supply chain. This workflow allows users to complete two workflows at once by verifying drug expiration with AR overlays while receiving or taking stock. Expired items are highlighted with a distinctive AR overlay and enable users to take immediate action. :::warning This workflow only works for items which have the expiry date encoded in the barcode. ::: ## Age Check Scandit Express's Age Check workflow allows users to verify age and ID authenticity. This helps ensure compliance with age-restricted regulations, such as alcohol sales or vehicle rentals, using Scandit's powerful ID Scanning and Validation technology. Users can scan the front and/or back of IDs, and they receive immediate feedback including verification of authenticity, expiry, and age. All scanned IDs can be exported at the end if needed. --- ## Configuring the Task Management Workflow # Configuring the Task Management Workflow Configure the Task Management workflow in the Scandit Express dashboard to help users efficiently manage tasks related to product recalls. The configuration can only be done via the Code Editor in the **Advanced** section of the dashboard: ## Configuration Options The Task Management workflow can be configured using the following options: | Option | Description | Example Value | |----------------------|---------------------------------------------------------------------------------------------------|------------------------------| | `type` | The type of workflow. This should always be set to `taskManagement`. | `taskManagement` | | `labelCaptureSettings` | Settings for label capture, including the fields to capture and their validation rules. | JSON, see example below | | `taskGenericKeys` | An array of generic keys that can be used in task prompts. | `["key1", "key2"]` | | `taskField` | The field you want to consider for taking decisions about leaving on the shelf or not. | `taskField` | Each `taskField` object must include the following properties: - `name`: The name of the field to capture (This should find a match the `labelCaptureSettings.labelDefinitions.fields[i].name`). - `inListValue`: String to be shown if the scanned label is in the expected list. - `notInListValue`: String to be shown if the scanned label is not in the expected list. ## Example Configuration ```json { "integration": { "integrations": [ { "name": "TaskManagement", "scenario": { "type": "taskManagement", "labelCaptureSettings": { "labelDefinitions": [ { "caching": true, "fields": [ { "fieldType": "customBarcode", "name": "Barcode", "symbologies": [ "ean13Upca", "code128", "code39", "interleavedTwoOfFive", "ean8", "upce" ] }, { "fieldType": "unitPriceText", "name": "Unit Price", "optional": true }, { "fieldType": "weightText", "name": "Weight", "optional": true }, { "fieldType": "totalPriceText", "name": "Total Price", "optional": true }, { "fieldType": "packingDateText", "name": "Packing Date", "optional": true }, { "fieldType": "expiryDateText", "name": "Expiry Date", "optional": true }, { "fieldType": "customText", "name": "Lot Number", "anchorRegexes": [ "Lot" ], "valueRegexes": [ "\\d{5,15}" ], "optional": true } ], "name": "text_semantics_label" } ] }, "taskGenericKeys": ["Column", "Column2", "Column3"], "taskField": { "name": "Lot Number", "inListValue": "Recalled Item!\nRemove from shelf!", "notInListValue": "Keep item on shelf" } }, "inputs": [ { "type": "userSession", "fields": [ { "type": "generic", "key": "Column" }, { "type": "generic", "key": "Column2" } ] }, { "type": "standard", "target": { "type": "googleSheets", "spreadSheetId": "10ewpiR5wWkBUGCvf5YooiZcrkh74VUQivEB3l3RU3jk", "sheetId": 640733273 }, "fields": [ { "type": "generic", "key": "Column3" } ] } ], "outputs": [] } ] } } ``` --- ## Advanced Options # Advanced Options This page covers advanced features and options for ID Bolt that help optimize performance and handle specific use cases. ## Keep Alive Available since version `1.6`. When running ID Bolt multiple times in sequence (such as scanning multiple passports in a batch), you can improve performance by keeping resources alive between sessions: ```ts // first scan let idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... keepAliveForNextSession: true, }); // second scan idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... keepAliveForNextSession: true, }); // more scans... // When finished with all scans IdBoltSession.terminate(); ``` ### Benefits - Faster loading times for subsequent scans - No need to request camera permissions again - Reduced resource initialization overhead ### Important Notes - Always call `IdBoltSession.terminate()` when done with all scans to release resources - This feature is most beneficial when scanning multiple IDs in quick succession ## Browser Navigation Control Available since version `1.14`. By default, ID Bolt closes when users press the browser's back button. You can disable this behavior: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... disableCloseOnBrowserBack: true, }); ``` ### When to Use - When you have custom navigation logic in your application, that interferes with this feature ### Default Behavior When `disableCloseOnBrowserBack` is `false` (default), pressing the back button closes the ID Bolt pop-up and triggers the `onCancellation` callback with `CancellationReason.UserClosed`. ## Transaction Tracking Available since version `1.17`. You can associate ID Bolt sessions with your internal tracking identifiers for analytics and debugging: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... externalTransactionId: "booking-12345", // your booking, order, or transaction ID }); ``` ### Benefits - Correlate ID Bolt sessions with your business transactions - Better analytics and reporting capabilities ### Example Use Cases - E-commerce: Order IDs - Booking systems: Reservation Numbers --- ## API Overview # ID Bolt API Overview ID Bolt is built around the concept of a **session** - a complete user journey from starting the ID scanning process to either successful completion or cancellation. The main class `IdBoltSession` represents this session and manages the entire workflow. ## Quick Start Example ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { licenseKey: LICENSE_KEY, documentSelection: DocumentSelection.create({ accepted: [new Passport(Region.Any)], }), returnDataMode: ReturnDataMode.Full, validation: [Validators.notExpired()], onCompletion: (result) => { console.log("Successfully completed workflow", result); }, onCancellation: (reason) => { console.log("Scanning cancelled", reason); }, }); await idBoltSession.start(); ``` ## Session Methods ### Creating a Session ```ts IdBoltSession.create(serviceUrl: string, options: IdBoltCreateSessionOptions): IdBoltSession ``` Creates a new ID Bolt session with your configuration. The session is not started until you call `start()`. **Parameters:** - `serviceUrl`: Your ID Bolt service URL from the Scandit dashboard - `options`: [Configuration object defining the session behavior](#configuration-options) :::note The default value `app.id-scanning.com` is an alias that points to Scandit's servers. In a production environment it can be changed to your own domain name pointing to Scandit's servers. This will require you to configure a CNAME record in the DNS settings of your domain. Contact your Scandit account manager for more information. ::: ### Starting a Session ```ts async session.start(): Promise ``` Launches the ID Bolt user interface and begins the scanning workflow. Returns a unique session ID for tracking. ### Resource Management ```ts IdBoltSession.terminate(): void ``` When the `keepAliveForNextSession` (default: false) option is selected, this method can be used to clean up resources after the last session ended. If this option is not selected, there is no need to call this method. ## Configuration Options The following options can be configured when creating an ID Bolt session: | Option | Type | Required | Description | Details | Since | | --------------------------- | ------------------- | -------- | --------------------------------------------------- | ------------------------------------------- | ----- | | `licenseKey` | `string` | Yes | Your Scandit license key | | 1.0 | | `documentSelection` | `DocumentSelection` | Yes | Defines acceptable documents | [Document Selection](../document-selection) | 1.0 | | `returnDataMode` | `ReturnDataMode` | Yes | Controls what data is returned | [Data Handling](../data-handling) | 1.0 | | `anonymizationMode` | `AnonymizationMode` | No | Controls data anonymization | [Data Handling](../data-handling) | 1.3 | | `anonymizedFields` | `AnonymizedFields` | No | Fine-grained control over which fields to anonymize | [Data Handling](../data-handling) | 2.2 | | `scanner` | `Scanner` | No | Customizes scanner behavior | [Workflow Options](../workflow) | 1.2 | | `validation` | `Validators[]` | No | Validators to verify ID | [Validators](../validators) | 1.0 | | `locale` | `string` | No | Interface language | [Supported Locales](#supported-locales) | 1.1 | | `workflow` | `WorkflowOptions` | No | Customizes workflow UI | [Workflow Options](../workflow) | 1.1 | | `theme` | `Theme` | No | Customizes visual appearance | [Theming](../theming) | 1.1 | | `textOverrides` | `TextOverrides` | No | Customizes displayed text | [Text Overrides](../text-overrides) | 1.2 | | `keepAliveForNextSession` | `boolean` | No | Keeps resources for multiple sessions | [Advanced Options](../advanced) | 1.6 | | `disableCloseOnBrowserBack` | `boolean` | No | Prevents closing on browser back | [Advanced Options](../advanced) | 1.14 | | `externalTransactionId` | `string` | No | Your tracking ID for analytics | [Advanced Options](../advanced) | 1.17 | | `learnMore` | `LearnMore` | No | Customize the "learn more" section | | 2.0 | | `onCompletion` | `Function` | Yes | Completion callback | [Callbacks](../callbacks) | 1.0 | | `onCancellation` | `Function` | No | Cancellation callback | [Callbacks](../callbacks) | 1.0 | ## Supported Locales The following languages are supported: - `en-US` (English, United States - default) - `de-DE` (German, Germany) - `de-CH` (German, Switzerland) - `es-ES` (Spanish, Spain) - `fr-FR` (French, France) - `it-IT` (Italian, Italy) - `nl-NL` (Dutch, Netherlands) - `pl-PL` (Polish, Poland) - `pt-PT` (Portuguese, Portugal) - `da-DK` (Danish, Denmark) --- ## Callbacks # Callbacks ID Bolt provides callbacks to handle session completion and cancellation, allowing your application to respond appropriately to user actions and scan results. ## Completion Callback The `onCompletion` callback is invoked when the user has successfully scanned their ID and passed all validations. This is where you'll receive the extracted data. ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... onCompletion: (result) => { if (result.capturedId) { console.log("Document type:", result.capturedId.documentType); console.log("Full name:", result.capturedId.fullName); console.log("Document number:", result.capturedId.documentNumber); // Process the scanned ID data } }, }); ``` ### CompletionResult Object The `onCompletion` callback receives a `CompletionResult` object containing: | Property | Type | Description | Since | | ------------ | ------------ | ------------------------------------------------------------------------------------------------ | ----- | | `capturedId` | `CapturedId` | The scanned document data. Will be `null` if no data was returned based on the `returnDataMode`. | 1.0 | ## Cancellation Callback The `onCancellation` callback is invoked when the user closes the ID Bolt pop-up without completing the scanning process or when the service fails to start. ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... onCancellation: (reason) => { switch (reason) { case CancellationReason.UserClosed: console.log("User closed the scanning window"); // Handle user cancellation break; case CancellationReason.ServiceStartFailure: console.log("ID Bolt service failed to start"); // Handle service failure break; } }, }); ``` ### CancellationReason Enum The `onCancellation` callback receives a `CancellationReason` enum value: | Value | Description | Since | | ---------------------------------------- | ------------------------------------------------------------------------- | ----- | | `CancellationReason.UserClosed` | The user closed the ID Bolt pop-up before completing the scanning process | 1.1 | | `CancellationReason.ServiceStartFailure` | The ID Bolt service failed to start | 1.1 | ## Captured ID Data The `CapturedId` object contains the extracted data from the scanned document. The available data depends on the document type and quality of the scan. ### CapturedId Properties | Property | Type | Description | Since | | -------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | | `firstName` | `string` | First name of the document holder | 1.0 | | `lastName` | `string` | Last name of the document holder | 1.0 | | `fullName` | `string` | Full name of the document holder | 1.0 | | `sex` | `string` | Sex/gender of the document holder | 1.0 | | `nationality` | `string` | Nationality of the document holder | 1.0 | | `address` | `string` | Address of the document holder | 1.0 | | `issuingCountry` | `Region` | The ISO (Alpha-3 code) abbreviation of the issuing country | 1.0 | | `documentNumber` | `string` | Unique identifier assigned to the document | 1.0 | | `documentAdditionalNumber` | `string` | Secondary identification number if present | 1.0 | | `personalIdNumber` | `string` | Personal identification number of the document holder | 1.3 | | `dateOfBirth` | `DateResult` | Date of birth of the document holder | 1.0 | | `age` | `number` | Calculated age based on date of birth | 1.0 | | `dateOfExpiry` | `DateResult` | Expiration date of the document | 1.0 | | `isExpired` | `boolean` | Whether the document is expired | 1.0 | | `dateOfIssue` | `DateResult` | Date when the document was issued | 1.0 | | `documentType` | `DocumentType` | Type of document (e.g. `"Passport"`, `"IdCard"`, `"DriverLicense"`, `"VisaIcao"`, `"ResidencePermit"`, `"HealthInsuranceCard"`, `"RegionSpecific"`) | 1.0 | | `documentSubtype` | `string \| null` | Subtype of the document, if applicable | 2.1 | | `capturedResultTypes` | `string[]` | Types of data that were captured | 1.0 | | `nationalityISO` | `string \| null` | ISO code of the nationality | 2.1 | | `isCitizenPassport` | `boolean` | Whether the document is a citizen passport | 2.1 | | `images` | `object \| null` | Object containing base64 encoded images (if requested) | 1.0 | | `mrzResult` | `MrzResult \| null` | Raw extracted data from Machine Readable Zone (MRZ) | 1.6 | | `vizResult` | `VizResult \| null` | Raw extracted data from Visual Inspection Zone (VIZ) | 1.11 | | `barcodeResult` | `BarcodeResult \| null` | Raw extracted data from barcode | 2.1 | | `anonymizedFields` | `IdFieldType[]` | List of fields that were anonymized for this document | 2.2 | ### DateResult Object Date values are represented as `DateResult` objects: | Property | Type | Description | Since | | -------- | -------- | ----------------------- | ----- | | `day` | `number` | Day of the month (1-31) | 1.0 | | `month` | `number` | Month (1-12) | 1.0 | | `year` | `number` | Four-digit year | 1.0 | ### Images Object If you've used `ReturnDataMode.FullWithImages`, the `images` property will contain front and back image sets: ```ts images: { front: ImageSet; back: ImageSet; } | null ``` Each `ImageSet` contains: | Property | Type | Description | Since | | ----------------- | ---------------- | --------------------------------------------------------------------------------------------------------- | ----- | | `face` | `string \| null` | Cropped face image extracted from the document (base64 encoded) | 2.0 | | `croppedDocument` | `string \| null` | Cropped image of the document, only available when the visual inspection zone is scanned (base64 encoded) | 2.0 | | `frame` | `string \| null` | Full frame image of the captured document (base64 encoded) | 2.0 | In version 1.x, `images` has a different structure: | Property | Type | Description | Since | | ----------- | ---------- | --------------------------------------------------------------------------------------------- | ----- | | `cropped` | `string[]` | Cropped images of the ID in the order they were captured (only available when VIZ is scanned) | 1.0 | | `fullFrame` | `string[]` | Full frame images in the order they were captured | 1.0 | ## Example: Complete Callback Usage ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { licenseKey: LICENSE_KEY, documentSelection: DocumentSelection.create({ accepted: [new Passport(Region.Any)], }), returnDataMode: ReturnDataMode.FullWithImages, onCompletion: (result) => { if (result.capturedId) { // Extract basic information const { fullName, documentNumber, documentType, issuingCountry } = result.capturedId; console.log("Full Name:", fullName); console.log("Document Number:", documentNumber); console.log("Document Type:", documentType); console.log("Issuing Country:", issuingCountry); } }, onCancellation: (reason) => { switch (reason) { case CancellationReason.UserClosed: { console.log("User cancelled the scanning process"); // Show alternative flow return; } case CancellationReason.ServiceStartFailure: { console.log("Service failed to start"); // Show alternative flow return; } default: { console.log("Other cancellation reason"); // Reserved for future cancellation reasons } } }, }); ``` --- ## Data Handling # Data Handling ID Bolt provides options to control what data is returned from scanned documents and how sensitive information is handled, allowing you to balance functionality with privacy requirements. ## Return Data Mode The `returnDataMode` option controls the extent of data returned by the `onCompletion()` callback: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... returnDataMode: ReturnDataMode.Full, }); ``` ### Available Modes | Value | Description | Since | | ------------------------------- | ------------------------------------------------------------------ | ----- | | `ReturnDataMode.Full` | All extracted data is returned, but images are excluded | 1.0 | | `ReturnDataMode.FullWithImages` | All extracted data is returned, including images of the scanned ID | 1.0 | ### Choosing the Right Mode - Use `ReturnDataMode.Full` when you need the extracted data but don't require images - Use `ReturnDataMode.FullWithImages` when you need visual verification or need to store images for compliance purposes When using `FullWithImages`, be aware that the response will be larger due to the base64-encoded image data. ## Anonymization Mode Available since version `1.3`. Some countries have specific requirements for the anonymization of documents. ID Bolt can be configured to protect sensitive fields and obscure them in result images: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... anonymizationMode: AnonymizationMode.FieldsOnly, }); ``` ### Available Modes | Value | Description | Since | | ----------------------------------- | ------------------------------------- | ----- | | `AnonymizationMode.None` | No anonymization is applied (default) | 1.3 | | `AnonymizationMode.FieldsOnly` | Only fields (data) are anonymized | 1.3 | | `AnonymizationMode.ImagesOnly` | Only images are anonymized | 1.3 | | `AnonymizationMode.FieldsAndImages` | Both fields and images are anonymized | 1.3 | ### Effects of Anonymization - **Fields Anonymization**: Sensitive fields are not extracted from documents - **Image Anonymization**: Black boxes cover sensitive data in result images When image anonymization is enabled (`ImagesOnly` or `FieldsAndImages`), and `ReturnDataMode.FullWithImages` is used, full-frame images will not be returned. Cropped images will still be available but with sensitive areas obscured. ## Anonymized Fields Available since version `2.2`. In addition to the anonymization mode, you can configure exactly which fields are anonymized using the `anonymizedFields` option. This gives you fine-grained control per document type. ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... anonymizationMode: AnonymizationMode.FieldsOnly, anonymizedFields: { defaultFields: true, extraFields: [ { document: new IdCard(Region.Any), fields: [IdFieldType.DocumentNumber, IdFieldType.DateOfBirth], }, ], }, }); ``` ### Configuration The `anonymizedFields` option accepts an object with two properties: | Property | Type | Description | Since | | --------------- | ------------------------ | ----------------------------------------------------------------------------------- | ----- | | `defaultFields` | `boolean` | When `true`, the default set of sensitive fields is anonymized. | 2.2 | | `extraFields` | `AnonymizedFieldEntry[]` | Additional fields to anonymize for specific document types, on top of the defaults. | 2.2 | Each `AnonymizedFieldEntry` specifies a document type and the fields to anonymize for that document: | Property | Type | Description | Since | | ---------- | ------------------- | ----------------------------------------------------------------------------------------------- | ----- | | `document` | `IdCaptureDocument` | The document type this entry applies to (e.g. `new Passport(Region.Any)`, `new IdCard("USA")`). | 2.2 | | `fields` | `IdFieldType[]` | The fields to anonymize for this document type. | 2.2 | ### Available Field Types The `IdFieldType` enum defines the fields that can be anonymized: | Value | Description | Since | | ------------------------------------------ | ------------------------------ | ----- | | `IdFieldType.FirstName` | First name | 2.2 | | `IdFieldType.LastName` | Last name | 2.2 | | `IdFieldType.FullName` | Full name | 2.2 | | `IdFieldType.Sex` | Sex/gender | 2.2 | | `IdFieldType.Nationality` | Nationality | 2.2 | | `IdFieldType.Address` | Address | 2.2 | | `IdFieldType.AdditionalAddressInformation` | Additional address information | 2.2 | | `IdFieldType.AdditionalNameInformation` | Additional name information | 2.2 | | `IdFieldType.Age` | Age | 2.2 | | `IdFieldType.DateOfBirth` | Date of birth | 2.2 | | `IdFieldType.DateOfExpiry` | Date of expiry | 2.2 | | `IdFieldType.DateOfIssue` | Date of issue | 2.2 | | `IdFieldType.DocumentNumber` | Document number | 2.2 | | `IdFieldType.DocumentAdditionalNumber` | Document additional number | 2.2 | | `IdFieldType.PersonalIdNumber` | Personal ID number | 2.2 | | `IdFieldType.IssuingAuthority` | Issuing authority | 2.2 | | `IdFieldType.PlaceOfBirth` | Place of birth | 2.2 | | `IdFieldType.Profession` | Profession | 2.2 | | `IdFieldType.Employer` | Employer | 2.2 | | `IdFieldType.MaritalStatus` | Marital status | 2.2 | | `IdFieldType.FathersName` | Father's name | 2.2 | | `IdFieldType.MothersName` | Mother's name | 2.2 | | `IdFieldType.Race` | Race | 2.2 | | `IdFieldType.Religion` | Religion | 2.2 | | `IdFieldType.BloodType` | Blood type | 2.2 | | `IdFieldType.ResidentialStatus` | Residential status | 2.2 | | `IdFieldType.MrzOptionalDataInLine1` | MRZ optional data in line 1 | 2.2 | | `IdFieldType.MrzOptionalDataInLine2` | MRZ optional data in line 2 | 2.2 | | `IdFieldType.BarcodeDictionary` | Barcode dictionary | 2.2 | ### Result The `CapturedId` object returned in the `onCompletion` callback includes an `anonymizedFields` property — an array of `IdFieldType` values indicating which fields were actually anonymized for the scanned document. --- ## Document Selection # Document Selection ID Bolt allows you to specify which types of documents are acceptable for scanning. Documents are selected using the `DocumentSelection` class. ## Creating a Document Selection Use `DocumentSelection.create()` to define which types of documents the ID Bolt will accept: ```ts const documentSelection = DocumentSelection.create({ accepted: [ new Passport(Region.Any), new IdCard(Region.FRA), new DriverLicense(Region.France), ], rejected: [ // You can explicitly reject certain documents that would otherwise be included new Passport(Region.Switzerland), ], }); ``` Documents not on the list may trigger the scanner, but will not be accepted. ## Standard Document Types ### Passport Includes all passports. ```ts new Passport(Region.USA); // US passports only new Passport(Region.Any); // Any passport ``` ### ID Card Includes national identity cards. ```ts new IdCard(Region.Germany); // German identity cards only new IdCard(Region.Any); // Identity cards from any country ``` ### Driver License Includes driver licenses. ```ts new DriverLicense(Region.France); // French driver licenses only new DriverLicense(Region.Any); // Driver licenses from any country ``` ### Visa (ICAO) Includes visas that comply with International Civil Aviation Organization (ICAO) standards. ```ts new VisaIcao(Region.USA); // US ICAO-compliant visas new VisaIcao(Region.Any); // Any ICAO-compliant visa ``` ### Residence Permit Includes residence permits. ```ts new ResidencePermit(Region.USA); // US residence permits new ResidencePermit(Region.Any); // Residence permits from any country ``` ### Health Insurance Card Includes health insurance cards. ```ts new HealthInsuranceCard(Region.Germany); // German health insurance cards new HealthInsuranceCard(Region.Any); // Health insurance cards from any country ``` ## Region Specific Documents For specialized document types that are specific to certain regions, use the `RegionSpecific` class with a `RegionSpecificSubtype` argument: ```ts new RegionSpecific(RegionSpecificSubtype.BelgiumMinorsId); // Belgian minors ID new RegionSpecific(RegionSpecificSubtype.MexicoTaxId); // Mexican tax ID ``` ### Supported Region Specific Documents The following region-specific document types are supported: #### United States - `UsBorderCrossingCard` - `UsGlobalEntryCard` - `UsNexusCard` - `UsCommonAccessCard` - `UsUniformedServicesId` - `UsVeteranId` - `UsWorkPermit` - `UsSocialSecurityCard` - `UsTwicCard` - `UsWeaponPermit` - `UsMedicalMarijuanaCard` - `UsMunicipalId` #### Asia - `ChinaExitEntryPermit` - `ChinaMainlandTravelPermitTaiwan` - `ChinaMainlandTravelPermitHongKongMacau` - `ChinaOneWayPermit` - `PakistanAfghanCitizenCard` - `PakistanProofOfRegistration` - `PakistanConsularId` - `SingaporeFinCard` - `SingaporeWorkPermit` - `SingaporeEmploymentPass` - `SingaporeSPass` - `IndiaPanCard` - `MalaysiaIkad` - `MalaysiaMykad` - `MalaysiaMypr` - `MalaysiaMykas` - `MalaysiaMykid` - `MalaysiaMytentera` - `MalaysiaRefugeeId` - `MalaysiaMypolis` - `PhilippinesMultipurposeId` - `PhilippinesWorkPermit` - `PhilippinesSocialSecurityCard` - `PhilippinesNbiClearance` - `PhilippinesPostalId` - `PhilippinesTaxId` #### Europe - `GermanyEid` - `BelgiumMinorsId` - `HungaryAddressCard` - `UkAsylumRequest` - `UkMilitaryId` - `SwedenSocialSecurityCard` - `SwedenSisId` - `IrelandPublicServicesCard` #### Americas - `MexicoConsularVoterId` - `MexicoProfessionalId` - `MexicoConsularId` - `MexicoTaxId` - `CanadaTribalId` - `CanadaSocialSecurityCard` - `CanadaCitizenshipCertificate` - `CanadaMinorsPublicServicesCard` - `CanadaWeaponPermit` - `CanadaPublicServicesCard` - `ColombiaMinorsId` - `ColombiaTemporaryProtectionPermit` - `PeruMinorsId` - `BoliviaMinorsId` - `GuatemalaConsularId` #### Other - `ApecBusinessTravelCard` - `AustraliaAsicCard` - `UaeVehicleRegistrationCard` - `UaeEsaadCard` ## Working with Regions Regions are used to define the geographic scope of a document. They can be specified using the `Region` enum, which contains both ISO codes and region names. ```ts // These are equivalent Region.FRA; Region.France; ("FRA"); // For any region Region.Any; ``` ### Two-letter ISO Codes If you have a two-letter ISO code, you can convert it to a region: ```ts const region = Region.fromShortCode("FR"); // == Region.France == "FRA" const shortCode = Region.toShortCode(Region.FRA); // == "FR" ``` If the provided short code is invalid, the methods will throw an exception. --- ## Getting Started ID Bolt can be integrated into your existing application or website with minimal time and effort, often ready to test in your staging environment in just one hour. ID Bolt is available as an [npm package](https://www.npmjs.com/package/@scandit/web-id-bolt) and can be installed using `npm` or `yarn`. ```bash npm install @scandit/web-id-bolt ``` ```bash yarn add @scandit/web-id-bolt ``` ## Content Security Policy (CSP) If you have `Content-Security-Policy` headers (CSP) which prevent loading iframes on your page, you need to adapt the value like so: ``` frame-src 'self' https://app.id-scanning.com https://id-service.scandit.com ``` This allows ID Bolt to load the necessary iframe components for the scanning interface. ## Basic Integration Once you have installed the package as a dependency, you can import the ID Bolt module and start scanning IDs. :::note A valid license key is required for ID Bolt. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=id-bolt). ::: Your specific application needs and design define when the ID Bolt pop-up should opened. In this example, we open it after a click on a button present on the page: ```ts import { DocumentSelection, IdBoltSession, Region, Passport, ReturnDataMode, Validators, } from "@scandit/web-id-bolt"; const ID_BOLT_URL = "https://app.id-scanning.com"; const LICENSE_KEY = "-- YOUR LICENSE KEY HERE --"; async function startIdBolt() { // define which documents are allowed to be scanned. More complex rules can be added. const documentSelection = DocumentSelection.create({ accepted: [new Passport(Region.Any)], }); // initialization of the ID Bolt session const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { licenseKey: LICENSE_KEY, documentSelection, // define what data you expect in the onCompletion callback returnDataMode: ReturnDataMode.Full, // add validation rules on the scanned document validation: [Validators.notExpired()], locale: "en-US", onCompletion: (result) => { // the ID has been captured and validation was successful. }, onCancellation: (reason) => { // the ID Bolt pop-up has been closed by the user without finishing the scan process. }, }); // open the pop-up await idBoltSession.start(); } // open ID Bolt when some button is clicked const someButton = document.getElementById("someButton") as HTMLButtonElement; someButton.addEventListener("click", startIdBolt); ``` For completeness this is the HTML you will need for the example: ```html Start ID Bolt ``` The above code snippet is a simple example of how to integrate ID Bolt into your application. It opens the ID Bolt pop-up when a button is clicked and listens for the completion of the scanning process. --- ## ID Bolt ID Bolt is a cloud-based identity scanning solution that enables you to provide customers a fast, foolproof ID scanning in just 1 second, leading to an improved customer experience as well as compliance. It works on-device, via desktop and mobile in a unified solution, ensuring no identity information is collected by third-party servers and reduces latency for quick scanning performance. :::tip In addition to ID Bolt, Scandit provides an [ID Capture SDK for the Web](/sdks/web/id-capture/intro.md) that allows full flexibility around the user interface and user flow. ::: ## Features ID Bolt offers the following features: - **Fast Scanning**: ID Bolt scans an ID in just 1 second, ensuring a quick and seamless customer experience. Scans are performed from video streams for the fastest possible scanning. - **On-Device Scanning/Processing**: ID Bolt scans IDs on-device, ensuring no identity information is collected by third-party servers, and handling all processing on the device for improved performance. - **Device Handover**: ID Bolt works on both desktop and mobile devices, providing a unified solution. Desktop/laptop users can scan IDs using their mobile device camera. - **Industry Leading UX**: ID Bolt provides a seamless user experience with a simple and intuitive interface, designed based on the millions of scans performed by Scandit customers each year. - **Compliance**: ID Bolt ensures compliance with data protection regulations, such as GDPR, by processing all data on-device and not collecting any identity information on third-party servers. - **White-Label Solution**: ID Bolt can be placed behind your own domain, allowing you to maintain brand consistency and provide a seamless, integrated experience to your customers while leveraging Scandit's powerful ID scanning capabilities. --- ## Release Notes ## 2.5.0 **Released**: June 4, 2026 ### New Features - Added support for a configurable banner displayed at the top of ID Bolt on mobile devices. You can set the banner image, background color, horizontal alignment, and optional custom styling. ### Bug fixes - Fixed a license key domain validation issue in the ID Bolt configurator within the Scandit dashboard. ## 2.3.0 **Released**: April 14, 2026 ### Improvements - Workflow: Simplified the welcome screen flow for desktop users. A single button now guides the user to continue and scan their document via QR code. Additional scanning methods (webcam and image upload) remain available from a secondary page. ### New Features - Workflow options: `showWelcomeScreenDesktop` and `showWelcomeScreenMobile` allow you to control the welcome screen visibility independently on desktop and mobile. - image upload: give users an additional way to process their document by uploading an image or a pdf file. See [workflow options](../workflow) for details. ### Bug fixes - the scanner now resets correctly when a user scans the front of a document, navigates back, and returns to the scanner page. The user must then start over by scanning the front of their document. ### Deprecations - workflow option `showWelcomeScreen` is deprecated, use `showWelcomeScreenDesktop` and `showWelcomeScreenMobile` instead. ## 2.2.0 **Released**: February 24, 2026 ### New Features - Granular anonymization control: configure which specific fields to anonymize, either using a default set or by specifying extra fields per document type. See [Data Handling](../data-handling) for details. ## 2.1.0 **Released**: January 21, 2026 ### New Features - Allow scanning of the table on the back of EU driver licenses. - Include the full decoded barcode result when scanning barcode on the back of US driver licenses. ## 2.0.0 **Released**: January 12, 2026 ### New Features - Updated Scandit Data Capture SDK to 8.x. - ID-Bolt SDK changes to align with Scandit Data Capture SDK 8.x. - Learn-more feature: User customizable content and external link to provide more information about the scanning process. ### Bug Fixes - Improved translation strings with more concise error and success messaging. ## 1.19.0 **Released**: November 11, 2025 ### Bug Fixes - US RealID check now also checks RealID compliance for VIZ scan, before it would only check barcode. Requires update to ID-Bolt SDK 1.19.0. - Other minor bug fixes. ## 1.18.0 **Released**: October 21, 2025 ### New Features - New configurator to be included in the customer dashboard. ## 1.17.0 **Released**: October 6, 2025 ### New Features - Add option to enforce VIZ being scanned when scanning passports. - Support for UK Military ID and UAE ESAAD card. - Support for supplying an external transaction ID to ID-Bolt, for better analytics and tracking. ### Bug Fixes - Wrong help text being shown when scanning on mobile device with low resolution camera. - Show personal id number instead of document number in result screen, when document number is not available. - Fix incorrect caching issue during new version deployments of ID-Bolt service. ## 1.16.0 **Released**: September 18, 2025 ### New Features - Update of Scandit Data Capture Engine to 7.6. ### Bug Fixes - Correctly differentiate between "unknown" and "unspecified" gender. - Fixes case when user could end up with an infinite loading screen. - Fixes issue with camera switch icon disappearing after changing pages. ## 1.14.0 **Released**: August 11, 2025 ### New Features - Add option to disable closing of ID-Bolt with the browser back button. ## 1.13.0 **Released**: July 21, 2025 ### New Features - Result from ID-Bolt now contains full MRZ and VIZ result sections. - Update to Scandit Data Capture 7.4.0. ### Bug Fixes - Fixed issue where camera would not be correctly stopped after a scan end. ## 1.11.0 **Released**: July 4, 2025 ### New Features - Issuing Authority exposed in the scan result. ## 1.10.0 **Released**: June 17, 2025 ### New Features - SDC updated to 7.3.0. ### Bug Fixes - "Remote scan session expired" shows an improper error message. - "ID scanned" image not showing when imaged disabled. - Fix issues caused with very strict browser data security settings. ## 1.9.0 **Released**: June 10, 2025 ### New Features - CSS customization of buttons, links and titles is now available. ### Bug Fixes - General bug fixes and improvements. ## 1.8.0 **Released**: May 26, 2025 ### New Features - Images in the flow can now be customized. - Fonts used in the flow can now be customized. - Reduction of images throughout the flow. - New “connection status” indicator on the QR page. - When scanning a rejected document, the flow stays in the scanner screen when using newest SDK. ### Bug Fixes - Fixed an edge case in the SDK that could cause a page navigation in a callback to not execute. - Document Type not properly extracted for residence permit and health insurance card. ## 1.6.0 **Released**: April 15, 2025 ### New Features - Large assets are now delivered compressed to speed up loading times. - Comprehensive data analytics collection system. - Raw MRZ data exposed in result. - Browser history is reset to the original state when closing ID-Bolt modal. - Error screen when loading of Scandit SDK fails. - Ability to keep ID-Bolt “alive” after a successful session to retain camera permission and speed up subsequent sessions. - Updated Scandit SDK to version 7.2. ### Bug Fixes - Localization string improvements. - Translations not properly applied in certain cases. ## 1.4.0 **Released**: March 18, 2025 ### New Features - Improved Accessibility functionality. - Improved handling of connection issues during handover flow. - Using the browser back button now properly closes ID Bolt. - ID Bolt now provides a better indication of data transfer state during handover flow. - Custom data validators can now be asynchronous. ### Bug Fixes - Fixed an issue where Camera permission was asked twice on Firefox Mobile. - Fixed an error when no license key provided. ## 1.3.0 **Released**: February 18, 2025 ### New Features - Optimized data transfer speeds in hand-over flow. - Added `personalIdNumber` to result structure. ### Bug Fixes - Fixed an issue where users can get stuck in mobile flow when the welcome screen is disabled. - Removed non-functional close button in hand-over flow. - Fixed an issue where mobile flows were reported as desktop in analytics dashboard. - Disable auto-capitalization of headers. - Excluded document text override not shown when no documents excluded. ## 1.2.0 **Released**: February 5, 2025 ### New Features - Added support for new document types from WebSDK 7.x. - Support for 2-letter country codes. - Added accessibility labels to all elements of ID Bolt service. - Allow customers to provide their own translations (new languages or different strings). - Updated WebSDK to latest 7.x. ### Bug Fixes - Fixed vertical scroll bar issue in handover flow result screen. - Fixed issue with US RealID validation settings. - Fixed issue where scanner stops responding after scanning ID card/DL/Resident permit with full scanner type in handover flow. ## 1.1.0 **Released**: October 11, 2024 ### New Features - Added support for scanning ICAO Visas. - Provide more language support out of the box. - Configurability of colors of text, background and icons. - Make start guidance and result display optional. - Attribution page for OSS components. ### Bug Fixes - Fixed issue where welcome screen is still flashed once before proceeding even when disabled. - Fixed issue where welcome text is wrong when multiple same document types selected. --- ## Session --- ## Text Overrides # Text Overrides ID Bolt allows you to customize the text displayed in the user interface to better match your application's tone, branding, or to provide more specific instructions to users. ## Using Text Overrides Text overrides are specified using the `textOverrides` option when creating an ID Bolt session: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... textOverrides: { "titles.SCANNER_HEADER": "Scan your ID for verification", "texts.HELP_SUPPORTED_DOCUMENTS_INCLUDE_LIST_BRIEF": "Please use a valid passport or driver's license", }, }); ``` ## Available Text Override Keys The following text keys can be overridden: | Key | Default | Description | Since | | --------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ----- | | `titles.SCANNER_HEADER` | "Scan document" | The header of the scan screen on mobile | 1.2 | | `titles.LOCAL_SCAN_HEADER` | "Scan document" | The header of the scan screen on desktop | 1.2 | | `texts.HELP_SUPPORTED_DOCUMENTS_INCLUDE_LIST` | "Please scan a valid document. The following documents are accepted: [list of documents]" | The list of documents that are accepted, as displayed in the help screen | 1.2 | | `texts.HELP_SUPPORTED_DOCUMENTS_INCLUDE_LIST_BRIEF` | "Please scan a valid document of type [list of documents]" | A brief description of the documents that are accepted, as displayed in the main screen | 1.2 | | `texts.HELP_SUPPORTED_DOCUMENTS_EXCLUDE_LIST` | "The following documents are not accepted: [list of documents]" | The list of documents that are excluded, as displayed in the help screen. Only shown if there are excluded documents | 1.2 | ## Examples ### Customizing for Specific Use Cases #### Example: Travel Documentation ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... textOverrides: { "titles.SCANNER_HEADER": "Scan travel document", "titles.LOCAL_SCAN_HEADER": "Scan travel document", "texts.HELP_SUPPORTED_DOCUMENTS_INCLUDE_LIST_BRIEF": "Scan passport or international ID", }, }); ``` ### Combining with Localization Text overrides should be adapted depending on the provided `locale` option to provide a fully localized experience: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // Set the base language locale: "fr-FR", // Override specific text in that language textOverrides: { "texts.HELP_SUPPORTED_DOCUMENTS_INCLUDE_LIST_BRIEF": "Veuillez utiliser un passeport ou une carte d'identité valide", }, // other options... }); ``` --- ## Theming # Theming ID Bolt allows comprehensive customization of its visual appearance to match your brand identity. Use the `theme` option when creating an ID Bolt session to customize colors, dimensions, and other visual elements. ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... theme: { colors: { primary: "#0070f3", background: "#ffffff", }, dimensions: { radiusButton: "8px", }, }, }); ``` ## Color Customization The `colors` object allows you to define colors for various UI elements: | Property | Type | Description | Since | | -------------------------------------- | -------- | ----------------------------------------------------------------------------- | ----- | | `primary` | `string` | Primary color used throughout the interface | 1.1 | | `image` | `string` | Color used for image-related elements | 1.1 | | `background` | `string` | Main popup background color | 1.1 | | `backgroundSecondary` | `string` | Secondary background color for surfaces | 1.1 | | `backgroundInverse` | `string` | Inverse background color | 1.1 | | `backgroundScannerPlaceholder` | `string` | Background color for scanner placeholder | 1.8 | | `textPrimary` | `string` | Primary text color | 1.1 | | `textSecondary` | `string` | Secondary text color | 1.1 | | `textTertiary` | `string` | Tertiary text color | 1.1 | | `textInverse` | `string` | Inverse text color | 1.1 | | `textScannerPlaceholder` | `string` | Text color for scanner placeholder | 1.8 | | `success` | `string` | Color for success states | 1.1 | | `error` | `string` | Color for error states | 1.1 | | `warning` | `string` | Color for warning states | 1.1 | | `info` | `string` | Color for informational states | 1.1 | | `buttonBackground` | `string` | Background color for buttons | 1.1 | | `buttonText` | `string` | Text color for buttons | 1.1 | | `buttonBorder` | `string` | Border color for buttons | 1.1 | | `buttonBackgroundDisabled` | `string` | Background color for disabled buttons | 1.1 | | `buttonBorderDisabled` | `string` | Border color for disabled buttons | 1.1 | | `buttonTextDisabled` | `string` | Text color for disabled buttons | 1.1 | | `connectionStatusConnectingBackground` | `string` | Background color for connection status pills in connecting/waiting state | 1.8 | | `connectionStatusConnectingText` | `string` | Text color for connection status pills in connecting/waiting state | 1.8 | | `connectionStatusSuccessBackground` | `string` | Background color for connection status pills in success state | 1.8 | | `connectionStatusSuccessText` | `string` | Text color for connection status pills in success state | 1.8 | | `connectionStatusErrorBackground` | `string` | Background color for connection status pills in error/failed state | 1.8 | | `connectionStatusErrorText` | `string` | Text color for connection status pills in error/failed state | 1.8 | | `headerButtons` | `string` | Color for the header back and close buttons (when not in their white variant) | 1.8 | | `divider` | `string` | Color for divider lines, such as the one on the QR code page | 1.8 | ## Dimension Customization The `dimensions` object allows you to customize sizes and spacing: | Property | Type | Description | Since | | -------------- | -------- | --------------------------- | ----- | | `radiusPopup` | `string` | Border radius for the popup | 1.1 | | `radiusButton` | `string` | Border radius for buttons | 1.1 | | `radiusCard` | `string` | Border radius for cards | 1.1 | All values are string and must be valid CSS dimension expressions. E.g. "12px". ## Image Customization Available since version `1.8`. The `images` object allows you to customize the images used in key screens: ```ts const theme = { images: { welcome: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...", flowCompleted: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...", acceptedId: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAA...", }, }; ``` ### Image Properties | Property | Type | Description | Since | | --------------- | -------- | ------------------------------------------------------------------------------------ | ----- | | `welcome` | `string` | Image displayed on the welcome screen, both on Desktop as well as hand-over | 1.8 | | `flowCompleted` | `string` | Image displayed on the completion screen in hand-over flow | 1.8 | | `acceptedId` | `string` | Image displayed as a placeholder for an accepted image, when picture is not captured | 1.8 | ### Image Requirements - Format: PNG, JPEG, SVG, or WebP (must be provided as data URLs with appropriate mime types) - Maximum size: 50KB per image (size of the base64 data URL) - Data URL format: Must start with one of the following prefixes: - `data:image/png` - `data:image/jpeg` - `data:image/svg+xml` - `data:image/webp` ## Banner (mobile only) Available since version `2.5`. To reinforce user trust, you can display a banner at the top of ID Bolt on mobile devices. The banner supports a maximum height of 80 pixels and can be horizontally aligned to the left, center, or right. You can also define a background color, which is visible when the image does not span the full available width. :::note The banner is not displayed on non-mobile devices, where your website and branding remain visible to the user while ID Bolt is open, making a banner unnecessary. ::: ```ts const theme = { banner: { image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...", backgroundColor: "#05164d", horizontalAlignment: "left", }, }; ``` ### Banner Properties | Property | Type | Description | Since | | --------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----- | | `image` | `string` | Base64 encoded image. Its height must not be larger than 80 pixels, its size must not exceed 50KB and its type should be PNG, JPEG, SVG or WebP. | 2.5 | | `backgroundColor` | `string` | CSS color to display behind the image. `transparent` by default. | 2.5 | | `horizontalAlignment` | `"left" \| "center" \| "right"` | Horizontal alignment of the image. Default is `center`. | 2.5 | ### CSS Customization of the banner If you need further customization of the banner, you can add CSS rules to `theme.styleOverrides.banner` using style overrides. Check out the [style overrides section](#style-overrides) to get more details. ## Font Customization Available since version `1.8`. The `fonts` object allows you to customize the fonts used in the interface: ```ts const theme = { fonts: { primary: { normal: "data:font/woff2;base64,d09GMgABAAAAAAT...", semibold: "data:font/woff2;base64,d09GMgABAAAAAAU...", bold: "data:font/woff2;base64,d09GMgABAAAAAAV...", }, }, }; ``` ### Font Properties | Property | Type | Description | Since | | ------------------ | -------- | --------------------------- | ----- | | `primary.normal` | `string` | Regular font weight (400) | 1.8 | | `primary.semibold` | `string` | Semi-bold font weight (600) | 1.8 | | `primary.bold` | `string` | Bold font weight (700) | 1.8 | ### Font Requirements - Format: WOFF2, WOFF, TTF, or OTF (must be provided as data URLs) - Maximum size: 100KB per font file (size of the base64 data url) - Data URL format: Must start with appropriate mime type prefixes (e.g., `data:font/woff2`, `data:font/woff`) ## Style Overrides Available since version `1.9`. The `styleOverrides` object allows you to apply custom CSS to specific UI elements: ```ts const theme = { styleOverrides: { button: ` .bolt-button { display: block; width: 100%; padding: 12px 24px; background-color: #fcb700; color: #000000; text-align: center; font-weight: bold; font-size: 16px; line-height: 1.5; text-decoration: none; border: none; cursor: pointer; box-sizing: border-box; border-radius: 0; box-shadow: none; transition: background-color 0.2s ease-in-out; } .bolt-button:hover, .bolt-button:focus { background-color: #e0a800; outline: none; } `, link: ` .bolt-link { text-decoration: none; border-bottom: 1px dotted currentColor; } .bolt-link:hover { border-bottom: 1px solid currentColor; } `, title: ` .bolt-title { text-transform: uppercase; letter-spacing: 0.05em; } `, banner: ` .bolt-banner { padding-left: 10px; } `, }, }; ``` ### Available Style Override Properties | Property | Type | Description | Since | | -------- | -------- | ------------------------- | ----- | | `button` | `string` | CSS styles for buttons | 1.9 | | `link` | `string` | CSS styles for links | 1.9 | | `title` | `string` | CSS styles for titles | 1.9 | | `banner` | `string` | CSS styles for the banner | 2.5 | #### CSS class names Use the `.bolt-button`, `.bolt-link`, `.bolt-title` and `.bolt-banner` selectors for the styling rule. You can also create additional rules for pseudo-states like `.bolt-button:hover` etc. When a style override is specified, the element is rendered in its own shadow-DOM, with the provided style sheet attached. The element will have many more CSS classes attached, but since it is rendered in a shadow DOM, these don't have an effect, unless you choose to use them in the style-override. #### Shadow DOM When a style override is specified, the component is rendered in a shadow DOM. This means that none of the default styles of ID Bolt apply to the component anymore. Therefore, make sure to specify all relevant styles. #### Used HTML elements Not all buttons use the `` HTML element. Certain buttons in the UI are `` links stylized as a button. Therefore, make sure to also add `display: flex` or `display: block`, as well as rules such as `text-decoration` to your style sheet. :::tip Always make sure to thoroughly test the full ID Bolt flow when you customize the styles, to make sure the result is as expected on all screens. ::: ## Popup Container Customization Available since version `1.9`. You can apply additional styling to the ID Bolt popup container directly from your application's CSS. This is particularly useful for customizing the popup's outer appearance like adding a box shadow: ```css /* In your application's CSS */ idbolt-pop-up::part(container) { box-shadow: 0 0 20px 5px rgba(0, 0, 0, 0.2); } ``` Note that this approach only affects the popup container itself and not elements inside the popup. For customizing the internal elements, use the Theme API described above. --- ## Validators # Validators Validators allow you to run checks on scanned ID documents to ensure they meet specific criteria. They are only run on documents that are on the list of accepted documents. ## Using Validators Validators are specified in the `validation` array when creating an ID Bolt session: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... validation: [Validators.notExpired(), Validators.notExpiredIn({ months: 6 })], }); ``` You can use multiple validators together. All validators must pass for the scan to be considered successful. ## Available Validators ### Not Expired The `notExpired` validator checks that the scanned document has not expired. This validator will not pass if the expiration date could not be determined from the extracted data. ```ts validation: [Validators.notExpired()]; ``` ### Not Expired In The `notExpiredIn` validator checks that the scanned document will not expire within a specified time period. This validator will not pass if the expiration date could not be determined from the extracted data. ```ts validation: [Validators.notExpiredIn({ months: 12 })]; ``` The `notExpiredIn` validator accepts a `Duration` object with the following properties: ```ts type Duration = { days?: number; months?: number; }; ``` You can specify either days, months, or both: ```ts // Document must not expire in the next 30 days Validators.notExpiredIn({ days: 30 }); // Document must not expire in the next 6 months Validators.notExpiredIn({ months: 6 }); // Document must not expire in the next 1 year and 30 days Validators.notExpiredIn({ months: 12, days: 30 }); ``` ### US Real ID The `US.isRealID` validator checks that the scanned driver license is compliant with the REAL ID Act defined by the American Association of Motor Vehicle Administrators (AAMVA). This validator will not pass if the scanned document is not an AAMVA document. ```ts validation: [Validators.US.isRealID()]; ``` A REAL ID compliant license has a star marking in the upper portion of the card. ## Combining Validators You can combine multiple validators to create more complex validation rules ### Example Check that a supplied drivers license is both RealID-compliant as well as not expired: ```ts const documentSelection = DocumentSelection.create({ accepted: [new DriverLicense(Region.USA)], }); const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { documentSelection, validation: [Validators.notExpired(), Validators.US.isRealID()], // other options... }); ``` ## Custom Validators In addition to the built-in validators, you can provide your own custom validation functions. These external validators receive the captured ID data and can perform any custom validation logic you need. ### External Validator Function An external validator is a function that takes a `ValidatorCapturedId` object and returns an `ExternalValidatorResult`. The function can be either synchronous or asynchronous. ```ts type ExternalValidatorFunction = ( capturedId: ValidatorCapturedId, ) => ExternalValidatorResult | Promise; ``` ### Return Type The external validator must return an `ExternalValidatorResult` with the following structure: ```ts export type ExternalValidatorResult = | { type: "external"; name: string; valid: true; } | { type: "external"; name: string; valid: false; details: { message?: string; }; }; ``` - **`type`**: Always set to `"external"` to identify this as an external validator result - **`name`**: A descriptive name for your validator (used for debugging and error reporting) - **`valid`**: Boolean indicating whether the validation passed - **`details.message`**: Optional error message displayed to the user when validation fails ### Synchronous Validator Example Here's an example validator that ensures the document's issuing country matches the holder's nationality: ```ts function countryMatchValidator(capturedId: ValidatorCapturedId): ExternalValidatorResult { const { issuingCountry, nationality } = capturedId; // Check if both fields are present if (!issuingCountry || !nationality) { return { type: "external", name: "country_verification", valid: false, details: { message: "Document issuing country and nationality information are required", }, }; } // Check if they match if (issuingCountry === nationality) { return { type: "external", name: "country_verification", valid: true, }; } else { return { type: "external", name: "country_verification", valid: false, details: { message: `Document issuing country (${issuingCountry}) does not match nationality (${nationality})`, }, }; } } // Use the country matching validator const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { validation: [Validators.notExpired(), countryMatchValidator], // other options... }); ``` ### Asynchronous Validator Example External validators can also be asynchronous, allowing you to perform API calls or other async operations: ```ts async function blacklistValidator(capturedId: ValidatorCapturedId): Promise { const documentNumber = capturedId.documentNumber; try { const isBlacklisted = await asyncCheckBlacklistFunction(documentNumber); if (isBlacklisted) { return { type: "external", name: "blacklist_check", valid: false, details: { message: "Document is not accepted", }, }; } return { type: "external", name: "blacklist_check", valid: true, }; } catch (error) { // Handle API errors gracefully return { type: "external", name: "Blacklist Check", valid: false, details: { message: "Unable to verify document at this time", }, }; } } // Use the async validator const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { validation: [Validators.notExpired(), blacklistValidator], // other options... }); ``` ### ValidatorCapturedId Interface The `ValidatorCapturedId` object passed to your external validator contains the same extracted data from the scanned document as the document returned at the end of the flow. ## Error Handling When a validator fails, ID Bolt will display an appropriate error message to the user and allow them to try again with a different document. The `onCompletion` callback will not be called unless all validators pass. --- ## Workflow & Scanner Options # Workflow & Scanner Options ID Bolt allows you to customize both the user interface flow and the scanning behavior to meet your specific requirements. ## Workflow Options The `workflow` option allows you to customize the user interface flow: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... workflow: { showWelcomeScreenDesktop: false, showResultScreen: true, }, }); ``` ### Available Options | Option | Type | Default | Description | Since | | -------------------------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | | `showWelcomeScreenDesktop` | `boolean` | `true` | When disabled, skip the welcome screen and immediately opens the QR code page. Other scanning methods are reachable. | 2.3 | | `showWelcomeScreenMobile` | `boolean` | `true` | When disabled: skip the welcome screen and immediately opens the scanner page. Note that the image upload will not be available on mobile if this option is `false`. | 2.3 | | `showResultScreen` | `boolean` | `true` | Determines whether to show the result screen at the end of the workflow. | 1.3 | | `allowImageUpload` | `boolean` | `false` | When enabled, let the user the possibility to upload an image or a PDF file from their device to be scanned. | 2.3 | ### Deprecated options | Option | Type | Default | Description | Since | | ----------------------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- | ----- | | ~~`showWelcomeScreen`~~ | `boolean` | `true` | **Deprecated since 2.3**. When `false`, equivalent to `showWelcomeScreenDesktop=true` and `showWelcomeScreenMobile=false`. | 1.3 | ### Image Upload Available since version `2.3`. When `allowImageUpload` is enabled, the user is offered an additional way of processing their document by uploading an image or a pdf from their device. This option is also compatible with the `FullDocumentScanner` option (see scanner options below): when the front side has been scanned and depending on the type of document, the back side may be required and must also be uploaded. If one of the sides is not recognized, the flow is completely restarted and the user must start over with different images or PDF files. ### Example: Do not show the result screen: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... workflow: { showResultScreen: false, }, }); ``` ## Scanner Options Available since version `1.2`. The scanner behavior can be customized using the `scanner` option. First, import the scanner classes: ```ts import { IdBoltSession, SingleSideScanner, FullDocumentScanner, } from "@scandit/web-id-bolt"; ``` By default, ID Bolt uses a `SingleSideScanner` with all modalities enabled, but you can choose different scanner types and configure their behavior. ### Single Side Scanner The `SingleSideScanner` extracts all data from a single side scan of the document. This is the default scanner type. ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... scanner: new SingleSideScanner( true, // Enable reading of barcode ID-documents true, // Enable reading of machine readable zone (MRZ) documents true, // Enable reading of visual inspection zone (VIZ) documents { enforceVizForPassportScan: false, // Optional: require VIZ for passport acceptance }, ), }); ``` #### Customizing Scanning Modalities You can enable or disable specific scanning modalities: ```ts // Only scan MRZ documents (like passports) const mrzOnlyScanner = new SingleSideScanner( false, // Disable barcode reading true, // Enable MRZ reading false, // Disable VIZ reading ); // Only scan barcode documents (like some driver licenses) const barcodeOnlyScanner = new SingleSideScanner( true, // Enable barcode reading false, // Disable MRZ reading false, // Disable VIZ reading ); ``` #### Passport VIZ Enforcement Available since version `1.17`. By default, passports can be accepted when only the Machine Readable Zone (MRZ) has been successfully scanned. You can require both MRZ and Visual Inspection Zone (VIZ) to be scanned: ```ts const strictPassportScanner = new SingleSideScanner( true, // Enable barcode reading true, // Enable MRZ reading true, // Enable VIZ reading { enforceVizForPassportScan: true, // Require both MRZ and VIZ for passports }, ); ``` **Important:** Enabling `enforceVizForPassportScan` may reduce global passport support coverage, as it requires successful scanning of both zones. Use this option when you need higher data quality or additional fields from the VIZ. ### Full Document Scanner The `FullDocumentScanner` forces the user to scan both the front and back sides of the document, which can provide more complete data extraction, especially for multi-sided documents like ID cards or driver licenses. ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { // other options... scanner: new FullDocumentScanner(), }); ``` The `FullDocumentScanner` automatically enables all scanning modalities (barcode, MRZ, and VIZ). ## Complete Workflow Configuration Example Here's an example that combines various workflow and scanner options: ```ts const idBoltSession = IdBoltSession.create(ID_BOLT_URL, { licenseKey: LICENSE_KEY, documentSelection: DocumentSelection.create({ accepted: [new Passport(Region.Any), new IdCard(Region.Any)], }), returnDataMode: ReturnDataMode.Full, // Configure scanner to only use MRZ reading (good for e.g. passports) scanner: new SingleSideScanner(false, true, false), // skip result screen workflow: { showResultScreen: false, // also offer image upload possibility allowImageUpload: true, }, onCompletion: (result) => { console.log("Successfully completed workflow", result); }, }); await idBoltSession.start(); ``` --- ## Supported ID Documents # Supported ID Documents ## ID Scanning Supported Documents ID Capture offers different [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-scanner.html#id-capture-scanner) types. Each scanner type offers a different scan flow, where either parts of the document or the whole document including front and back side is scanned. This sections lists the supported documents for each scanner type. import IdDocumentsFull from './partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from './partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents ID Validate supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). The following ID types are supported: import IdValidateDocuments from './partials/advanced/_id-documents-validate.mdx'; --- ## Installation import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Installation This page describes how to integrate the Scandit Data Capture SDK into your Android project. The Scandit Data Capture SDK is distributed as [AAR libraries](https://developer.android.com/studio/projects/android-library#aar-contents) in the official Scandit Maven repository. ## Prerequisites Before you begin, make sure you have the following prerequisites in place: - Latest version of the Android SDK (for example through the latest Android Studio) - Android project with target SDK version 23 (Android 6, Marshmallow) or higher :::note ID Capture requires a minimum target SDK version of 24. ::: - Valid Scandit Data Capture SDK license key :::tip Devices running the Scandit Data Capture SDK need a GPU. Otherwise, you can see a significant decrease in performance. ::: ### Internal Dependencies import InternalDependencies from '../../partials/get-started/_internal-deps.mdx'; ### External Dependencies import ExternalDependencies from '../../partials/get-started/_external-deps-android.mdx'; ## Install via Package Manager Add _mavenCentral()_ repository in your _build.gradle_ file: ```gradle repositories { mavenCentral() } ``` See [Internal Dependencies](#internal-dependencies) to identify the artifacts needed based on your desired functionality. Then add the necessary dependencies to your app’s _build.gradle_ file: ```gradle dependencies { implementation "com.scandit.datacapture:[dependency]:[version]" } ``` You can find the latest version on [Sonatype](https://s01.oss.sonatype.org/content/repositories/releases/com/scandit/datacapture/). Add the _mavenCentral_ repository in _pom.xml_ file: ```xml false central Maven Central https://repo1.maven.org/maven2 ``` See [Internal Dependencies](#internal-dependencies) to identify the artifacts needed based on your desired functionality. Then add the necessary dependencies: ```xml ... com.scandit.datacapture [required_dependency] [version] ... ``` ## Install Manually You need to add a reference to `ScanditCaptureCore.aar`, which contains the shared functionality used by the other data capture modules. Depending on the data capture task, you also need to reference the specific module(s) needed as detailed in [Internal Dependencies](#internal-dependencies). If your project already has a local `flatDir` repository, add the AAR files to that folder. If you do not have a `flatDir` repository yet, create a new one in your _build.gradle_ file as illustrated below: ```gradle repositories { flatDir { dirs '/path/to/folder/containing/the/aar/file' } } ``` Add the .aar libraries as dependencies to your `build.gradle` file: ```gradle dependencies { api(name:'ScanditBarcodeCapture', ext:'aar') } ``` ## Additional Information ### Incompatible Modes Error If you’re using _androidx.fragments_ dependency and have the situation where a scanning fragment navigates to another scanning fragment with an incompatible mode, make sure you’re using version 1.3.0+ of the dependency. If not, you may run into an incompatible modes error as the new fragment gets resumed before the previous is paused and for some time incompatible modes may be enabled in the `DataCaptureContext` at the same time. This results in sessions being empty of any result. ### Content Providers On Android, the Scandit SDK uses content providers to initialize the scanning capabilities properly. If your own content providers depend on the Scandit SDK, choose an **initOrder** lower than 10 to make sure the SDK is ready first. If not specified, **initOrder** is zero by default and you have nothing to worry about. Check [the official provider documentation](https://developer.android.com/guide/topics/manifest/provider-element). import OSSLicense from '../../partials/_third-party-licenses.mdx'; --- ## Agent Skills import SkillsPage from '@site/src/components/SkillsPage'; # Agent Skills for Android --- ## AGENTS.md — Scandit Data Capture SDK (Android: Java/Kotlin) # AGENTS.md — Scandit Data Capture SDK (Android: Java/Kotlin) This file guides coding agents (and humans!) to install and integrate the **Scandit Smart Data Capture SDK** for Android using **Java/Kotlin**. It covers setup and how to add key Scandit products: **SparkScan**, **MatrixScan Find/Count**, **Smart Label Capture**, **Barcode Capture**, and **ID Capture**. > Target: **Android (SDK v7.x)** — Gradle/Maven project. > Languages: **Kotlin** (primary) & **Java** (equivalents where helpful). --- ## Setup Commands - **Install Android SDK deps**: use latest Android Studio and SDKs. - **Min/Target**: target/compile SDK ≥ **23** (ID Capture needs **24+**). - **Add Maven Central** to `settings.gradle`/`build.gradle`: ```gradle repositories { mavenCentral() } ``` - **Add Scandit modules** you need in `app/build.gradle` (choose from list below): ```gradle dependencies { implementation "com.scandit.datacapture:ScanditCaptureCore:[latest]" // Add feature modules as needed: implementation "com.scandit.datacapture:ScanditBarcodeCapture:[latest]" implementation "com.scandit.datacapture:ScanditLabelCapture:[latest]" implementation "com.scandit.datacapture:ScanditIdCapture:[latest]" // Optional extras depending on features: implementation "com.scandit.datacapture:ScanditIdCaptureBackend:[latest]" implementation "com.scandit.datacapture:ScanditIdEuropeDrivingLicense:[latest]" implementation "com.scandit.datacapture:ScanditIdAamvaBarcodeVerification:[latest]" implementation "com.scandit.datacapture:ScanditIdVoidedDetection:[latest]" } ``` > Find the **latest version** and exact artifacts on Maven Central (Sonatype). - **Android Manifest**: ```xml ``` - **ProGuard/R8**: no special rules typically required beyond the SDK’s defaults. If you shrink/obfuscate aggressively, keep Scandit packages as needed. - **License key**: create in the Scandit Dashboard and inject via code or BuildConfig. --- ## Project Structure Hints - `App.kt` / `MainActivity.kt`: create `DataCaptureContext` early (Application/Activity). - Fragments/Activities owning a Scandit *View* must forward lifecycle events (`onResume/onPause`). - Keep each product’s setup in its own class (e.g., `SparkScanManager`, `IdCaptureManager`, etc.). --- ## Initialize the SDK (Core) ```kotlin import com.scandit.datacapture.core.DataCaptureContext val dataCaptureContext = DataCaptureContext.forLicenseKey(BuildConfig.SCANDIT_LICENSE_KEY) ``` > Tip: The built‑in UI components (e.g., `SparkScanView`, `BarcodeFindView`) manage camera start/stop when you route lifecycle calls to them. --- ## SparkScan (pre‑built single‑scan UI) **When to use**: fastest way to add ergonomic single‑item scanning with a floating trigger button. **Dependencies**: `ScanditCaptureCore`, `ScanditBarcodeCapture`. ```kotlin import com.scandit.datacapture.barcode.spark.ui.SparkScanView import com.scandit.datacapture.barcode.spark.ui.SparkScanViewSettings import com.scandit.datacapture.barcode.spark.SparkScan import com.scandit.datacapture.barcode.spark.SparkScanSettings import com.scandit.datacapture.barcode.data.Symbology val settings = SparkScanSettings().apply { enableSymbologies(setOf(Symbology.EAN13_UPCA)) // adjust for your use case } val sparkScan = SparkScan(settings) val viewSettings = SparkScanViewSettings() // customize as needed val sparkView = SparkScanView.newInstance(parentView, dataCaptureContext, sparkScan, viewSettings) override fun onResume() { super.onResume(); sparkView.onResume() } override fun onPause() { sparkView.onPause(); super.onPause() } // Listen for results sparkScan.addListener(object : SparkScanListener { override fun onBarcodeScanned(spark: SparkScan, session: SparkScanSession, data: FrameData?) { val barcode = session.newlyRecognizedBarcode barcode?.let { /* handle on UI thread */ } } }) ``` --- ## Barcode Capture (low‑level single scan) **When to use**: full control without SparkScan’s prebuilt UI. **Dependencies**: `ScanditCaptureCore`, `ScanditBarcodeCapture`. ```kotlin val barcodeSettings = BarcodeCaptureSettings().apply { enableSymbologies(setOf(Symbology.CODE128, Symbology.QR)) } val barcodeCapture = BarcodeCapture.forDataCaptureContext(dataCaptureContext, barcodeSettings) // View + overlay val captureView = DataCaptureView.newInstance(context, dataCaptureContext) val overlay = BarcodeCaptureOverlay.newInstance(barcodeCapture, captureView) barcodeCapture.addListener(object : BarcodeCaptureListener { override fun onBarcodeScanned(mode: BarcodeCapture, session: BarcodeCaptureSession, data: FrameData?) { val code = session.newlyRecognizedBarcode?.data // handle result } }) ``` --- ## MatrixScan Find (search & find with AR UI) / MatrixScan Count **When to use**: highlight items that match a *list*; quickly search shelves/containers. **Note**: MatrixScan Count/Find are powered by **BarcodeFind** + **BarcodeFindView**. ```kotlin val findSettings = BarcodeFindSettings().apply { setSymbologyEnabled(Symbology.EAN13_UPCA, true) } val items = hashSetOf( BarcodeFindItem(BarcodeFindItemSearchOptions("9783598215438"), BarcodeFindItemContent("Mini Screwdriver Set", "(6‑Piece)", null)), BarcodeFindItem(BarcodeFindItemSearchOptions("9783598215414"), null) ) val findMode = BarcodeFind(findSettings).apply { setItemList(items) } val findViewSettings = BarcodeFindViewSettings().apply { // e.g., inListItemColor / notInListItemColor, soundEnabled, hapticEnabled } val findView = BarcodeFindView.newInstance(parentView, dataCaptureContext, findMode, findViewSettings) override fun onResume() { super.onResume(); findView.onResume() } override fun onPause() { findView.onPause(); super.onPause() } findView.setListener(object : BarcodeFindViewUiListener { override fun onFinishButtonTapped(found: Set) { /* navigate or consume */ } }) // Programmatic start (same as tapping Play): findView.startSearching() ``` --- ## Smart Label Capture (barcodes + printed text in one shot) **When to use**: read **multiple barcodes + OCR** fields from a label (e.g., expiry date, weight, serial). **Dependencies**: `ScanditCaptureCore`, `ScanditBarcodeCapture`, `ScanditLabelCapture` (+ optional `ScanditLabelCaptureText`, `ScanditPriceLabel` depending on your label definitions). Typical flow: 1. Create `LabelCaptureSettings` and your **label definition** (fields layout + parsers). 2. Create `LabelCapture` for the `dataCaptureContext`. 3. Add a `LabelCaptureViewfinder/Overlay` (or **ValidationFlowOverlay** for guided steps). 4. Register `LabelCaptureListener` to receive structured results. 5. Start camera / provide user feedback. Kotlin sketch: ```kotlin val labelSettings = LabelCaptureSettings.builder()/* configure with your label definition */.build() val labelCapture = LabelCapture.forDataCaptureContext(dataCaptureContext, labelSettings) val captureView = DataCaptureView.newInstance(context, dataCaptureContext) // Optional guided overlay for validation flows: val validationOverlay = LabelCaptureValidationFlowOverlay.newInstance( requireContext(), labelCapture, captureView ) labelCapture.addListener(object : LabelCaptureListener { override fun onLabelCaptured(capture: LabelCapture, session: LabelCaptureSession, data: FrameData?) { val fields = session.capturedLabels.firstOrNull()?.fields // Extract required field values } }) ``` > Author your label definitions to match the physical layout and desired outputs. Use the samples to bootstrap. --- ## ID Capture (ID scanning & data extraction) **When to use**: read MRZ, PDF417 on DL/IDs, and visual zones on supported IDs. **Dependencies**: `ScanditCaptureCore`, `ScanditIdCapture` (+ optional backends per region/use case). **Important**: **Do not enable** ID Capture at the same time as other modes (e.g., Barcode Capture, Text Capture). Switch modes cleanly. Kotlin outline: ```kotlin val idSettings = IdCaptureSettings().apply { acceptedDocuments = listOf(IdCard(IdCaptureRegion.ANY), DriverLicense(IdCaptureRegion.ANY)) // Configure sides/regions as required } val idCapture = IdCapture.forDataCaptureContext(dataCaptureContext, idSettings) val captureView = DataCaptureView.newInstance(context, dataCaptureContext) val overlay = IdCaptureOverlay.newInstance(idCapture, captureView) idCapture.addListener(object : IdCaptureListener { override fun onIdCaptured(mode: IdCapture, id: CapturedId) { // Consume fields (name, DOB, document number, etc.) } }) ``` > For validation workflows, add corresponding verifiers (e.g., AAMVA, EU DL) as optional dependencies. --- ## Common Tasks for Agents - **Symbologies**: enable only what you need (EAN‑13, Code 128, QR, etc.) to maximize speed. - **Lifecycle**: always forward `onResume/onPause` to Scandit *views* (SparkScanView, BarcodeFindView, DataCaptureView). - **Threading**: listener callbacks may be on background threads—post results to the UI thread. - **Performance**: keep overlays lean; disable unneeded features; use lists/sets for lookups (MatrixScan Find). - **Testing**: keep printable test sheets handy; exercise low light, glare, and motion. --- ## Samples & References - **Android Samples**: [https://github.com/Scandit/datacapture-android-samples](https://github.com/Scandit/datacapture-android-samples) — multiple ready‑to‑run apps. - **Install guide** (Gradle, modules, requirements). - **SparkScan get started** (prebuilt UI). - **MatrixScan Find get started** (search & find). - **Smart Label Capture get started** (labels & OCR). - **ID Capture get started** (IDs & validation). --- ## Troubleshooting - **Incompatible modes** error across fragments: ensure `androidx.fragment` **1.3.0+** and avoid having two incompatible modes active across fragment transitions. - **Content provider order**: if your `ContentProvider` depends on Scandit, set a lower `initOrder` than 10 so Scandit initializes first. - **GPU requirement**: devices must have a GPU for best performance. --- ## Checklists **PR Checklist** - [ ] Gradle modules added as needed - [ ] License key wired via `BuildConfig`/secure source - [ ] Correct symbologies enabled - [ ] Lifecycles forwarded to Scandit views - [ ] Listeners return results on UI thread - [ ] Mode conflicts avoided (esp. with **IdCapture**) **Release Checklist** - [ ] Camera permission rationale & flows - [ ] Shrink/obfuscate release build verified - [ ] QA on device matrix (OEMs, lighting, cases) - [ ] Legal notices page shows OSS attributions via `DataCaptureContext.openSourceSoftwareLicenseInfo()` --- ## Appendix — Typical Imports (Kotlin) ```kotlin import com.scandit.datacapture.core.* import com.scandit.datacapture.core.ui.* import com.scandit.datacapture.core.ui.viewfinder.* import com.scandit.datacapture.barcode.* import com.scandit.datacapture.barcode.capture.* import com.scandit.datacapture.barcode.capture.ui.* import com.scandit.datacapture.barcode.spark.* import com.scandit.datacapture.barcode.spark.ui.* import com.scandit.datacapture.find.* import com.scandit.datacapture.find.ui.* import com.scandit.datacapture.label.* import com.scandit.datacapture.label.ui.* import com.scandit.datacapture.id.* import com.scandit.datacapture.id.ui.* ``` --- ## Configure Barcode Symbologies # Configure Barcode Symbologies import Intro from '../../../partials/configure-symbologies/_intro.mdx' ## Enable the Symbologies You Want to Read import EnableSymbologies from '../../../partials/configure-symbologies/_enable-symbologies.mdx' The following code shows how to enable scanning Code 128 codes for Barcode Capture: ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCaptureSettings # import com.scandit.datacapture.barcode.data.Symbology val settings = BarcodeCaptureSettings() settings.enableSymbology(Symbology.CODE128, true) ``` import CapturePresents from '../../../partials/configure-symbologies/_capture-presents.mdx' ## Configure the Active Symbol Count Barcode symbologies (such as Code 128, Code 39, Code 93, or Interleaved Two of Five) can store variable-length data. For example, Code 39 can be used to store a string from 1 to 40-50 symbols. There is no fixed upper limit, though there are practical limitations to the code’s length for it to still be conveniently readable by barcode scanners. For performance reasons, the Scandit Data Capture SDK limits the [possible symbol range](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.ActiveSymbolCounts) for variable-length symbologies. If you want to read codes that are shorter/longer than the specified default range or you want to tailor your app to only read codes of a certain length, you need to change the active symbol count of the symbology to accommodate the data length you want to use in your application. The below code shows how to change the active symbol count for Code 128 to read codes with 6, 7 and 8 symbols. ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCaptureSettings # import com.scandit.datacapture.barcode.data.Symbology val settings = BarcodeCaptureSettings() val symbologySettings = settings.getSymbologySettings(Symbology.CODE128) val activeSymbolCounts = mutableSetOf(6, 7, 8) symbologySettings.activeSymbolCounts = activeSymbolCounts ``` import CalculateSymbolCount from '../../../partials/configure-symbologies/_calculate-symbol-count.mdx' ## Read Bright-on-Dark Barcodes Most barcodes are printed using dark ink on a bright background. Some symbologies allow the colors to be inverted and can also be printed using bright ink on a dark background. This is not possible for all symbologies as it could lead to false reads when the symbology is not designed for this use case. See [symbology properties](../symbology-properties.mdx) to learn which symbologies allow color inversion. When you enable a symbology as described above, only dark-on-bright codes are enabled. If you also want to read bright-on-dark codes, color-inverted reading for that symbology must be enabled ( `SymbologySettings.isColorInvertedEnabled`). The following code shows how to enable color-inverted reading for Code 128: ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCaptureSettings # import com.scandit.datacapture.barcode.data.Symbology val settings = BarcodeCaptureSettings() val symbologySettings = settings.getSymbologySettings(Symbology.CODE128) symbologySettings.isColorInvertedEnabled = true ``` ## Enforce Checksums Some symbologies have a mandatory checksum that always gets enforced while others only have optional [checksums](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/checksum.html#enum-scandit.datacapture.barcode.Checksum).Enforcing an optional checksum reduces false positives as an additional check can be performed. When enabling a checksum you have to make sure that the data of your codes contains the calculated checksum otherwise the codes get discarded as the checksum doesn't match. All available checksums per symbology can be found in [symbology properties](../symbology-properties.mdx). You can enforce a specific checksum by setting it through `SymbologySettings.checksums`: ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCaptureSettings # import com.scandit.datacapture.barcode.data.Checksum # import com.scandit.datacapture.barcode.data.Symbology # import java.util.EnumSet val settings = BarcodeCaptureSettings() val symbologySettings = settings.getSymbologySettings(Symbology.CODE39) symbologySettings.checksums = EnumSet.of(Checksum.MOD43) ``` ## Enable Symbology-Specific Extensions Some symbologies allow further configuration. These configuration options are available as symbology extensions that can be enabled/disabled for each symbology individually. Some extensions affect how the data in the code is formatted, others allow for more relaxed recognition modes that are disabled by default to eliminate false reads. All available extensions per symbology and a description of what they do can be found in the documentation on [symbology properties](../symbology-properties.mdx). To enable/disable a symbology extension, use `SymbologySettings.setExtensionEnabled()`. The following code shows how to enable the full ASCII extension for Code 39. ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCaptureSettings # import com.scandit.datacapture.barcode.data.Symbology val settings = BarcodeCaptureSettings() val symbologySettings = settings.getSymbologySettings(Symbology.CODE39) symbologySettings.setExtensionEnabled("full_ascii", true) ``` This extension allows Code 39 to encode all 128 ASCII characters instead of only the 43 characters defined in the standard. The extension is disabled by default as it can lead to false reads when enabled. --- ## Get Started # Get Started This page describes the step-by-step instructions that helps you to add Barcode Capture to your application. The general steps are: - Include the *ScanditBarcodeCapture* library and its dependencies to your project, if any - Create a new [data capture context](https://docs.scandit.com/data-capture-sdk/android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) instance, initialized with your license key - Create your [barcode capture settings](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and enable the [barcode symbologies](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology) you want to read - Create a new [barcode capture mode](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance and initialize it - Register a [barcode capture listener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) to receive scan events - Process successful scans according to your application’s needs and decide whether more codes will be scanned or the scanning process should be stopped - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/android/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for better visual feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### External Dependencies import ExternalDependencies from '../../../partials/get-started/_external-deps-android.mdx'; ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create a Data Capture Context import DataCaptureContextAndroid from '../../../partials/get-started/_create-data-capture-context-android.mdx'; ## Configure Barcode Scanning Settings Barcode scanning is orchestrated by the [BarcodeCapture data capture mode](https://docs.scandit.com/data-capture-sdk/android/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). This class is the main entry point for scanning barcodes. It is configured through [BarcodeCaptureSettings](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) that will get informed whenever new codes have been recognized. For this task, we setup barcode scanning for a small list of barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is application specific. We recommend that you only enable the symbologies your application requires. If you are not familiar with the symbologies that are relevant for your use case, you can use [capture presets](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/capture-preset.html#enum-scandit.datacapture.barcode.CapturePreset) that are tailored for different verticals (for instance, retail, logistics, and so on). ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCaptureSettings # import com.scandit.datacapture.barcode.data.Symbology val settings = BarcodeCaptureSettings().apply { enableSymbology(Symbology.CODE128, true) enableSymbology(Symbology.CODE39, true) enableSymbology(Symbology.QR, true) enableSymbology(Symbology.EAN8, true) enableSymbology(Symbology.UPCE, true) enableSymbology(Symbology.EAN13_UPCA, true) } ``` :::note If you are not disabling barcode capture immediately after having scanned the first code, consider setting the [BarcodeCaptureSettings.codeDuplicateFilter](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture-settings.html#property-scandit.datacapture.barcode.BarcodeCaptureSettings.CodeDuplicateFilter) to around `500` or even `-1` if you do not want codes to be scanned more than once. ::: Next, create a [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance with the settings initialized in the previous step: ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCapture # import com.scandit.datacapture.barcode.capture.BarcodeCaptureSettings # lateinit var settings: BarcodeCaptureSettings val barcodeCapture = BarcodeCapture.forDataCaptureContext(dataCaptureContext, settings) ``` ## Register the Barcode Capture Listener To get informed whenever a new code has been recognized, add a [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) through [BarcodeCapture.addListener()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.AddListener) and implement the listener methods to suit your application’s needs. First conform to the `BarcodeCaptureListener` interface. For example: ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCapture # import com.scandit.datacapture.barcode.capture.BarcodeCaptureListener # import com.scandit.datacapture.barcode.capture.BarcodeCaptureSession # import com.scandit.datacapture.core.data.FrameData # object : BarcodeCaptureListener { override fun onBarcodeScanned( barcodeCapture: BarcodeCapture, session: BarcodeCaptureSession, frameData: FrameData ) { val recognizedBarcodes = session.newlyRecognizedBarcode // Do something with the barcodes. See Rejecting Barcodes, below, for an example. } # } ``` Then add the listener: ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCapture # import com.scandit.datacapture.barcode.capture.BarcodeCaptureListener # object : BarcodeCaptureListener { # init { # lateinit var barcodeCapture: BarcodeCapture barcodeCapture.addListener(this) # } # } ``` ### Rejecting Barcodes To prevent scanning unwanted codes, you can reject them by adding the desired logic to the `onBarcodeScanned` method. This will prevent the barcode from being added to the session and will not trigger the `onSessionUpdated` method. The example below will only scan barcodes beginning with the digits `09` and ignore all others, using a transparent brush to distinguish a rejected barcode from a recognized one: ```kotlin # import com.scandit.datacapture.barcode.data.Barcode # import com.scandit.datacapture.barcode.ui.overlay.BarcodeCaptureOverlay # import com.scandit.datacapture.core.ui.style.Brush # lateinit var barcode: Barcode # lateinit var overlay: BarcodeCaptureOverlay val data = barcode.data if (data == null || !data.startsWith("09:")) { overlay.brush = Brush.transparent() return } ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications use the built-in camera of the device. :::note In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the *AndroidManifest.xml* file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the `android.permission.CAMERA` permission. ::: When using the built-in camera there are recommended settings for each capture mode. These must be used to achieve the best performance and user experience for the respective mode. The following code shows how to get the recommended settings and create the camera: ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCapture # import com.scandit.datacapture.core.source.Camera val cameraSettings = BarcodeCapture.createRecommendedCameraSettings() // Depending on the use case further camera settings adjustments can be made here. val camera = Camera.getDefaultCamera() camera?.applySettings(cameraSettings) ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/android/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync) ```kotlin dataCaptureContext.setFrameSource(camera) ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/android/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.ON](https://docs.scandit.com/data-capture-sdk/android/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```kotlin # import com.scandit.datacapture.core.source.FrameSourceState camera?.switchToDesiredState(FrameSourceState.ON) ``` :::note On Android, the Scandit Data Capture SDK is not lifecycle aware which means it is not able to turn off the camera when the app goes in the background. This has to be done so the camera is not locked for other apps and is left to the implementer. Make sure that you turn the camera off in the activity’s **onPause lifecycle** method. Often this means that you want to (re)start it in **onResume**. You can see a way of doing this in all of the [samples](https://github.com/Scandit/datacapture-android-samples). ::: ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you may want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```kotlin # import android.app.Activity # import com.scandit.datacapture.core.ui.DataCaptureView # object : Activity() { # init { val dataCaptureView = DataCaptureView.newInstance(this, dataCaptureContext) setContentView(dataCaptureView) # } # } ``` To visualize the results of barcode scanning, the following [overlay](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) can be added: ```kotlin # import com.scandit.datacapture.barcode.capture.BarcodeCapture # import com.scandit.datacapture.barcode.ui.overlay.BarcodeCaptureOverlay # lateinit var barcodeCapture: BarcodeCapture val overlay = BarcodeCaptureOverlay.newInstance(barcodeCapture, dataCaptureView) ``` ## Disabling Barcode Capture To disable barcode capture, for instance as a consequence of a barcode being recognized, set [BarcodeCapture.isEnabled](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-capture.html#property-scandit.datacapture.barcode.BarcodeCapture.IsEnabled) to `FALSE`. The effect is immediate: no more frames are processed after the change. However, if a frame is currently being processed, this frame is completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## Barcode Generator # Barcode Generator The Barcode Generator is a simple tool to generate barcodes directly from the Scandit SDK. In this guide, we will show you how to use the Barcode Generator to generate barcodes and QR codes. The Barcode Generator supports the following formats: * Code 39 * Code 128 * EAN 13 * UPCA * ITF * QR * DataMatrix * PDF417 (SDK version >= 8.2) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Generating Barcodes To generate barcodes, you need to create a [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`BarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.BarcodeGeneratorBuilder), and use the method of [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) for the symbology you are interested in, in this example Code 128. You can configure the colors used in the resulting image: ```kotlin # import android.graphics.Color # import com.scandit.datacapture.barcode.generator.BarcodeGenerator # import com.scandit.datacapture.core.capture.DataCaptureContext # val licenseKey = "licenceKey" val dataCaptureContext = DataCaptureContext.forLicenseKey(licenseKey) val builder = BarcodeGenerator.code128BarcodeGeneratorBuilder(dataCaptureContext) .withBackgroundColor(Color.WHITE) .withForegroundColor(Color.BLACK) ``` When the builder is configured get the `BarcodeGenerator` and try to generate the image: ```kotlin # import com.scandit.datacapture.barcode.generator.BarcodeGenerator # lateinit var builder: BarcodeGenerator.Code128BarcodeGeneratorBuilder # val dataString = "data" try { val generator = builder.build() val image = generator.generate(dataString, 200) // Use the image } catch (exception: Exception) { // Handle the error exception.printStackTrace() } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-generator.html) for more information. ## Generating QR Codes To generate barcodes, you need to create a [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`QRCodeBarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder) using the method of [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) specific for QR codes. You can configure the colors used in the resulting image, and the two settings that can be configured for QR codes: [`QRCodeBarcodeGeneratorBuilder.errorCorrectionLevel`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithErrorCorrectionLevel) and [`QRCodeBarcodeGeneratorBuilder.versionNumber`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithVersionNumber). ```kotlin # import android.graphics.Color # import com.scandit.datacapture.barcode.generator.BarcodeGenerator # import com.scandit.datacapture.barcode.generator.QrCodeErrorCorrectionLevel # import com.scandit.datacapture.core.capture.DataCaptureContext # val licenseKey = "licenseKey" val dataCaptureContext = DataCaptureContext.forLicenseKey(licenseKey) val builder = BarcodeGenerator.qrCodeBarcodeGeneratorBuilder(dataCaptureContext) .withBackgroundColor(Color.WHITE) .withForegroundColor(Color.BLACK) .withErrorCorrectionLevel(QrCodeErrorCorrectionLevel.MEDIUM) .withVersionNumber(4) ``` When the builder is configured get the `BarcodeGenerator` and try to generate the image: ```kotlin # import com.scandit.datacapture.barcode.generator.BarcodeGenerator # lateinit var builder: BarcodeGenerator.QrCodeBarcodeGeneratorBuilder # val dataString = "data" try { val generator = builder.build() val image = generator.generate(dataString, 200) // Use the image } catch (exception: Exception) { // Handle the error exception.printStackTrace() } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-generator.html) for more information. --- ## Get Started # Get Started :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/android/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: This page describes the steps to add Barcode Selection to your application. The general steps are: - Create a new Data Capture Context instance, initialized with your license key - Configure the Barcode Selection settings - Create a new Barcode Selection mode instance - Register the listener to receive scan events: - Process the successful scans according to your application’s needs, e.g. by looking up information in a database - Decide whether more codes will be scanned, or the scanning process must be stopped - Obtain the camera instance and set as frame source - Display the camera preview by creating a data capture view - Create (optionally) a new overlay and add it to data capture view for a better visual feedback, if displaying a preview ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### External Dependencies import ExternalDependencies from '../../../partials/get-started/_external-deps-android.mdx'; ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create a Data Capture Context import DataCaptureContextAndroid from '../../../partials/get-started/_create-data-capture-context-android.mdx'; ## Configure the Barcode Selection Mode Barcode selection is orchestrated by the [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) [data capture mode](https://docs.scandit.com/data-capture-sdk/android/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). It is configured via [BarcodeSelectionSettings](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) for when new codes have been selected. For this task, we setup barcode scanning for a small list of different barcode types, called [symbologies](../barcode-symbologies.mdx). The list of symbologies to enable is highly application specific. It is recommended that you **only enable the list of symbologies your application requires**. ```kotlin # import com.scandit.datacapture.barcode.data.Symbology # import com.scandit.datacapture.barcode.selection.capture.BarcodeSelectionSettings val settings = BarcodeSelectionSettings().apply { enableSymbology(Symbology.QR, true) enableSymbology(Symbology.EAN8, true) enableSymbology(Symbology.UPCE, true) enableSymbology(Symbology.EAN13_UPCA, true) } ``` ### Selection Types The behavior of Barcode Selection can be changed by using a different [selection type](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-type.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionType). This defines the method used by [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) to select codes. There are two types: - If you want the user to select barcodes with a tap, use [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection). - This selection type can automatically freeze the camera preview to make the selection easier. You can configure the freezing behavior via [BarcodeSelectionTapSelection.freezeBehavior](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.FreezeBehavior). - With [BarcodeSelectionTapSelection.tapBehavior](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.TapBehavior) you can decide if a second tap on a barcode means that the barcode is unselected or if it is selected another time (increasing the counter). :::note Using BarcodeSelectionTapSelection requires the MatrixScan add-on. ::: - If you want the selection to happen automatically based on where the user points the camera, then use [BarcodeSelectionAimerSelection](https://docs.scandit.com/data-capture-sdk/android/selecting-one-of-many.html#:~:text=BarcodeSelectionAimerSelection). It is possible to choose between two different [selection strategies](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-strategy.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionStrategy): - Use [BarcodeSelectionAutoSelectionStrategy](https://docs.scandit.com/data-capture-sdk/android/selecting-one-of-many.html#:~:text=BarcodeSelectionAutoSelectionStrategy) if you want the barcodes to be selected automatically when aiming at them as soon as the intention is understood by our internal algorithms. - Use [BarcodeSelectionManualSelectionStrategy](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionManualSelectionStrategy) if you want the barcodes to be selected when aiming at them and tapping anywhere on the screen. ### Single Barcode Auto Detection If you want to automatically select a barcode when it is the only one on screen, turn on [BarcodeSelectionSettings.singleBarcodeAutoDetection](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-settings.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionSettings.SingleBarcodeAutoDetection). ### Creating the Mode Next, create a `BarcodeSelection` instance with the settings initialized in the previous step: ```kotlin # import com.scandit.datacapture.barcode.selection.capture.BarcodeSelection # import com.scandit.datacapture.barcode.selection.capture.BarcodeSelectionSettings # val settings = BarcodeSelectionSettings() val barcodeSelection = BarcodeSelection.forDataCaptureContext(dataCaptureContext, settings) ``` ## Registering the Listener To get informed whenever a new code has been recognized, add a [BarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) through [BarcodeSelection.addListener()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-selection.html#method-scandit.datacapture.barcode.selection.BarcodeSelection.AddListener) and implement the listener methods to suit your application’s needs. First implement the `BarcodeSelectionListener` interface. For example: ```kotlin # import com.scandit.datacapture.barcode.selection.capture.BarcodeSelection # import com.scandit.datacapture.barcode.selection.capture.BarcodeSelectionListener # import com.scandit.datacapture.barcode.selection.capture.BarcodeSelectionSession # import com.scandit.datacapture.core.data.FrameData class MyBarcodeSelectionListener: BarcodeSelectionListener { override fun onObservationStarted(barcodeSelection: BarcodeSelection) { // Called when Barcode Selection is started. // We don't use this callback in this guide. } override fun onObservationStopped(barcodeSelection: BarcodeSelection) { // Called when Barcode Selection is stopped. // We don't use this callback in this guide. } override fun onSessionUpdated( barcodeSelection: BarcodeSelection, session: BarcodeSelectionSession, data: FrameData?, ) { // Called every new frame. // We don't use this callback in this guide. } override fun onSelectionUpdated( barcodeSelection: BarcodeSelection, session: BarcodeSelectionSession, data: FrameData?, ) { val newlySelectedBarcodes = session.newlySelectedBarcodes val selectedBarcodes = session.selectedBarcodes val newlyUnselectedBarcodes = session.newlyUnselectedBarcodes // Do something with the retrieved barcodes. } } ``` Then add the listener to the `BarcodeSelection` instance: ```kotlin # import com.scandit.datacapture.barcode.selection.capture.BarcodeSelection # import com.scandit.datacapture.barcode.selection.capture.BarcodeSelectionListener # class MyBarcodeSelectionListener : BarcodeSelectionListener # lateinit var barcodeSelection: BarcodeSelection # barcodeSelection.addListener(MyBarcodeSelectionListener()) ``` ## Obtaining the Camera Instance and Set as Frame Source The data capture context supports using different frame sources to perform recognition, here we assume that you will use the built-in camera of the device. :::note In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the *AndroidManifest.xml* file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These must be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```kotlin # import com.scandit.datacapture.barcode.selection.capture.BarcodeSelection # import com.scandit.datacapture.core.source.Camera val cameraSettings = BarcodeSelection.createRecommendedCameraSettings() // Depending on the use case further camera settings adjustments can be made here. val camera = Camera.getDefaultCamera() camera?.applySettings(cameraSettings) ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/android/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```kotlin dataCaptureContext.setFrameSource(camera) ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/android/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.ON](https://docs.scandit.com/data-capture-sdk/android/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```kotlin # import com.scandit.datacapture.core.source.FrameSourceState camera?.switchToDesiredState(FrameSourceState.ON) ``` ## Disabling Barcode Selection To disable barcode selection, for instance when the selection is complete, set `BarcodeSelection.isEnabled` to `FALSE`. The effect is immediate, no more frames get processed after the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## About Barcode Selection # About Barcode Selection :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/android/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: Barcode Selection enables you to increase scanning accuracy and prevent users from scanning the wrong code in scenario where there are multiple barcodes present. This includes the following: - A crowded shelf where users want to scan the correct barcode to report stockouts or perform a cycle count. - An order catalog with barcodes printed closely together. - A label that has several types of barcodes; however users are only interested in scanning barcodes that have the same type, but cannot select them programmatically. Barcode Selection provides two key capabilities: - **Aim to Select** allows users to select one code at a time. This is especially useful for one-handed operation. - **Tap to Select** is a quick way for users to select several codes from the same view. Selection is done by tapping on highlighted barcodes in the live camera preview or on a frozen screen. Tapping on codes while keeping the smartphone steady can be tricky, and freezing the screen allows for ergonomic use. :::warning Barcode Selection does not support handling of duplicate codes. If a code appears twice in the visible preview both instances will be marked as selected even if only one of them was selected. ::: --- ## Advanced Configurations # Advanced Configurations There are several advanced configurations that can be used to customize the behavior of the ID Capture SDK and enable additional features. ## Decode EU Driver Licenses By default, ID Capture doesn’t extract data from the table on the back of European Driver Licenses. If you are interested in this data, you may enable the extraction by calling: ```kotlin settings.decodeBackOfEuropeanDrivingLicense = true ``` :::warning To use this feature, you will need to include the `ScanditIdEuropeDrivingLicense` module in your project. See the [module overview](/sdks/android/id-capture/get-started.md#module-overview) for details. ::: ## Configure Data Anonymization By default, data extracted from documents is anonymized according to local regulations. See [Anonymized Documents](/sdks/android/id-capture/supported-documents.md#anonymized-documents) for more information. That means certain data from certain fields won’t be returned, even if it’s present on a document. You control the anonymization level with the following setting: ```kotlin // Default value: settings.anonymizationMode = IdAnonymizationMode.FIELDS_ONLY // Sensitive data is additionally covered with black boxes on returned images: settings.anonymizationMode = IdAnonymizationMode.FIELDS_AND_IMAGES // Only images are anonymized: settings.anonymizationMode = IdAnonymizationMode.IMAGES_ONLY // No anonymization: settings.anonymizationMode = IdAnonymizationMode.NONE ``` ## ID Images Your use can may require that you capture and extract images of the ID document. Use the [IdImageType](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-image-type.html#enum-scandit.datacapture.id.IdImageType) enum to specify the images you want to extract from the `CapturedId` object. :::tip Face and Cropped Document can be extracted only by either `SingleSideScanner` with `visualInspectionZone` enabled or by `FullDocumentScanner`. In the case of `FullDocumentScanner`, if the front & the back side of a document are scanned, Cropped Document and Full Frame are returned for both sides. ::: For the full frame of the document, you can use [`setShouldPassImageTypeToResult`](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-settings.html#method-scandit.datacapture.id.IdCaptureSettings.SetShouldPassImageTypeToResult) when creating the `IdCaptureSettings` object. This will pass the image type to the result, which you can then access in the `CapturedId` object. ```kotlin // Holder's picture as printed on a document: settings.setShouldPassImageTypeToResult(IdImageType.FACE, true) // Cropped image of a document: settings.setShouldPassImageTypeToResult(IdImageType.CROPPED_DOCUMENT, true) // Full camera frame that contains the document: settings.setShouldPassImageTypeToResult(IdImageType.FRAME, true) ``` ## Callbacks and Scanning Workflows The ID Capture Listener provides two callbacks: `onIdCaptured` and `onIdRejected`. The `onIdCaptured` callback is called when an acceptable document is successfully captured, while the `onIdRejected` callback is called when a document is captured but rejected. For a successful capture, the `onIdCaptured` callback provides a `CapturedId` object that contains the extracted information from the document. This object is specific to the type of document scanned. For example, a `CapturedId` object for a US Driver License will contain different fields than a `CapturedId` object for a Passport. For a rejected document, a [RejectionReason](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) is provided in the `onIdRejected` callback to help you understand why the document was rejected and to take appropriate action. These are: * NOT_ACCEPTED_DOCUMENT_TYPE: The document is not in the list of accepted documents. In this scenario, you could direct the user to scan a different document. * INVALID_FORMAT: The document is in the list of accepted documents, but the format is invalid. In this scenario, you could direct the user to scan the document again. * DOCUMENT_VOIDED: The document is in the list of accepted documents, but the document is voided. In this scenario, you could direct the user to scan a different document. * TIMEOUT: The document was not scanned within the specified time. In this scenario, you could direct the user to scan the document again. ## Detect Fake IDs *ID Validate* is a fake ID detection software. It currently supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). Fake ID detection can be performed automatically using the following settings: * [IdCaptureSettings.rejectForgedAamvaBarcodes](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectForgedAamvaBarcodes): Automatically rejects documents whose AAMVA barcode fails authenticity validation. * [IdCaptureSettings.rejectInconsistentData](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectInconsistentData): Automatically rejects documents whose human‑readable data does not match the data encoded in the barcode or MRZ. To enable ID validation for your subscription, please reach out to [Scandit Support](mailto:support@scandit.com). --- ## Get Started # Get Started This page will guide you through the process of adding ID Capture to your Android application. ID Capture is a mode of the Scandit Data Capture SDK that allows you to capture and extract information from personal identification documents, such as driver's licenses, passports, and ID cards. The general steps are: - Create a new Data Capture Context instance - Access a Camera - Configure the Capture Settings - Implement a Listener to Receive Scan Results - Set-up the Capture View and Overlay - Start the Capture Process :::warning Using ID Capture at the same time as other modes (e.g. Barcode Capture) is not supported. ::: ## Prerequisites Before starting with your integration, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. See the [installation guide](/sdks/android/add-sdk.md) for details. :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### External Dependencies import ExternalDependencies from '../../../partials/get-started/_external-deps-android.mdx'; ### Module Overview import IdModuleOverview from '../../../partials/get-started/_id-module-overview.mdx'; ### Mobile ID Scanning ID Capture allows capture of ISO mobile documents (mdoc) using Bluetooth by setting up a BLE (Bluetooth Low Energy) communication between the mdoc app and Scandit SDK. To do so, add the following feature/permissions to `AndroidManifest.xml` file. Note that Scandit SDK may act as either a Central or a Peripheral device so it must request permissions to advertise, scan, and connect to other devices (see the [Android Bluetooth permissions documentation](https://developer.android.com/develop/connectivity/bluetooth/bt-permissions)). ```xml ``` ## Create a Data Capture Context import DataCaptureContextAndroid from '../../../partials/get-started/_create-data-capture-context-android.mdx'; ## Access a Camera Next, you need to create a new instance of the [Camera](https://docs.scandit.com/data-capture-sdk/android/core/api/camera.html#class-scandit.datacapture.core.Camera) class to indicate the camera to stream previews and to capture images. ```kotlin val camera = Camera.getDefaultCamera(IdCapture.createRecommendedCameraSettings()) if (camera == null) { throw IllegalStateException("Failed to init camera!") } dataCaptureContext.setFrameSource(camera) ``` ## Configure the Capture Settings Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scanner type to use and the documents that should be accepted and/or rejected. Check [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) for all the available options. :::tip By default, [anonymized data](./advanced.md#configure-data-anonymization) is not returned in accordance with local regulations for specific documents. This setting can be disabled for testing purposes, but be sure to comply with local laws and requirements in production. ::: ```kotlin val settings = IdCaptureSettings().apply { acceptedDocuments = listOf( // Documents from any region IdCard(IdCaptureRegion.ANY), // Only documents issued by a specific country IdCard(IdCaptureRegion.GERMANY), // Regional documents RegionSpecific(RegionSpecificSubtype.APEC_BUSINESS_TRAVEL_CARD), ) rejectedDocuments = listOf( // Reject passports from certain regions: Passport(IdCaptureRegion.CUBA), ) // To scan only one-sided documents and a given zone: scanner = IdCaptureScanner(SingleSideScanner( barcode = true, machineReadableZone = true, visualInspectionZone = true, )) // To scan both sides of the document: scanner = IdCaptureScanner(FullDocumentScanner()) } ``` Create a new ID Capture mode with the chosen settings: ```kotlin val idCapture = IdCapture.forDataCaptureContext(dataCaptureContext, settings) ``` ## Implement a Listener To receive scan results, implement and [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener). The listener provides two callbacks: `onIdCaptured` and `onIdRejected`. ```kotlin idCapture.addListener(object : IdCaptureListener { override fun onIdCaptured(idCapture: IdCapture, capturedId: CapturedId) { // Success! Handle extracted data here. } override fun onIdRejected(idCapture: IdCapture, capturedId: CapturedId?, rejectionReason: RejectionReason) { // Something went wrong. Inspect the reason to determine the follow-up action. } }) ``` ### Handling Success Capture results are delivered as a [CapturedId](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/captured-id.html#class-scandit.datacapture.id.CapturedId). This class contains data common for all kinds of personal identification documents. For more specific information, use its non-null result properties (e.g. [CapturedId.barcode](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/captured-id.html#property-scandit.datacapture.id.CapturedId.Barcode)). On a successful scan you may read the extracted data from `CapturedId`: ```kotlin override fun onIdCaptured(idCapture: IdCapture, capturedId: CapturedId) { val fullName = capturedId.fullName val dateOfBirth = capturedId.dateOfBirth val dateOfExpiry = capturedId.dateOfExpiry val documentNumber = capturedId.documentNumber // Process data: processData(fullName, dateOfBirth, dateOfExpiry, documentNumber) } ``` :::tip All data fields are optional, so it's important to verify whether the required information is present if some of the accepted documents may not contain certain data. ::: ### Handling Rejection The ID scanning process may fail for various reasons. Start from inspecting [`RejectionReason`](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) to understand the cause. You may wish to implement the follow-up action based on the reason of failure: ```kotlin override fun onIdRejected(idCapture: IdCapture, capturedId: CapturedId, rejectionReason: RejectionReason) { when (rejectionReason) { RejectionReason.TIMEOUT -> { // Ask the user to retry, or offer alternative input method. } RejectionReason.DOCUMENT_EXPIRED -> { // Ask the user to provide alternative document. } RejectionReason.HOLDER_UNDERAGE -> { // Reject the process. } else -> { // Deal with the default case. } } } ``` ## Set up Capture View and Overlay When using the built-in camera as frame source, you may typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```kotlin val dataCaptureView = DataCaptureView.newInstance(this, dataCaptureContext) setContentView(dataCaptureView) ``` Then, add an instance of [IdCaptureOverlay](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) to the view: ```kotlin val overlay = IdCaptureOverlay.newInstance(idCapture, dataCaptureView) ``` The overlay chooses the displayed UI automatically, based on the selected [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings). If you prefer to show a different UI or to temporarily hide it, set the appropriate [IdCaptureOverlay.idLayout](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/ui/id-capture-overlay.html#property-scandit.datacapture.id.ui.IdCaptureOverlay.IdLayout). ## Start the Capture Process Finally, turn on the camera to start scanning: ```kotlin camera.switchToDesiredState(FrameSourceState.ON) ``` --- ## About ID Capture import AboutIdCapture from '../../../partials/intro/_about-id-capture.mdx'; --- ## Supported Documents ## ID Scanning Supported Documents Scandit ID Capture provides various [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/android/id-capture/api/id-capture-scanner.html#id-capture-scanner) types, each designed for specific scanning workflows. These workflows can involve scanning either specific parts of a document or the entire document, including both the front and back sides. This section details the types of documents supported by each scanner type. import IdDocumentsFull from '../../../partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from '../../../partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents import IdValidateDocuments from '../../../partials/advanced/_id-documents-validate.mdx'; --- ## Advanced Configurations import ValidationFlowHowItWorks from '../../../partials/advanced/_validation-flow-how-it-works.mdx'; import ValidationFlowCustomButtons from '../../../partials/advanced/_validation-flow-custom-buttons.mdx'; import ValidationFlowTypingHints from '../../../partials/advanced/_validation-flow-typing-hints.mdx'; import ValidationFlowCloudVLM from '../../../partials/advanced/_validation-flow-cloud-vlm.mdx'; import ReceiptScanning from '../../../partials/advanced/_receipt-scanning.mdx'; import ValidationFlowRequiredOptional from '../../../partials/advanced/_validation-flow-required-optional.mdx'; import ValidationFlowCustomToasts from '../../../partials/advanced/_validation-flow-custom-toasts.mdx'; import ValidationFlowCustomField from '../../../partials/advanced/_validation-flow-custom-field.mdx'; # Advanced Configurations ## Customization of the Overlays ### Basic Overlay To customize the appearance of an overlay you can implement a [LabelCaptureBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/ui/label-capture-basic-overlay-listener.html#interface-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener) and/or [LabelCaptureAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/ui/label-capture-advanced-overlay-listener.html) interface, depending on the overlay(s) you are using. The method [brushForLabel()](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForLabel) is called every time a label is captured, and [brushForField()](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForField) is called for each of its fields to determine the brush for the label or field. ```kotlin overlay.listener = object : LabelCaptureBasicOverlayListener { /* * Customize the appearance of the overlay for the individual fields. */ override fun brushForField( overlay: LabelCaptureBasicOverlay, field: LabelField, label: CapturedLabel, ): Brush? = when (field.name) { "" -> Brush(Color.CYAN, Color.CYAN, 1f) "" -> Brush(Color.GREEN, Color.GREEN, 1f) else -> Brush(Color.TRANSPARENT, Color.TRANSPARENT, 0f) } /* * Customize the appearance of the overlay for the full label. * In this example, we disable label overlays by returning null always. */ override fun brushForLabel( overlay: LabelCaptureBasicOverlay, label: CapturedLabel, ): Brush? = null override fun onLabelTapped( overlay: LabelCaptureBasicOverlay, label: CapturedLabel, ) { /* * Handle the user tap gesture on the label. */ } } ``` :::tip You can also use `LabelCaptureBasicOverlay.setLabelBrush()` and `LabelCaptureBasicOverlay.setCapturedFieldBrush()` to configure the overlay if you don't need to customize the appearance based on the name or content of the fields. ::: ### Advanced Overlay For more advanced use cases, such as adding custom views or implementing Augmented Reality (AR) features, you can use the `LabelCaptureAdvancedOverlay`. The example below creates an advanced overlay, configuring it to display a styled warning message below expiry date fields when they’re close to expiring, while ignoring other fields. ```kotlin // Create an advanced overlay that allows for custom views to be added over detected label fields // This is the key component for implementing Augmented Reality features val advancedOverlay = LabelCaptureAdvancedOverlay.newInstance(dataCaptureManager.getLabelCapture(), view) // Configure the advanced overlay with a listener that handles AR content creation and positioning advancedOverlay.listener = object : LabelCaptureAdvancedOverlayListener { // This method is called when a label is detected - we return null since we're only adding AR elements to specific fields, not the entire label override fun viewForCapturedLabel( overlay: LabelCaptureAdvancedOverlay, capturedLabel: CapturedLabel, ): View? = null // This defines where on the detected label the AR view would be anchored override fun anchorForCapturedLabel( overlay: LabelCaptureAdvancedOverlay, capturedLabel: CapturedLabel, ): Anchor = Anchor.CENTER // This defines the offset from the anchor point for the label's AR view override fun offsetForCapturedLabel( overlay: LabelCaptureAdvancedOverlay, capturedLabel: CapturedLabel, view: View, ): PointWithUnit = PointWithUnit(0f, 0f, MeasureUnit.PIXEL) // This method is called when a field is detected in a label override fun viewForCapturedLabelField( overlay: LabelCaptureAdvancedOverlay, labelField: LabelField, ): View? { // We only want to create AR elements for expiry date fields that are text-based if (labelField.name.contains("expiry", ignoreCase = true) && labelField.type == LabelFieldType.TEXT) { // // data extraction from expiry date field and days until expiry date calculation // // Check if scanned expiry date is to close to actual date if (daysUntilExpiry ```kotlin // Create the overlay val validationFlowOverlay = LabelCaptureValidationFlowOverlay.newInstance( requireContext(), dataCaptureManager.getLabelCapture(), view, ) // Set the listener to receive validation events validationFlowOverlay.listener = this ``` :::note The validation flow overlay uses input fields, so window insets must be handled as described in the [official edge-to-edge Android guidelines](https://developer.android.com/develop/ui/views/layout/edge-to-edge) to keep the software keyboard from covering them. When that is not an option, setting `validationFlowOverlay.shouldHandleKeyboardInsetsInternally = true` lets the overlay handle window insets internally and should resolve the issue in most scenarios. ::: ### Define a Listener When the user has verified that all fields are correctly captured and presses the finish button, the Validation Flow triggers a callback with the final results. To receive these results, implement the [LabelCaptureValidationFlowOverlayListener](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/ui/label-capture-validation-flow-listener.html) interface: ```kotlin // This is called by the validation flow overlay when a label has been fully captured and validated override fun onValidationFlowLabelCaptured(fields: List) { val barcodeData = fields.find { it.name == "" }?.barcode?.data val expiryDate = fields.find { it.name == "" }?.text } ``` ```kotlin val validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.newInstance() validationFlowOverlaySettings.setPlaceholderTextForLabelDefinition(FIELD_EXPIRY_DATE, "MM/DD/YYYY") validationFlowOverlay.applySettings(validationFlowOverlaySettings) ``` ```kotlin val validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.newInstance() validationFlowOverlaySettings.restartButtonText = "Borrar todo" validationFlowOverlaySettings.pauseButtonText = "Pausar" validationFlowOverlaySettings.finishButtonText = "Finalizar" validationFlowOverlay.applySettings(validationFlowOverlaySettings) ``` ```kotlin val validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.newInstance() validationFlowOverlaySettings.standbyHintText = "No label detected, camera paused" validationFlowOverlaySettings.validationHintText = "data fields collected" // X/Y (X fields out of total Y) is shown in front of this string validationFlowOverlay.applySettings(validationFlowOverlaySettings) ``` ```kotlin val validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.newInstance() validationFlowOverlaySettings.validationErrorText = "Incorrect format." validationFlowOverlaySettings.scanningText = "Scan in progress" validationFlowOverlaySettings.adaptiveScanningText = "Processing" validationFlowOverlay.applySettings(validationFlowOverlaySettings) ``` ```kotlin val settings = labelCaptureSettings { label(LABEL_TITLE) { customBarcode(FIELD_BARCODE) { setSymbologies( Symbology.EAN13_UPCA, Symbology.GS1_DATABAR_EXPANDED, Symbology.CODE128 ) } expiryDateText(FIELD_EXPIRY_DATE) { setLabelDateFormat( LabelDateFormat( componentFormat = LabelDateComponentFormat.MDY, acceptPartialDates = false, ) ) } adaptiveRecognition(adaptiveRecognitionMode = AdaptiveRecognitionMode.AUTO) } } ``` See [AdaptiveRecognitionMode](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/label-definition.html#property-scandit.datacapture.label.LabelDefinition.AdaptiveRecognitionMode) for available options. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Smart Label Capture to your application. The general steps are: - Create a new Data Capture Context instance - Configure the LabelCapture mode - Define a listener to handle captured labels - Visualize the scan process - Start the camera - Provide feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import LabelCaptureModuleOverview from '../../../partials/get-started/_smart-label-capture-module-overview.mdx'; ## Create a Data Capture Context import DataCaptureContextAndroid from '../../../partials/get-started/_create-data-capture-context-android.mdx'; ## Configure the Label Capture Mode The main entry point for the Label Capture Mode is the [LabelCapture](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/label-capture.html#class-scandit.datacapture.label.LabelCapture) object. It is configured through [LabelCaptureSettings](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/label-capture-settings.html#class-scandit.datacapture.label.LabelCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) that get informed whenever a new frame has been processed. :::tip You can use Label Definitions provided in Smart Label Capture to set pre-built label types or define your label using pre-built fields. For more information, see the [Label Definitions](label-definitions.md) section. ::: ```kotlin import com.scandit.datacapture.label.capture.LabelCapture import com.scandit.datacapture.label.capture.LabelCaptureSettings import com.scandit.datacapture.label.data.LabelDateComponentFormat import com.scandit.datacapture.label.data.LabelDateFormat import com.scandit.datacapture.barcode.symbology.Symbology // Build LabelCaptureSettings val settings = LabelCaptureSettings.builder() .addLabel() // Add a barcode field with the expected symbologies and pattern .addCustomBarcode() .setSymbologies(Symbology.EAN13_UPCA, Symbology.CODE128) .setAnchorRegexes("\\d{12,14}") .buildFluent("") // Add a text field for capturing expiry dates .addExpiryDateText() .isOptional(true) .setLabelDateFormat(LabelDateFormat(LabelDateComponentFormat.MDY, false)) .buildFluent("") .buildFluent("") .build() // Create the label capture mode with the settings and data capture context val labelCapture = LabelCapture.forDataCaptureContext(dataCaptureContext, settings) ``` ## Define a Listener to Handle Captured Labels To get informed whenever a new label has been recognized, add a [LabelCaptureListener](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) through [LabelCapture.addListener()](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/label-capture.html#method-scandit.datacapture.label.LabelCapture.AddListener) and implement the listener methods to suit your application’s needs. First conform to the `LabelCaptureListener` interface. Here is an example of how to implement a listener that processes the captured labels based on the label capture settings defined above. In this example, we create a `LabelCaptureRepository` class that implements the `LabelCaptureListener` interface. This class is responsible for handling the captured labels and processing them accordingly. Depending on your app architecture and whether you use dependency injection or not, you may use a fragment or a repository to implement the listener. ```kotlin labelCapture.addListener(object : LabelCaptureListener { override fun onSessionUpdated( mode: LabelCapture, session: LabelCaptureSession, data: FrameData, ) { /* * The session update callback is called for every processed frame. * Check if the session contains any captured labels; * if not, continue capturing. */ val capturedLabel = session.capturedLabels.firstOrNull() ?: return /* * Given the label capture settings defined above, * barcode data will always be present. */ val barcodeData = capturedLabel.fields .find { it.name == "" }?.barcode?.data /* * The expiry date field is optional. Check for null in your result handling. */ val expiryDate = capturedLabel.fields .find { it.name == "" }?.asDate() /* * Disable the label capture mode after a label has been captured * to prevent it from capturing the same label multiple times. */ mode.isEnabled = false /* * Consider handling the results in a coroutine to avoid blocking the main thread * when updating the UI. */ coroutineScope.launch { handleResults(barcodeData, expiryDate) Feedback.defaultFeedback().emit() } } }) ``` ## Visualize the Scan Process The capture process can be visualized by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy. The view controls what UI elements such as the viewfinder, as well as the overlays that are shown to visualize captured labels. To visualize the results of Label Capture you can use two overlays: - [LabelCaptureBasicOverlay](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/ui/label-capture-basic-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureBasicOverlay) - [LabelCaptureAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/ui/label-capture-advanced-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureAdvancedOverlay) :::tip The overlays can be used independently of each other, but you can also use both at the same time as each can serve to extend the functionality of the other. ::: Here is an example of how to add a `LabelCaptureBasicOverlay` to the `DataCaptureView`: ```kotlin /* * Create the data capture view and attach it to the data capture context created earlier. */ val dataCaptureView = DataCaptureView.newInstance(requireContext(), dataCaptureContext) /* * Add the data capture view to your view hierarchy, e.g. with setContentView or findViewById. */ val container = /* get your containing view here, e.g. with inflate or findViewById */ container.addView( dataCaptureView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, ) /* * Create the overlay with the label capture mode and data capture view created earlier. */ val overlay = LabelCaptureBasicOverlay.newInstance(labelCapture, dataCaptureView) overlay.viewfinder = RectangularViewfinder(RectangularViewfinderStyle.SQUARE) ``` :::tip See the [Advanced Configurations](advanced.md) section for more information about how to customize the appearance of the overlays and how to use the advanced overlay to display arbitrary Android views such as text views, icons or images. ::: ## Start the Camera Next, you need to create a new instance of the [Camera](https://docs.scandit.com/data-capture-sdk/android/core/api/camera.html#class-scandit.datacapture.core.Camera) class to indicate the camera to stream previews and to capture images. When initializing the camera, you can pass the recommended camera settings for Label Capture. ```kotlin val camera = Camera.getDefaultCamera(LabelCapture.createRecommendedCameraSettings()) if (camera == null) { throw IllegalStateException("Failed to init camera!") } dataCaptureContext.setFrameSource(camera) ``` Once the Camera, DataCaptureContext, DataCaptureView and LabelCapture are initialized, you can switch on the camera to start capturing labels. Typically, this is done on resuming the view and when the user granted permission to use the camera, or once the user pressed continue scanning after handling a previous scan. ```kotlin camera.switchToDesiredState(FrameSourceState.ON) ``` ## Provide Feedback Smart Label Capture provides customizable feedback, emitted automatically when a label is recognized and successfully processed, configurable via [`LabelCapture.feedback`](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/label-capture.html#property-scandit.datacapture.label.LabelCapture.Feedback). You can use the default feedback, or configure your own sound or vibration. :::tip If you already have a [Feedback](https://docs.scandit.com/data-capture-sdk/android/core/api/feedback.html#class-scandit.datacapture.core.Feedback) instance implemented in your application, remove it to avoid double feedback. ::: ```kotlin labelCapture.feedback = LabelCaptureFeedback.defaultFeedback() ``` :::note Audio feedback is only played if the device is not muted. ::: --- ## About Smart Label Capture import AboutLabelCapture from '../../../partials/intro/_about-smart-label-capture.mdx'; import ValidationFlow from '../../../partials/intro/_about_validation_flow.mdx'; See [here](./advanced.md#validation-flow) for more details. --- ## Label Definitions # Label Definitions A **Label Definition** is a configuration that defines the label, and its relevant fields, that Smart Label Capture should recognize and extract during scans. Smart Label Capture provides a [Label Definition](https://docs.scandit.com/data-capture-sdk/android/label-capture/api/label-definition.html#label-definition) API, enabling you to configure and extract structured data from predefined and custom labels. This feature provides a flexible way to recognize and decode fields within a specific label layout such as price tags, VIN labels, or packaging stickers without needing to write custom code for each label type. There are two approaches to using label definitions: - [**Pre-built Labels**](#pre-built-labels) - [**Custom Labels**](#custom-labels) ## Pre-built Labels Smart Label Capture includes ready-made label definitions for common use cases. These pre-built options let you recognize and extract information from standard label types without creating custom configurations: ### Example: Price label Use the `LabelCaptureSettings` builder to configure a pre-built label definition for price labels, such as those found in retail environments: ![Price Label Example](/img/slc/price-label.png) ```kotlin val settings = LabelCaptureSettings.builder() .addLabel(LabelDefinition.createPriceCaptureDefinition("price-label")) .build() ``` ## Custom Labels If Smart Label Capture’s pre-built options don’t fit your needs, define a custom label instead. Custom labels can combine your own fields with any of the available pre-built ones. :::tip The following characters are recognized: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ()-./:,$¶"`. ::: ### Custom Fields There are two types of custom fields you can define: The following methods are available to configure custom fields: | Method | Optional | Description | |--------|----------|-------------| | `valueRegexes` | No | The regex patterns that identify the target string in the scanned content. | | `anchorRegexes` | Yes | Used to specify keywords or phrases that help identify the context of the field. This is particularly useful when the label contains multiple fields that could match the same pattern (e.g., when both packaging and expiry dates are present). | | `symbologies` | No | The barcode symbologies to match for barcode fields. This is important for ensuring that the field only captures data from specific barcode types, enhancing accuracy and relevance. | | `isOptional` | Yes | Whether the field is optional or mandatory. This is helpful when certain fields may not be present on every scan. | #### Example: Fish Shipping Box This example shows how to create a custom label definition for a fish shipping box, which includes fields for barcode and batch number. ![Fish Shipping Box Example](/img/slc/fish-shipping-box.png) ```kotlin val settings = LabelCaptureSettings.builder() .addLabel() .addCustomBarcode() .setSymbologies(Symbology.CODE128) .buildFluent("barcode-field") .addCustomText() .setAnchorRegexes("Batch") .setValueRegexes("FZ\\d{5,10}") .isOptional(true) .buildFluent("batch-number-field") .buildFluent("shipping-label") .build() ``` ### Pre-built Fields You can also build your label using pre-built fields. These common fields speed up integration because their `valueRegexes`, `anchorRegexes`, and `symbologies` are already predefined. Customization of pre-built fields is done via the `valueRegexes`, `anchorRegexes`, and `isOptional` methods, which allow you to specify the expected format of the field data. :::tip All pre-built fields come with default `valueRegexes` and `anchorRegexes` that are suitable for most use cases. **Using either method is optional and will override the defaults**. The `resetAnchorRegexes` method can be used to remove the default `anchorRegexes`, allowing you to rely solely on the `valueRegexes` for detection. ::: import FeatureList from '@site/src/components/FeatureList'; #### Barcode Fields #### Price and Weight Fields #### Date and Custom Text Fields #### Example: Hard disk drive label This example demonstrates how to configure a label definition for a hard disk drive (HDD) label, which typically includes common fields like serial number and part number. ![Hard Disk Drive Label Example](/img/slc/hdd-label.png) ```kotlin val settings = LabelCaptureSettings.builder() .addLabel() .addSerialNumberBarcode() .buildFluent("serial-number") .addPartNumberBarcode() .buildFluent("part-number") .buildFluent("hdd-label") .build() ``` --- ## Adding AR Overlays # Adding AR Overlays In the previous section we covered how to vizualize the scan process using the `BarcodeBatchBasicOverlay`. This section describes the steps to add custom AR overlays to your MatrixScan application. There are two ways to add custom AR overlays to your application: * Use [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) class, our ready-to-use implementation for view-based AR overlays. * Provide your own fully custom implementation by using the function [BarcodeBatchListener.onSessionUpdated()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) to retrieve the barcode’s current screen position for each frame. :::note The first option is the easiest and recommended approach for most applications. It covers adding, removing, and animating the overlay’s views whenever needed. In addition, this option is flexible enough to cover the majority of use cases. ::: ## Using BarcodeBatchAdvancedOverlay The advanced overlay combined with its [listener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) offers an easy way of adding augmentations to your `DataCaptureView`. This example describes the steps to add a view above each barcode showing its content. First, create a new instance of `BarcodeBatchAdvancedOverlay` and add it to your `DataCaptureView`: ```kotlin # import com.scandit.datacapture.barcode.batch.capture.BarcodeBatch # import com.scandit.datacapture.barcode.batch.ui.overlay.BarcodeBatchAdvancedOverlay # lateinit var barcodeBatch: BarcodeBatch val overlay = BarcodeBatchAdvancedOverlay.newInstance(barcodeBatch, dataCaptureView) ``` There are two ways to proceed from here: * Add a [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) to the overlay. * Use the `setters` in the `overlay` to specify the view, anchor, and offset for each barcode. :::note The second way takes priority over the first one, meaning that if a view for a barcode has been set using [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), the function [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode), won’t be invoked for that specific barcode. ::: ### Using the Listener For this option, keep in mind that: * You need to conform to [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener). This interface’s methods are invoked every time a barcode is newly tracked. * [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) asks for a view to animate on top of the barcode. Returning null shows no view. * [BarcodeBatchAdvancedOverlayListener.anchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode) asks how to anchor the view to the barcode through Anchor. Be aware that it anchors the view’s center to the anchor point. To achieve anchoring the top of the view or the bottom etc. you need to set an offset as explained in the next point. * [BarcodeBatchAdvancedOverlayListener.offsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode) asks for an offset that is applied on the already anchored view. This offset is expressed through a [PointWithUnit](https://docs.scandit.com/data-capture-sdk/android/core/api/common.html#struct-scandit.datacapture.core.PointWithUnit). ```kotlin // Create and return the view you want to show for this tracked barcode. You can also return null, to have no view for this barcode. fun viewForTrackedBarcode( overlay: BarcodeBatchAdvancedOverlay, trackedBarcode: TrackedBarcode, ): View = TextView(this).apply { setBackgroundColor(Color.WHITE) layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, ) text = trackedBarcode.barcode.data } // As we want the view to be above the barcode, we anchor the view's center to the top-center of the barcode quadrilateral. // Use the function 'offsetForTrackedBarcode' below to adjust the position of the view by providing an offset. fun anchorForTrackedBarcode( overlay: BarcodeBatchAdvancedOverlay, trackedBarcode: TrackedBarcode, ): Anchor = Anchor.TOP_CENTER // This is the offset that will be applied to the view. // You can use MeasureUnit.FRACTION to give a measure relative to the view itself, the sdk will take care of transforming this into pixel size. // We now center horizontally and move up the view to make sure it's centered and above the barcode quadrilateral by half of the view's height. fun offsetForTrackedBarcode( overlay: BarcodeBatchAdvancedOverlay, trackedBarcode: TrackedBarcode, view: View, ): PointWithUnit = PointWithUnit( FloatWithUnit(0f, MeasureUnit.FRACTION), FloatWithUnit(-1f, MeasureUnit.FRACTION), ) ``` ### Using the Setters The function `BarcodeBatchListener.onSessionUpdated()` gives you access to a `session`, which contains all added, updated and removed tracked barcodes. From here you can create the view you want to display, and then call: * [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode) * [BarcodeBatchAdvancedOverlay.setAnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode) * [BarcodeBatchAdvancedOverlay.setOffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode) ```kotlin fun onSessionUpdated( mode: BarcodeBatch, session: BarcodeBatchSession, data: FrameData, ) { // Be careful, this function is not invoked on the main thread! runOnUiThread { session.addedTrackedBarcodes.forEach { trackedBarcode -> val textView = TextView(this).apply { setBackgroundColor(Color.WHITE) layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT ) text = trackedBarcode.barcode.data } overlay.setViewForTrackedBarcode(trackedBarcode, textView) overlay.setAnchorForTrackedBarcode( trackedBarcode, Anchor.TOP_CENTER, ) overlay.setOffsetForTrackedBarcode( trackedBarcode, PointWithUnit( FloatWithUnit(0f, MeasureUnit.FRACTION), FloatWithUnit(-1f, MeasureUnit.FRACTION), ) ) } } } ``` ## Using Custom Implementations If you do not want to use the overlay, it is also possible to add augmented reality features based on the tracking identifier and the [quadrilateral](https://docs.scandit.com/data-capture-sdk/android/core/api/common.html#struct-scandit.datacapture.core.Quadrilateral) coordinates of every tracked barcode. When doing so, keep the following in mind: * Set a `BarcodeBatchListener` on the barcode tracking * In the `BarcodeBatchListener.onSessionUpdated()` function, fetch the added and removed tracked barcodes * Create and show the views for the added barcodes * Remove the views for the lost barcode * Add a method that is called 60fps when `BarcodeBatch` is enabled. In this method, for each [TrackedBarcode](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/tracked-barcode.html#class-scandit.datacapture.barcode.batch.TrackedBarcode) on-screen, update the position based on [TrackedBarcode.location](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location). Please note that there is no need to animate the change of location, the change of position will happen frequently enough that the view will look as it is animated :::note The frame coordinates from `TrackedBarcode.location` need to be mapped to view coordinates, using [DataCaptureView.mapFrameQuadrilateralToView()](https://docs.scandit.com/data-capture-sdk/android/core/api/ui/data-capture-view.html#method-scandit.datacapture.core.ui.DataCaptureView.MapFrameQuadrilateralToView). ::: ```kotlin fun onSessionUpdated( mode: BarcodeBatch, session: BarcodeBatchSession, data: FrameData, ) { // Be careful, this function is not invoked on the main thread! runOnUiThread { session.removedTrackedBarcodes.forEach { lostTrackIdentifier -> // You now know the identifier of the tracked barcode that has been lost. Usually here you would remove the views associated. } session.addedTrackedBarcodes.forEach { trackedBarcode -> // Fixed identifier for the tracked barcode. val trackingIdentifier = trackedBarcode.identifier // Current location of the tracked barcode. val location = trackedBarcode.location val quadrilateral = dataCaptureView.mapFrameQuadrilateralToView(location) // You now know this tracking's identifier and location. Usually here you would create and show the views. } } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan to your application. The general steps are: - Creating a new Data Capture Context instance - Configuring the MatrixScan mode - Using the built-in camera - Visualizing the scan process - Providing feedback - Disabling barcode tracking ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### External Dependencies The Scandit Data Capture SDK modules depend on a few standard libraries that you can find listed below. If you are including the Scandit Data Capture SDK through **Gradle** or **Maven**, all of these dependencies are automatically pulled in and there is no need for you to do anything further. On the other hand, if you directly add the AAR files to the project, you need to add these dependencies yourself. | Module | Dependencies | | ----------- | ----------- | | *ScanditCaptureCore.aar* | org.jetbrains.kotlin:kotlin-stdlib:[version]; androidx.annotation:annotation:[version]; com.squareup.okhttp3:okhttp:4.9.2 | | *ScanditBarcodeCapture.aar* | org.jetbrains.kotlin:kotlin-stdlib:[version]; androidx.annotation:annotation:[version] | | *ScanditParser.aar* | No dependencies | ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create a Data Capture Context import DataCaptureContextAndroid from '../../../partials/get-started/_create-data-capture-context-android.mdx'; ## Configure the Barcode Batch Mode The main entry point for the Barcode Batch Mode is the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object. It is configured through [BarcodeBatchSettings](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) that gets informed whenever a new frame has been processed. :::note Typically you do not need to implement to a `BarcodeBatchListener`, instead you may add a [BarcodeBatchBasicOverlay](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) and implement to a [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener). ::: For this task, we setup Barcode Batch for tracking QR codes: ```kotlin val settings = BarcodeBatchSettings().apply { enableSymbology(Symbology.QR, true) } ``` Next, create a `BarcodeBatch` instance with the data capture context and the settings initialized in the previous steps: ```kotlin val barcodeBatch = BarcodeBatch.forDataCaptureContext(dataCaptureContext, settings) ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications uses the built-in camera of the device, for instance, the world-facing camera of a device. The remainder of this tutorial assumes that you use the built-in camera. :::note In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the *AndroidManifest.xml* file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These must be used to achieve the best performance and user experience for the respective mode. The following lines show how to get the recommended settings and create the camera from it: ```kotlin val cameraSettings = BarcodeBatch.createRecommendedCameraSettings() // Depending on the use case further camera settings adjustments can be made here. val camera = Camera.getDefaultCamera() camera?.applySettings(cameraSettings, null) ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/android/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```kotlin dataCaptureContext.setFrameSource(camera) ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/android/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.ON](https://docs.scandit.com/data-capture-sdk/android/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```kotlin camera?.switchToDesiredState(FrameSourceState.ON) ``` ## Visualize the Scan Process When using the built-in camera as frame source, you typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```kotlin val dataCaptureView = DataCaptureView.newInstance(this, dataCaptureContext) setContentView(dataCaptureView) ``` To visualize the results of Barcode Batch, first you need to add the following [overlay](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay): ```kotlin val overlay = BarcodeBatchBasicOverlay.newInstance(barcodeBatch, dataCaptureView) ``` Once the overlay has been added, you must conform to the [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) interface. The method [BarcodeBatchBasicOverlayListener.brushForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode) is invoked every time a new tracked barcode appears and it can be used to set a brush used to highlight that specific barcode in the [overlay](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay). ```kotlin override fun brushForTrackedBarcode( overlay: BarcodeBatchBasicOverlay, trackedBarcode: TrackedBarcode, ): Brush { // Return a custom Brush based on the tracked barcode. } ``` If you want to make the highlights tappable, you need to implement the [BarcodeBatchBasicOverlayListener.onTrackedBarcodeTapped()] method. ```kotlin override fun onTrackedBarcodeTapped( overlay: BarcodeBatchBasicOverlay, trackedBarcode: TrackedBarcode, ) { // A tracked barcode was tapped. } ``` ## Barcode Batch Feedback Barcode Batch, unlike Barcode Capture, doesn’t emit feedback (sound or vibration) when a new barcode is recognized. However, you may implement a `BarcodeBatchListener` to provide a similar experience. Here, we use the default [Feedback](https://docs.scandit.com/data-capture-sdk/android/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration. First, we create a feedback and release it after it is no longer used, to avoid resources being unnecessarily held. ```kotlin val feedback = Feedback.defaultFeedback() ``` Next, use this `feedback` in a `BarcodeBatchListener`: ```kotlin class FeedbackListener: BarcodeBatchListener { val feedback = Feedback.defaultFeedback() override fun onObservationStarted(barcodeBatch: BarcodeBatch) { // Called when Barcode Batch is started. // We don't use this callback in this guide. } override fun onObservationStopped(barcodeBatch: BarcodeBatch) { // Called when Barcode Batch is stopped. // We don't use this callback in this guide. } override fun onSessionUpdated( mode: BarcodeBatch, session: BarcodeBatchSession, data: FrameData, ) { if (session.addedTrackedBarcodes.isNotEmpty()) { feedback.emit() } } } ``` [BarcodeBatchListener.onSessionUpdated()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) is invoked for every processed frame. The [session](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession) parameter contains information about the currently tracked barcodes, in particular, the newly recognized ones. We check if there are any and if so, we emit the feedback. As the last step, register the listener responsible for emitting the feedback with the `BarcodeBatch` instance. ```kotlin barcodeBatch.addListener(FeedbackListener()) ``` ## Disable Barcode Batch To disable barcode tracking, set `BarcodeBatch.isEnabled` to `FALSE`. The effect is immediate, no more frames get processed after the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off or put it in standby calling [SwitchToDesiredState](https://docs.scandit.com/data-capture-sdk/android/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [StandBy](https://docs.scandit.com/data-capture-sdk/android/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.Standby). --- ## About MatrixScan Batch # About MatrixScan Batch import AboutMatrixScan from '../../../partials/intro/_about-matrixscan.mdx' --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan AR to your application. Implementing MatrixScan AR involves two primary elements: - Barcode AR: The data capture mode that is used for scan and check functionality. - A Barcode AR View: The pre-built UI elements used to highlight items to be checked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode AR Mode - Setup the Barcode AR View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### External Dependencies import ExternalDependencies from '../../../partials/get-started/_external-deps-android.mdx'; ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create a Data Capture Context import DataCaptureContextAndroid from '../../../partials/get-started/_create-data-capture-context-android.mdx'; ## Configure the Barcode AR Mode The main entry point for the Barcode AR Mode is the `BarcodeAr` object. You can configure the supported Symbologies through its [`BarcodeArSettings`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-ar-settings.html). Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```kotlin val settings = BarcodeArSettings().apply { enableSymbology(Symbology.EAN13_UPCA, true) } ``` Then create the mode with the previously created settings: ```kotlin val barcodeAr = BarcodeAr(dataCaptureContext, settings) ``` ## Setup the `BarcodeArView` MatrixScan AR’s built-in AR user interface includes buttons and overlays that guide the user through the scan and check process. By adding a [`BarcodeArView`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView), the scanning interface is added automatically to your application. The `BarcodeArView` is where you provide the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider) to supply the highlight and annotation information for the barcodes to be checked. If *null*, a default highlight is used and no annotations are provided. The `BarcodeArView` appearance can be customized through [`BarcodeArViewSettings`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-ar-view-settings.html#class-scandit.datacapture.barcode.check.ui.BarcodeArViewSettings), properties on the`BarcodeArView`, and the corresponding settings for your desired highlights and/or annotations, to match your application’s look and feel. The following settings can be customized: * Audio and haptic feedback * Camera position * Torch button visibility and its position * Switch camera button visibility and its position * Zoom control visibility and its position * The size, colors, and styles of the highlights and annotations ```kotlin val viewSettings = BarcodeArViewSettings().apply { hapticEnabled = false soundEnabled = false defaultCameraPosition = CameraPosition.USER_FACING } ``` Next, create a `BarcodeArView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodeArView` is automatically added to the provided parent view. ```kotlin val barcodeArView = BarcodeArView(parentView, barcodeAr, dataCaptureContext, viewSettings).apply { shouldShowCameraSwitchControl = true shouldShowTorchControl = true shouldShowZoomControl = true cameraSwitchControlPosition = Anchor.TOP_RIGHT torchControlPosition = Anchor.BOTTOM_RIGHT zoomControlPosition = Anchor.TOP_LEFT } ``` Configure the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider). ```kotlin private class AnnotationProvider: BarcodeArAnnotationProvider { override fun annotationForBarcode(context: Context, barcode: Barcode, callback: Callback) { val annotation = BarcodeArStatusIconAnnotation(context, barcode).apply { text = "Example annotation" } callback.onData(annotation) } } private class HighlightProvider: BarcodeArHighlightProvider { override fun highlightForBarcode(context: Context, barcode: Barcode, callback: Callback) { callback.onData(BarcodeArRectangleHighlight(context, barcode)) } } ``` And set them to the view: ```kotlin barcodeArView.highlightProvider = HighlightProvider() barcodeArView.annotationProvider = AnnotationProvider() ``` Connect the `BarcodeArView` to the Android lifecycle. The view is dependent on calling `BarcodeArView.onPause()`, `BarcodeArView.onResume()`, and `BarcodeArView.onDestroy()` to set up the camera and its overlays properly. ```kotlin override fun onResume() { super.onResume() barcodeArView.onResume() } override fun onPause() { super.onPause() barcodeArView.onPause() } override fun onDestroy() { super.onDestroy(); barcodeArView.onDestroy() } ``` ## Register the Listener If you want a callback when a highlight is tapped, register a [BarcodeArViewUiListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-ar-view.html#interface-scandit.datacapture.barcode.check.ui.IBarcodeArViewUiListener). ```kotlin barcodeArView.uiListener = object : BarcodeArViewUiListener { override fun onHighlightForBarcodeTapped(barcodeAr: BarcodeAr, barcode: Barcode, highlight: BarcodeArHighlight, highlightView: View) { // handle tap } } ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `barcodeArView.start()`. ```kotlin barcodeArView.start() ``` --- ## About MatrixScan AR # About MatrixScan AR import AboutMatrixScanCheck from '../../../partials/intro/_about-matrixscan-ar.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Count is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Count to best fit your needs. ## Scanning Against a List There is a function to set a list of expected barcodes if you are scanning against a manifest or item list. If this is used, a progress bar is added to the UI so you can keep track of the process while scanning. When scanning against a list, the UI will also show red icons to mark scanned barcodes that aren’t present on the list. To set the list of expected barcodes, use the following code: ```kotlin val targetBarcodes = listOf( TargetBarcode.create("data", 1) ) val captureList = BarcodeCountCaptureList.create(this, targetBarcodes) barcodeCount.setBarcodeCountCaptureList(captureList) ``` ## Barcode Count Status This feature is used to provide users with more details regarding the items they’re scanning in order to aid effective handling. The icons appear as an AR overlay after tapping the “Status Mode” button and can be used to highlight the following: ![Barcode Count Status](/img/matrixscan-count/barcode_count_status.png) See the [Expiry Management Sample](https://github.com/Scandit/datacapture-android-samples/tree/master/03_Advanced_Batch_Scanning_Samples/02_Counting_and_Receiving/ExpiryManagementSample) for an example of how to use this feature. ## Clustering import Clustering from '../../../partials/count/_clustering.mdx' ## Tote Mapping import Totes from '../../../partials/count/_tote-mapping.mdx' ## Strap Mode It can be difficult to reach the shutter button if the smart device is attached to the user’s wrist by a strap or similar. You can enable a floating shutter button that can be positioned by the end user in a more ergonomically suitable position: ```kotlin barcodeCountView.shouldShowFloatingShutterButton = true ``` ## Filtering If there several types of barcodes on your label you may want to scan only one of them. In this case, you can filter the others out by symbology, symbol count, or setting a regex. For example, you might want to scan only Code 128 barcodes and no PDF417 barcodes. You can do this by setting the following: ```kotlin val settings = BarcodeCountSettings().apply { enableSymbologies(enabledSymbologies) } val excludedSymbologies = setOf(Symbology.PDF417) val filterSettings = settings.filterSettings filterSettings.excludedSymbologies = excludedSymbologies ``` Or to exclude all the barcodes starting with 4 numbers: ```kotlin val settings = BarcodeCountSettings() val filterSettings = settings.filterSettings filterSettings.excludedCodesRegex = "^1234.*" ``` By default the filters applied to the relevant barcodes are transparent, but you can use [`BarcodeFilterHighlightSettings`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-filter-highlight-settings.html#barcode-filter-highlight-settings) to change the color and level of transparency. ![Different Filters in MatrixScan Count](/img/matrixscan-count/filtering_styles.png) ## Clear Screen Button There are situations in which the user may find it helpful to clean up their screen (i.e. clear all the AR overlays) but keep the list of barcodes scanned. For this you can enable the “Clear screen” button: ```kotlin barcodeCountView.shouldShowClearHighlightsButton = true ``` ## Customizing the AR Overlays MatrixScan Count comes with recommended and user-tested AR overlays. However, if you wish to customize the overlay colors, once the overlay has been added, you can conform to the [BarcodeCountViewListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-count-view-listener.html#interface-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener) interface. The methods [BarcodeCountViewListener.brushForRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForRecognizedBarcode) and [BarcodeCountViewListener.brushForUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForUnrecognizedBarcode) are invoked every time a new recognized or unrecognized barcode appears. These can be used to set a brush that will be used to highlight that specific barcode in the overlay. Keep in mind that these methods are relevant only when using the style [BarcodeCountViewStyle.DOT](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-count-view.html#value-scandit.datacapture.barcode.count.ui.BarcodeCountViewStyle.Dot). ```kotlin override fun brushForRecognizedBarcode(view: BarcodeCountView, trackedBarcode: TrackedBarcode): Brush? { // Return a custom brush } override fun brushForRecognizedBarcodeNotInList(view: BarcodeCountView, trackedBarcode: TrackedBarcode): Brush? { // Return a custom brush } ``` ## Notifications If you want to be notified when a user taps on an overlay, you need to implement the [BarcodeCountViewListener.onRecognizedBarcodeTapped()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnRecognizedBarcodeTapped) and [BarcodeCountViewListener.onUnrecognizedBarcodeTapped()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped) methods. ```kotlin override fun onRecognizedBarcodeTapped(view: BarcodeCountView, trackedBarcode: TrackedBarcode) { // Do something with the tapped barcode } override fun onRecognizedBarcodeNotInListTapped(view: BarcodeCountView, trackedBarcode: TrackedBarcode) { // Do something with the tapped barcode } ``` ## Disable UI Elements The UI is an integral part of MatrixScan Count and we do not recommend that you use it without it. However, if you wish to disable UI elements you can so as follows. To disable buttons: ```kotlin barcodeCountView.shouldShowListButton = false barcodeCountView.shouldShowExitButton = false barcodeCountView.shouldShowShutterButton = false ``` To disable feedback and hints: ```kotlin barcodeCountView.shouldShowUserGuidanceView = false barcodeCountView.shouldShowHints = false ``` --- ## Get Started # Get Started This page describes the steps to add MatrixScan Count to your application. :::note MatrixScan Count is implemented via [BarcodeCount](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount). ::: The general steps are: - Create a new Data Capture Context instance - Configure the Barcode Count Mode - Obtain the camera instance and set frame source - Register the listener to be informed when scan phase is complete - Set the capture view and AR overlays - Configure the camera for scanning view - Store and retrieve the captured barcodes - Reset the Barcode Count Mode - List and exit callbacks ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### External Dependencies import ExternalDependencies from '../../../partials/get-started/_external-deps-android.mdx'; ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create a Data Capture Context import DataCaptureContextAndroid from '../../../partials/get-started/_create-data-capture-context-android.mdx'; ## Configure the Barcode Count Mode The main entry point for the Barcode Count Mode is the `BarcodeCount` object. It is configured through [BarcodeCountSettings](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-count-settings.html) and allows you to register one or more listeners that are informed whenever a scan phase has finished. Here we set up Barcode Count for tracking EAN13 codes, however you must change this to the appropriate symbologies for your use case. If you are sure that your environment has only unique barcodes, you can also enable `BarcodeCountSettings.expectsOnlyUniqueBarcodes`. This option improves scanning performance as long as you are sure that no duplicates are present. ```kotlin val settings = BarcodeCountSettings().apply { setSymbologyEnabled(Symbology.EAN13_UPCA, true) } ``` Next, create a `BarcodeCount` instance with the Data Capture Context and the settings initialized in the previous step: ```kotlin val barcodeCount = BarcodeCount.forDataCaptureContext(dataCaptureContext, settings) ``` ## Camera Instance And Set Frame Source Our recommended camera settings should be used to achieve the best performance and user experience. The following code shows how to get the recommended settings for MatrixScan Count and create the camera from it: ```kotlin val cameraSettings = BarcodeCount.createRecommendedCameraSettings() val camera = Camera.getDefaultCamera(cameraSettings) ``` Because the frame source is configurable the data capture context must be told which frame source to use. This is done with a call to [`DataCaptureContext.setFrameSource()`](https://docs.scandit.com/data-capture-sdk/android/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```kotlin dataCaptureContext.setFrameSource(camera) ``` ## Registering the Listener To keep track of the barcodes that have been scanned, implement the [BarcodeCountListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) interface and register the listener. ```kotlin // Register self as a listener to monitor the barcode count session. barcodeCount.addListener(this) ``` [`BarcodeCountListener.onScan()`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan) is called when the scan phase has finished and results can be retrieved from [`BarcodeCountSession`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession). ## Setting the Capture View and AR Overlays MatrixScan Count’s built-in AR user interface includes buttons and overlays that guide the user through the capturing process. By adding a [`BarcodeCountView`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) the scanning interface will be added automatically to your application. Add a `BarcodeCountView` to your view hierarchy: ```kotlin val barcodeCountView = BarcodeCountView.newInstance(context, captureView, barcodeCount) ``` ## Configuring the Camera for Scanning View The camera is not automatically turned on when you are in a scanning view. You need to set up the camera so that it switches on when needed and it switches off when not needed anymore. Similarly `BarcodeCount` should also be enabled and disabled. For example, you should switch off the camera when the `BarcodeCountView` is not visible and switch on the camera when the `BarcodeCountView` is visible. For example: ```kotlin override fun onPause() { camera.switchToDesiredState(FrameSourceState.OFF) super.onPause() } override fun onResume() { super.onResume() camera.switchToDesiredState(FrameSourceState.ON) } ``` ## Store And Retrieve Scanned Barcodes The values captured as part of the scanning process are part of the session, and the session is not accessible outside [`BarcodeCountListener.onScan`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan). We recommend you store the values to present a list, for example when the user taps the list icon. To do this, make a copy of [`BarcodeCountSession.recognizedBarcodes`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-count-session.html#property-scandit.datacapture.barcode.count.BarcodeCountSession.RecognizedBarcodes): ```kotlin override fun onScan( mode: BarcodeCount, session: BarcodeCountSession, data: FrameData, ) { val allRecognizedBarcodes = session.recognizedBarcodes } ``` ## Resetting the Barcode Count Mode When the scanning process is over, you need to reset the mode to make it ready for the next process. This clears the list of barcodes scanned and all the AR overlays. To reset Barcode Count’s scanning process, call the `BarcodeCount.reset` method: ```kotlin barcodeCount.reset() ``` ## List and Exit Callbacks The UI includes two icons (buttons): “List” and “Exit”. The SDK provides the callbacks so you can add the desired action when those icons are tapped by the user: ```kotlin override fun onListButtonTapped() { // Show the current progress but the order is not completed } override fun onExitButtonTapped(view: BarcodeCountView) { // The order is completed } ``` --- ## About MatrixScan Count # About MatrixScan Count import AboutMatrixScanCount from '../../../partials/intro/_about-matrixscan-count.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Find is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Find to best fit your needs. ## BarcodeFind Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodeFind` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodeFindListener`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-find-listener.html#interface-scandit.datacapture.barcode.find.IBarcodeFindListener) on the mode itself, keeping in mind that these listeners are called from a background thread. ```kotlin barcodeFind.addListener(object : BarcodeFindListener() { override fun onSearchPaused(foundItems: Set) { // The mode was paused } override fun onSearchStarted() { // The mode was started } override fun onSearchStopped(foundItems: Set) { // The mode was stopped after the finish button was clicked } }) ``` ## Multiple criteria You can assign different brushes to each BarcodeFindItem, so they appear visually different to the end user. This can be used to make some items stand out more, or to help the user mentally group certain items together. ```kotlin val availableBrush = Brush(Color.GREEN, Color.GREEN, 1f) val expiredBrush = Brush(Color.RED, Color.RED, 1f) val items = setOf( BarcodeFindItem( BarcodeFindItemSearchOptions("9783598215438", availableBrush), BarcodeFindItemContent("Mini Screwdriver Set", "(6-Piece)", null), ), BarcodeFindItem( BarcodeFindItemSearchOptions("9783598215414", expiredBrush), null, ), ) ``` ## Set up a transformation Sometimes, the barcode data needs to be transformed. For example, if the barcode contains the product identifier and other information, when a product is scanned, the barcode data is first parsed (via a transformation) and then the input list is checked. First implement the [BarcodeFindTransformer](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-find-transformer.html#interface-scandit.datacapture.barcode.find.IBarcodeFindTransformer) interface. For example, if you want to only consider the first 5 characters: ```kotlin class Transformer: BarcodeFindTransformer { override fun transformBarcodeData(data: String?): String? = data?.substring(0, 5) } ``` Then the transformer needs to be set so it can be used by MatrixScan Find: ```kotlin barcodeFind.setTransformer(Transformer()) ``` ## UI Customization The `BarcodeFindView` by default shows a set of UI elements, any of which can be optionally hidden: - Play/Pause button - Finish button - Searched items carousel - Guidance hints - Progress bar (hidden by default) Each of these elements can be shown or hidden as needed. For example: ```kotlin barcodeFindView.shouldShowCarousel = false barcodeFindView.shouldShowProgressBar = true // … ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Find to your application. Implementing MatrixScan Find involves two primary elements: - Barcode Find: The data capture mode that is used for search and find functionality. - A Barcode Find View: The pre-built UI elements used to highlight found items. :::note MatrixScan Find is implemented via [`BarcodeFind`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind). ::: The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Find Mode - Setup the Barcode Find View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### External Dependencies import ExternalDependencies from '../../../partials/get-started/_external-deps-android.mdx'; ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create a Data Capture Context import DataCaptureContextAndroid from '../../../partials/get-started/_create-data-capture-context-android.mdx'; ## Configure the Barcode Find Mode The main entry point for the Barcode Find Mode is the `BarcodeFind` object. You can configure the supported Symbologies through its [`BarcodeFindSettings`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-find-settings.html#class-scandit.datacapture.barcode.find.BarcodeFindSettings), and set up the list of items that you want MatrixScan Find to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```kotlin val settings = BarcodeFindSettings().apply { setSymbologyEnabled(Symbology.EAN13_UPCA, true) } ``` Next, create the list of items that will be actively searched for. We will also attach some optional information to the first item that can be used by the `BarcodeFindView` to display extra information: ```kotlin val items = setOf( BarcodeFindItem( BarcodeFindItemSearchOptions("9783598215438"), BarcodeFindItemContent("Mini Screwdriver Set", "(6-Piece)", null), ), BarcodeFindItem( BarcodeFindItemSearchOptions("9783598215414"), null, // Item information is optional, used for display only ), ) ``` Finally, create a `BarcodeFind` instance with the Data Capture Context and the settings initialized in the previous step: ```kotlin val barcodeFind = BarcodeFind(settings) barcodeFind.setItemList(items) ``` ## Setup the `BarcodeFindView` MatrixScan Find’s built-in AR user interface includes buttons and overlays that guide the user through the searching process. By adding a [`BarcodeFindView`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView), the scanning interface is added automatically to your application. The `BarcodeFindView` appearance can be customized through [`BarcodeFindViewSettings`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-find-view-settings.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindViewSettings) to match your application’s look and feel. For example, you can change the color of the dots that are overlaid on top of the items that are found and enable sound and haptic alerts. ```kotlin val viewSettings = BarcodeFindViewSettings( inListItemColor = Color.GREEN, notInListItemColor = Color.RED, soundEnabled = true, hapticEnabled = true, ) ``` Next, create a `BarcodeFindView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodeFindView` is automatically added to the provided parent view. ```kotlin val barcodeFindView = BarcodeFindView.newInstance(parentView, dataCaptureContext, barcodeFind, viewSettings) ``` Connect the `BarcodeFindView` to the Android lifecycle. The view is dependent on calling `BarcodeFindView.onPause()` and `BarcodeFindView.onResume()` to set up the camera and its overlays properly. ```kotlin override fun onResume() { super.onResume() barcodeFindView.onResume() } override fun onPause() { super.onPause() barcodeFindView.onPause() } ``` ## Register the Listener The `BarcodeFindView` displays a **Finish** button next to its shutter button. Register a [BarcodeFindViewUiListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-find-view.html#interface-scandit.datacapture.barcode.find.ui.IBarcodeFindViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```kotlin barcodeFindView.setListener(object : BarcodeFindViewUiListener { override fun onFinishButtonTapped(foundItems: Set) { requireActivity().onBackPressed() } }) ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `barcodeFindView.startSearching()`. ```kotlin barcodeFindView.startSearching() ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Find # About MatrixScan Find import AboutFind from '../../../partials/intro/_about-matrixscan-find.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Pick is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Pick to best fit your needs. ## BarcodePick Listener You can register a [`BarcodePickListener`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-pick-listener.html) on the mode, which can be used to get updates about the scanned items with each frame. ```kotlin barcodePick.addListener(object : BarcodePickListener { override fun onSessionUpdated(barcodePick: BarcodePick, session: BarcodePickSession) { // This callback will be invoked on a background thread every frame. the session object contains // updated the newly tracked items. } override fun onObservationStarted(barcodePick: BarcodePick) {} override fun onObservationStopped(barcodePick: BarcodePick) {} }) ``` ## BarcodePickScanning Listener You can register a [`BarcodePickScanningListener`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-pick-scanning-listener.html) on the mode, which can be used to listen to every time the pick state changes. ```kotlin barcodePick.addScanningListener(object : BarcodePickScanningListener { override fun onScanningSessionUpdated(barcodePick: BarcodePick, session: BarcodePickScanningSession) { // This callback will be invoked on a background thread every time the picked state of some item changes. // The session object contains the list of picked and scanned items. } override fun onScanningSessionCompleted(barcodePick: BarcodePick, session: BarcodePickScanningSession) { // This callback is invoked when all the registered items needing picking have been picked. } override fun onObservationStarted(barcodePick: BarcodePick) {} override fun onObservationStopped(barcodePick: BarcodePick) {} }) ``` ## BarcodePickView Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodePick` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodePickViewListener`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-pick-view-listener.html) on the mode itself, keeping in mind that these listeners are called from a background thread. ```kotlin barcodePickView.listener = object : BarcodePickViewListener { override fun onStopped(view: BarcodePickView) {} override fun onPaused(view: BarcodePickView) {} override fun onFreezed(view: BarcodePickView) {} override fun onStarted(view: BarcodePickView) {} } ``` ## BarcodePickAction Listener You can also register a [`BarcodePickActionListener`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-pick-action-listener.html) on the mode, which can be used to reject specific pick/unpick actions. ```kotlin barcodePickView.addActionListener(object : BarcodePickActionListener { override fun onPick(itemData: String, callback: BarcodePickActionCallback) { // Perform the needed checks, and invoke callback.onFinish(true/false) to allow/reject // the current pick action } override fun onUnpick(itemData: String, callback: BarcodePickActionCallback) { // Perform the needed checks, and invoke callback.onFinish(true/false) to allow/reject // the current unpick action } }) ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Pick to your application. Implementing MatrixScan Pick involves two primary elements: - Barcode Pick: The data capture mode that is used for scan and pick functionality. - A Barcode Pick View: The pre-built UI elements used to highlight items to be picked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Pick Mode - Setup the Barcode Pick View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### External Dependencies import ExternalDependencies from '../../../partials/get-started/_external-deps-android.mdx'; ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create a Data Capture Context import DataCaptureContextAndroid from '../../../partials/get-started/_create-data-capture-context-android.mdx'; ## Configure the Barcode Pick Mode The main entry point for the Barcode Pick Mode is the `BarcodePick` object. You can configure the supported Symbologies through its [`BarcodePickSettings`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-pick-settings.html), and set up the list of items that you want MatrixScan Pick to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```kotlin val settings = BarcodePickSettings().apply { enableSymbology(Symbology.EAN13_UPCA, true) } ``` Then you have to create the product provider for the Barcode Pick mode. This provider is responsible for providing the items that should be highlighted in the AR view. Note that in this example we are using a hardcoded list of items, but in a real-world scenario, you would fetch this list from your backend. ```kotlin val productDatabase = listOf( ProductDatabaseEntry( /*product identifier*/"product_1", /*quantity to pick*/2, /*items for the product*/setOf { "9783598215438", "9783598215414", "9783598215441", "9783598215412", } ), ProductDatabaseEntry( /*product identifier*/"product_2", /*quantity to pick*/3, /*items for the product*/setOf { "9783598215471", "9783598215481", "9783598215458", "9783598215498", "9783598215421", } ), ) // Map the database products to create the Scandit product provider input. val items = mutableSetOf() productDatabase.forEach { productDatabaseEntry -> items.add( BarcodePickProduct( productDatabaseEntry.productIdentifier, productDatabaseEntry.quantityToPick, ) ) } // Finally, create the product provider itself val productProvider = BarcodePickAsyncMapperProductProvider( items, object : BarcodePickAsyncMapperProductProviderCallback { override fun productIdentifierForItems( itemsData: List, callback: BarcodePickProductProviderCallback, ) { val results = mutableListOf() // Use the scanned itemsData list to retrieve the identifier of the product they belong to. // This should be an async query in real world scenarios if there are a lot of products/items to loop. itemsData.forEach { itemData -> for (entry in productDatabase) { if (entry.items.contains(itemData)) { results.add( BarcodePickProductProviderCallbackItem( /*item data*/itemData, /*product identifier*/entry.productIdentifier ) ) break } } } callback.onData(results) } } ) ``` Create the mode with the previously created settings: ```kotlin val barcodePick = BarcodePick(dataCaptureContext, settings, productProvider) ``` ## Setup the `BarcodePickView` MatrixScan Pick’s built-in AR user interface includes buttons and overlays that guide the user through the scan and pick process. By adding a [`BarcodePickView`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-pick-view.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickView), the scanning interface is added automatically to your application. The `BarcodePickView` appearance can be customized through [`BarcodePickViewSettings`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-pick-view-settings.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickViewSettings) to match your application’s look and feel. The following settings can be customized: * Colors of dots in augmented reality overlay * Enable sound and haptic alerts * Guidelines text * Showing hints * Finish button * Pause button * Zoom button * Loading Dialog ```kotlin val viewSettings = BarcodePickViewSettings() // ... ``` Next, create a `BarcodePickView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodePickView` is automatically added to the provided parent view. ```kotlin val barcodePickView = BarcodePickView.newInstance(parentView, dataCaptureContext, barcodePick, viewSettings) ``` Connect the `BarcodePickView` to the Android lifecycle. The view is dependent on calling `BarcodePickView.onPause()`, `BarcodePickView.onResume()`, and `BarcodePickView.onDestroy()` to set up the camera and its overlays properly. ```kotlin override fun onResume() { super.onResume() barcodePickView.onResume() } override fun onPause() { super.onPause() barcodePickView.onPause() } override fun onDestroy() { super.onDestroy(); barcodePickView.onDestroy() } ``` ## Register the Listener The `BarcodePickView` displays a **Finish** button next to its shutter button. Register a [BarcodePickViewUiListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/barcode-pick-view.html#interface-scandit.datacapture.barcode.pick.ui.IBarcodePickViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```kotlin barcodePickView.uiListener = object : BarcodePickViewUiListener { override fun onFinishButtonTapped(view: BarcodePickView) { requireActivity().onBackPressed() } } ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `barcodePickView.start()`. ```kotlin barcodePickView.start() ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Pick # About MatrixScan Pick MatrixScan Pick is a pre-built UI that uses augmented reality overlays to highlight specific items that need to be picked. Whereas MatrixScan AR is fully customizable, MatrixScan Pick is a pre-built solution that allows you to add a scan and pick experience with augmented reality to an existing native app, with just a few lines of code. MatrixScan Pick is implemented through functionality provided by [`BarcodePick`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-pick.html). ## UI Overview * MatrixScan Pick is inspired by the familiar paradigm of a camera, including a shutter button that the user operates in order start and pause the scanning view. The Finish button is used at any time to exit the workflow. * It highlights items with obvious and colorful visual dots on screen. * When paused, MatrixScan Pick freezes the display at the last view, even if the device is moved. The Play button transitions back to the live view. * Textual guidance is displayed from the beginning of the session and as the workflow progresses, informing of the user of changes in item status (i.e. Detected, Ignored, To-Pick, or Picked). * Status icons can be defined to provide further information to users for a given barcode. In the live view, the icons are displayed but not tapable. In the frozen view, the status icons can be tapped and expanded to provide additional textual information. * This guide takes you through the process to install the full UI. However, you can then customize it by choosing to remove any elements on the screen except for the AR overlays. This allows you to create custom UIs suitable for your own workflows. ## Supported Symbologies MatrixScan Find supports all [symbologies](../barcode-symbologies.mdx) **except** DotCode, MaxiCode and postal codes (KIX, RM4SCC). If you are not familiar with the symbologies that are relevant for your use case, you can use capture presets that are tailored for different verticals (e.g. retail, logistics, etc.). --- ## Get Started # Get Started The parser parses data strings, e.g. as found in barcodes, into a set of key-value mappings. In this guide, you will know briefly how to use a parser and what types of parser are currently supported by Scandit. These data formats are supported: [Health Industry Bar Code (HIBC)](https://docs.scandit.com/data-capture-sdk/android/parser/hibc.html), [GS1 Application Identifier system](https://docs.scandit.com/data-capture-sdk/android/parser/gs1ai.html) and [Swiss QR Codes](https://docs.scandit.com/data-capture-sdk/android/parser/swissqr.html), [VIN Vehicle Identification Number](https://docs.scandit.com/data-capture-sdk/android/parser/vin.html), [IATA Bar Coded Boarding Pass (BCBP)](https://docs.scandit.com/data-capture-sdk/android/parser/iata-bcbp.html), [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/android/parser/epc.html). More data formats will be added in future releases. Please contact us if the data format you are using is not yet supported, or you want to use the parser on a currently unsupported platform. ## Format-Specific Documentation - [Supported Data Formats](https://docs.scandit.com/data-capture-sdk/android/parser/formats.html) - [HIBC](https://docs.scandit.com/data-capture-sdk/android/parser/hibc.html) - [GS1 AI](https://docs.scandit.com/data-capture-sdk/android/parser/gs1ai.html) - [GS1 Digital Link](https://docs.scandit.com/data-capture-sdk/android/parser/gs1-digital-link.html) - [Swiss QR](https://docs.scandit.com/data-capture-sdk/android/parser/swissqr.html) - [VIN](https://docs.scandit.com/data-capture-sdk/android/parser/vin.html) - [IATA BCBP](https://docs.scandit.com/data-capture-sdk/android/parser/iata-bcbp.html) - [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/android/parser/epc.html) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: First of all, include the ScanditParser library and its dependencies to your project, if any. ### Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### New Features #### Barcode * MatrixScan Sequence: Introduced several new configurations to adapt the sequencing flow: - Configure the duration of the idle timeout via BarcodeSequenceSettings.IdleTimeout. - Set the accepted device orientation via `BarcodeSequenceSettings.shelfSequencingOrientation`. Defaults to `LANDSCAPE_ONLY`, with `PORTRAIT_ONLY` and `ANY` also available. The rotate-device prompt's default text now reflects the configured orientation. - Toggle the per-row tray indicator label (e.g. "Row 1") through `shouldShowTrayIndicatorText` on the `BarcodeSequenceView`. * Added group scanning to MatrixScan Count, enabled via `BarcodeCountSettings`. Group scanning lets users count items in distinct groups, for example one pallet or delivery at a time, within a single session. Three controls manage the flow: Next group saves the current group's scans and clears its AR highlights so the next group starts on a clean screen; Redo clears the scans for the current group only, leaving already-completed groups untouched; Finish ends the session. * Added `BarcodeCountSettings.ExpectedNumberOfBarcodesPerCluster` to MatrixScan Count to declare how many barcodes each cluster should contain (for example, 2 for labels carrying two barcodes). Any cluster that deviates from the expected count is flagged and highlighted with a default yellow brush (overridable). * Added support for `ScanditIcon` in MatrixScan Count highlights. * Added the SelectionMode API to replace the SparkScan target-mode APIs and `ScanIntention.smartSelection`: Set `selectionMode` (off/on/auto) in the `BarcodeCaptureSettings` and `SparkScanSettings` to control whether an aimed-at barcode is scanned automatically or requires explicit selection. * Added `logoStyle` and `logoAnchor` customization properties to `BarcodeArView`, `BarcodeCountView`, `BarcodeFindView`, `BarcodePickView`, and `BarcodeSequenceView`. * Updated `BarcodeCountView` clusters to show normal indicators when no status is provided in status mode. #### Id * Added Irish Garda Age Card as `RegionSpecificSubtype.IrelandAgeCard`. * Added a new `PassportType` property to `MrzResult`. * Added double-sided support for the Oman residence card. * Added single-sided support for extraction of issue date and birth date from the 2025 NYC Municipal ID. #### Smart Label Capture * Extended VIN label capture to also scan Code 128 barcodes (in addition to QR, Code 39, and Data Matrix) via `createVinLabelDefinition()`. * Extended LabelCapture to accept label definitions where both "barcode" and "text" field types use the "semantics" feature simultaneously; previously this was restricted to only one field type at a time. ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Smart Label Capture * Improved Receipt Scanning efficiency by optimizing receipt image processing before extraction. * Improved lifecycle handling of `LabelCaptureValidationFlowOverlay` in unexpected scenarios. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. * Updated `SymbologyDescription.forIdentifier` to return `null` for unrecognized identifiers (e.g. `"EAN-8"` instead of `"ean8"`); previously such input was silently mapped to `Codabar`. ### Bug Fixes #### Barcode * Fixed an issue where the "Remove" button in the sequence popover would sometimes not work. * Fixed a memory leak in item-based scanning. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Id * Fixed an issue where cropped document images were rotated when Frame Image was also enabled. * Corrected the orientation of cropped Visa document images that were being rotated incorrectly when scanned using a single-frame image source. * Fixed parser handling of non-standard Surrey BC AAMVA barcodes that were incorrectly returning "Invalid Format". #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed an Android camera issue where zoom values outside the device-supported range were sent to Camera2 on Android R+ (API 30+) without clamping, which could cause the capture request to fail and stall the preview. * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a crash when the `DataCaptureContext` singleton was initialized more than once. ### Deprecations #### Barcode * The SparkScan target-mode APIs and `ScanIntention.smartSelection` are deprecated in favour of selectionMode. * Deprecated the `BarcodeCountView.newInstance()` overloads that accept a `DataCaptureView` on Android (will be removed in 9.0); pass a `DataCaptureContext` instead. * Added `ScanditIcon` support for `BarcodeCount` status mode highlights, and deprecated the `SDCBarcodeCountStatus`-based highlight API. ## 8.4.1 **Released**: June 23, 2026 ### Bug Fixes #### Barcode * Fixed a memory leak in SparkScan when using the item-based API. #### Id * Fixed an issue where cropped document images were rotated when they are recovered using the getFrame API. ## 8.4.0 **Released**: May 18, 2026 ### New Features #### Barcode * Added an Error entry to `BarcodeSequenceState`, triggered when the sequencing process encounters an error. * Added `dotRadius` property to `BarcodeBatchBasicOverlay` to allow customizing the size of dots when using the Dot overlay style. * Added `shouldShowShutterButton` flag in `BarcodeSequenceView` to hide the main shutter button and blinking indicator; added `BarcodeSequenceView::startSequencing()` and `BarcodeSequenceView::pauseSequencing()` (iOS) / `BarcodeSequenceView::stopSequencing()` (Android) to programmatically replicate the shutter button behavior; exposed `BarcodeSequenceState` enum and `BarcodeSequenceViewUIListener::onStateChanged` to be notified when a state change occurs; exposed `BarcodeSequenceView::state` to retrieve the current state; exposed `BarcodeSequenceView::sequencedShelfModule` to retrieve the scanned shelf module. #### Id * Added support for reading the vehicle table on the back of New Zealand driving licences, with the latest expiry date returned; supported vehicle classes are 1–6, including L=learner and R=restricted variants. * Added support for new versions of USA, California – Driver's License; USA, North Carolina – Driver's License; USA, Texas – Driver's License; and USA, Oklahoma – Driver's License. #### Core * Redesigned `ZoomSwitchControl` to support multiple configurable zoom levels; the control now displays as a compact button that expands to show all available zoom levels, automatically filtered to those supported by the device hardware. * Added a new `PinchToZoom` gesture. * Introduced a new `ZoomListener` on the Camera object. ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. #### Core * Updated mbedtls from version 3.6.5 to 3.6.6. ### Bug Fixes #### Barcode * Fixed an issue in `BarcodeCount` where the floating shutter button was not visible after setting `shouldShowFloatingShutterButton` to `true`. * Fixed an issue preventing `BarcodeFind` from finding binary barcodes. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed an issue where the Smart Scan Selection aimer would become too small when scan-area margins restricted the visible scan area; the aimer is now sized relative to the view, keeping a consistent on-screen size regardless of margins. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. #### Id * Fixed an issue where the US Permanent Residence Card was not processed through the VizMrz flow. * Fixed an issue where AAMVA verification was being performed even when no AAMVA document types were enabled in the accepted documents. #### Smart Label Capture * Fixed a memory leak in LabelCapture * Fixed an issue where the validation flow viewfinder was not displayed. * Fixed a race condition in the validation flow. * Fixed a bug that caused error messages in `DataCaptureView` to be rendered partially out-of-view. * Fixed a bug that would cause the buttons in the `LabelCaptureValidationFlowOverlay` to overlap when applying a long custom text. * Fixed a rare race condition in Label Capture. * Added `.asDate()` support to `ExpiryDate` and `PackingDate` label fields when the text is provided as manual input or as an Adaptive-Recognition-Engine response. * Fixed a bug where the receipt scanning overlay and validation flow overlay could not be used on the same LabelCapture mode instance. #### Core * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. * Fixed a rare crash when opening the camera. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed custom sound not working in Barcode Find on Android. * Fixed a rare crash when starting camera capture while under memory pressure. ## 8.3.1 **Released**: April 14, 2026 ### New Features #### Barcode * Added `shouldShowShutterButton` flag in `BarcodeSequenceView` to hide the main shutter button and blinking indicator; added `BarcodeSequenceView::startSequencing()` and `BarcodeSequenceView::pauseSequencing()` to programmatically replicate the shutter button behavior; exposed `BarcodeSequenceState` enum as well as `BarcodeSequenceViewUIListener::onStateChanged` to be notified when a state change occurs; exposed `BarcodeSequenceView::state` to retrieve the current state; exposed `BarcodeSequenceView::sequencedShelfModule` to retrieve the scanned shelf module. ### Bug Fixes #### Smart Label Capture * Fixed the validation flow to accept dates in more formats when manually entered * Fixed a race condition in the validation flow ## 8.3.0 **Released**: March 26, 2026 ### New Features #### Barcode * Added support for composite codes in SparkScan * Added PDF417 barcode generation support with configurable options like error correction level, compaction mode, and dimensions through the new `Pdf417BarcodeGeneratorBuilder`. #### Id * Added support for OCR scanning of the 2026 version of Victoria mobile driver licenses * Added IdCaptureSettings.anonymizeDefaultFields setting that controls whether the SDK applies default anonymization rules for specific document types and regions * US, EU/ Schengen + UK passports no longer fallback to MRZ only. Now, US, EU/ Schengen + UK passports must capture VIZ instead of returning MRZ values after the configurable timeout has elapsed. This applies to FullDocumentScanner or SingleSideScanner when both VIZ and MRZ zones are enabled. #### Smart Label Capture * Fixed a rare race condition #### Core * Deprecated outdated DataCaptureViewListener ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Improved speed of MatrixScan Count scanning phase for mid- and high-end devices #### Core * Improved nullability handling across the library to ensure null-safety contracts are enforced consistently, reducing the risk of unexpected crashes ### Behavioral Changes #### Core * Updated Android documentation to render in Kotlin ### Bug Fixes #### Barcode * Fixed an issue in BarcodeCount where the floating shutter button was not visible after setting shouldShowFloatingShutterButton to true. * Fixed a bug that was causing BarcodeFind to render barcodes filtered out by the Transformer as if they were valid targets. #### Id * Fixed support for UAE Esaad card * Sanitized name fields on ACT driver license to split FullName and populate first and last name properties * Added support for scanning MRZ from the back of Argentinian DN when using `FullDocumentScanner` #### Smart Label Capture * Fixed an issue in the `LabelCaptureValidationFlowOverlay` when using it with Jetpack Compose that caused focus loss when opening the keyboard * Added `LabelCaptureValidationFlowOverlay.ShouldHandleKeyboardInsetsInternally` for cases when customers don't want to follow official Android edge-to-edge and inset guidelines #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. ## 8.2.1 **Released**: March 5, 2026 ### Bug Fixes #### Id * Sanitized name fields on ACT DL. Splits FullName to populate first and last name properties #### Smart Label Capture * Fixed LabelCaptureValidationFlowOverlay possible issue with Jetpack Compose that caused focus loss when opening the keyboard * Added LabelCaptureValidationFlowOverlay::ShouldHandleKeyboardInsetsInternally in case customers don't want to follow official Android guidelines for edge-to-edge and insets * Fixed a rare race condition ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Barcode * Added new getFeedbackForScannedItem method to SparkScanFeedbackDelegate #### Id * Added a Jetpack compose settings sample for ID * Enabled scanning of MRZ on the backside of several EU residence permits * Added extraction of a cropped document image from Passports and VISAs that do not support VIZ extraction * Added extraction of the date of birth from Romanian IDs #### Smart Label Capture * The Validation Flow, our ready‑to‑use workflow in Smart Label Capture for capturing and validating label data with minimal code, now features a completely redesigned user interface. The update improves ergonomics through a simplified API and highly requested customization options, making Smart Label Capture more intuitive and significantly reducing integration and customization effort across a wider range of use cases * Added LabelCapture Validation Flow Manual input delegate, that allows the developer to receive a callback when the users trigger the manual input. #### Core * Added ability to emit sound or vibration separately in Feedback ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes * Barcode Generator: Improved DataMatrix encoding efficiency, which depending on input data may result in smaller generated codes ### Behavioral Changes #### Barcode * Highlights in BarcodeAr can now be updated when BarcodeArView is in a paused mode * Updated MatrixScan tote mapping sample to Kotlin ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. * Fixed an issue where the successful hint in BarcodeFind is not displayed #### Id * Fixed an issue affecting MRZ scanning performance when using the user facing camera in portrait mode on Android * Fixed a memory issue leading to a persistent black screen during ID Capture startup * Treated Puerto Rico driver licenses as AAMVA to enforce barcode capture with FullScanner * Fixed a bug that would cause Canada Northwest Territories driver license scans to be incomplete #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed an issue where some LabelCapture fields were being returned incorrectly on TS frameworks ### Deprecations #### Smart Label Capture * Deprecated some LabelCaptureValidationFlowSetting APIs: requiredFieldErrorText, missingFieldsHintText, manualInputButtonText, as those don't make sense anymore with the redesign of Validation Flow in 8.2 ## 8.1.5 **Released**: June 10, 2026 ### New Features #### Barcode * Added `shouldShowTrayIndicatorText` to `BarcodeSequenceView` to toggle the per-row tray indicator label (e.g. "Row 1"). * Added an option to configure the duration of BarcodeSequence's idle timeout. ### Bug Fixes #### Barcode * Fixed an issue where the "Remove" button in the sequence popover would sometimes not work. * Fixed a memory leak in item-based scanning. #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a rare native crash (SIGABRT in BitTube::recvObjects) that could occur on Android during camera preview rendering. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. #### Core * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed crashes caused by RuntimeExceptions thrown by OEM camera code that are not part of the standard Android Camera API contract; these exceptions are now caught and logged instead of crashing. ## 8.1.3 **Released**: March 25, 2026 ### New Features #### Barcode * Added `shouldShowShutterButton` flag in `BarcodeSequenceView` to hide the main shutter button and blinking indicator; added `BarcodeSequenceView::startSequencing()` and `BarcodeSequenceView::pauseSequencing()` to programmatically replicate the shutter button behavior; exposed `BarcodeSequenceState` enum as well as `BarcodeSequenceViewUIListener::onStateChanged` to be notified when a state change occurs; exposed `BarcodeSequenceView::state` to retrieve the current state; exposed `BarcodeSequenceView::sequencedShelfModule` to retrieve the scanned shelf module. ### Bug Fixes #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. ## 8.1.2 **Released**: March 9, 2026 ### Bug Fixes #### Smart Label Capture * Fixed a rare race condition ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Id * Fixed a memory issue leading to a persistent black screen during ID Capture startup #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed a bug that could in rare cases produce a black screen when starting the camera ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Smart Scan Selection is now available in Barcode Capture. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. * Added, in `BarcodeAr`, a `BarcodeArFilter` interface to selectively control which barcodes are displayed in the AR overlay based on custom filtering logic. You can set a filter via `BarcodeAr.SetBarcodeFilter`. * Added `ScanditIconType.Slash` which can be used in `BarcodeArStatusIconAnnotationAnchor`. * BarcodeCountView now supports cameras with different aspect ratios. #### Id * Added NationalityISO property that maps results from Nationality field to country ISO code * Added RejectionDiagnosticJSON property to CapturedId to report debug info during Timeout rejections * Added rejectionTimeoutSeconds to IdCaptureSettings allowing customers to use timeout other than default (6s). Minimum timeout is 1s. * Added support for new California DL, new South Carolina DL, Arizona Medical Marijuana Card, Kuwait Civil card, and new Texas DL * Our SDK can now scan the following documents both in single-side and double-side mode: - All Mexican DLs - Mexican Voter Cards #### Core * Added support for QuadHD resolution to provide improved performance and extended range for MatrixScan modes on slower devices * Added Electronic Product Code (EPC) parser ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the [“strict" symbology extension](../symbology-properties#symbology-extension-descriptions) #### Smart Label Capture * Incremental improvements in accuracy across all use-cases for the OCR model powering Smart Label Capture. ### Behavioral Changes #### Barcode * Enabling the [“ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 (“Missing Resource”) #### Smart Label Capture * Validation Flow: Manually input values for barcodes will go through a stricter validation. Some values may no longer be accepted if they do not match the symbology specs for the symbology’s definition ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Fixed a bug in the default color of BarcodeCapture highlights * Fixed an issue where popover annotations with HIGHLIGHT_TAP_AND_BARCODE_SCAN trigger could not be opened again * Fixed an issue in BarcodeSequence where camera would not be ON in portrait * Fixed an issue where SparkScan mini preview would sometimes stay in regular when entering target mode * Fixed the app becoming unresponsive after being in the background for extended periods * Fixed an issue where the successful notification in BarcodeFind was not displayed #### Id * Fixed a bug concerning return complete instead of cropped images on the back of EU driving licenses #### Core * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only ## 8.0.1 **Released**: January 14, 2026 ### New Features #### Barcode * Added, in `BarcodeAr`, a `BarcodeArFilter` interface to selectively control which barcodes are displayed in the AR overlay based on custom filtering logic. You can set a filter via `BarcodeAr.SetBarcodeFilter`. ### Bug Fixes #### Barcode * Fixed an issue where the successful hint in BarcodeFind was not displayed * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. #### Core * This release drops support for Android 6. The new `minSdk` version is now 24 (previously 23). #### Barcode * Updated the Gradle version for all sample applications to 8.14.3. * A new version of the SparkScan sample application implemented in Jetpack Compose is now available. * SparkScan is not limited to only barcodes anymore, but can also scan items - in other words any combinations of barcodes and text present on a target to be scanned. The feature is available in beta at the moment, please contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out. #### Smart Label Capture * We’re introducing an enhancement that makes Smart Label Capture more robust and scalable by complementing its on-device model with a larger, more capable model. When the on-device model can’t capture certain labels, the SDK automatically escalates to this enhancement to handle complex or unforeseen cases with high accuracy and reliability. This capability is currently available in `beta`. If you’re interested in trying it, please contact [Scandit Support](mailto:support@scandit.com). For configuration details, see `labelDefinition.adaptiveRecognitionEngine`. #### ID * Added `ElementsToRetain` to `MobileDocumentScanner`: The set of data elements that the application intends to retain from scanned mobile documents. This information is used to set the `IntentToRetain` flag in ISO 18013-5 mdoc requests, which is required for legal compliance with data protection standards. An empty set indicates no elements will be retained, and `IntentToRetain` will be set to `false` for all fields. * ID Capture now supports full-frame anonymization. * The result of `decodeMobileDriverLicenseViz`, which is currently returned as part of the `VizResult` within `CapturedId`, will now be provided through a new field named `mobileDocumentOcr`. * Added `CapturedId::isCitizenPassport`, which indicates whether the passport was issued to a citizen of the issuing country. Returns `false` for travel documents such as refugee, stateless, or alien passports, and for any passports issued by organizations rather than states. * The following Chinese travel permits now extract VIZ + MIZ data during double-sided scanning flows: * CT - Taiwan Residents Mainland Travel Permit * W - Mainland Residents Exit-Entry Permit to and from Hong Kong and Macao * CD - Mainland Residents Entry-Exit Permit to and from Taiwan ### Behavioral Changes #### Barcode * Symbology `RM4SCC` has been renamed to `ROYAL_MAIL_4STATE`. * Changed the default highlight brush in SparkScan and Barcode Capture. #### Label * The `LabelFieldDefinition` API has been updated with the following changes: * Renamed property: `pattern` → `valueRegex`, `patterns` → `valueRegexes` * Renamed property: `dataTypePattern` → `anchorRegex`, `dataTypePatterns` → `anchorRegexes` * Our Receipt Scanning Capture feature, available in beta (contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out), has been updated to improve performance and the API: * `ReceiptScanningResult`: * Removed properties: `storeNumber`, `storeStreet`, `storeZip`, `storeState`, `storePhone`, `paymentMethod`, and `paymentCurrency`. * Added property: `storeAddress` - Full address of the store (Street Number, Street, City, State, NPA). * Renamed property: `paymentSubtotal` → `paymentPreTaxTotal` - Total balance before taxes are applied. * `ReceiptScanningLineItem`: * Removed property: `category`. * Renamed properties: `price` → `unitPrice` (Price for a single unit of the item), `total` → `totalPrice` (Total price for a specific product, quantity × unitPrice). #### ID * The configuration for the following documents has been changed as detailed below: * Australian mobile driver licenses (mDL) are now treated as normal documents, with no separate mode. * US Green Cards are now treated as residence permits. * Removed the deprecated API `DateResult::toDate`. Use `DateResult::toLocalDate` or `DateResult::toUtcDate` instead. * `fullName` now an optional field on all `IdCapture` result types and `capturedMrz` now an optional field on `MrzResult`. ### Bug Fixes #### Core * Fixed a class duplication build error caused by embedding `snapchat-djinni` sources. * Fixed a flickering camera preview issue on some devices. #### ID * Fixed a bug that could get the scanner stuck when scanning a US passport card. ### Deprecations #### Core * `VideoResolution::Auto` is now deprecated. Please use the capture mode's `recommendedCameraSettings` for the best results. #### Barcode * The following previously deprecated APIs have been removed: * BarcodeCaptureOverlay Related APIs * BarcodeCaptureOverlayStyle enum * BarcodeCaptureOverlay.NewInstance(BarcodeCapture, DataCaptureView?, BarcodeCaptureOverlayStyle)factory method * BarcodeCaptureOverlay.DefaultBrushForStyle(BarcodeCaptureOverlayStyle) method * BarcodeCaptureOverlay.Style property * SparkScanViewHandMode enum * SparkScanView.torchButtonVisible property * SparkScanView.handModeButtonVisible property * SparkScanView.stopCapturingText property * SparkScanView.startCapturingText property * SparkScanView.resumeCapturingText property * SparkScanView.scanningCapturingText property * SparkScanView.captureButtonBackgroundColor property * SparkScanView.captureButtonActiveBackgroundColor property * SparkScanView.captureButtonTintColor property * SparkScanViewSettings.defaultHandMode property * SparkScan View Defaults APIs * SparkScanViewDefaults.DefaultHandModeButtonVisible property * SparkScanViewDefaults.DefaultTorchButtonVisible property * SparkScanViewDefaults.DefaultStopCapturingText property * SparkScanViewDefaults.DefaultStartCapturingText property * SparkScanViewDefaults.DefaultResumeCapturingText property * SparkScanViewDefaults.DefaultScanningCapturingText property * SparkScanViewDefaults.DefaultCaptureButtonActiveBackgroundColor property * SparkScanViewDefaults.DefaultCaptureButtonBackgroundColor property * SparkScanViewDefaults.DefaultCaptureButtonTintColorProperty ## 7.6.7 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/android/release-notes) --- ## Advanced Configurations # Advanced Configurations SparkScan is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are some cases where you might want to customize the behavior of SparkScan. This guide will show you how to add additional capabilities and further customize SparkScan to best fit your needs. ## Advanced Capabilities ### Hardware Button Control Allowing the end user to control the scanner with hardware buttons can be useful if your users typically wear gloves. It can also improve ergonomics in some workflows. SparkScan offers a built-in API to let you do this via [SparkScanViewSettings.hardwareTriggerEnabled](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled). ### Trigger Error State You may want to introduce logic in your app to show an error message when scanning specific barcodes (e.g. barcodes already added to the list, barcodes from the wrong lot etc.). SparkScan offers a built-in error state you can easily set to trigger an error feedback prompt to the user. You can customize: - The text message. - The timeout of the error message: the scanner will be paused for the specified amount of time, but the user can quickly restart the scanning process by tapping the trigger button. :::tip A high timeout (>10s) typically requires the users to interact with the UI to start scanning again. This is a good choice when you want to interrupt the scanning workflow (e.g. because a wrong barcode is scanned and some actions need to be performed). A small timeout (\ This error state for a code that should not have been scanned. This error state for a code that has been scanned more than once. ### Reject Barcodes To prevent scanning unwanted barcodes (like those already listed or from incorrect lots), use SparkScan's built-in error state. Setting the [`Error.resumeCapturingDelay`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/spark-scan-barcode-feedback.html#property-scandit.datacapture.barcode.spark.feedback.Error.ResumeCapturingDelay) parameter to `0` allows the user to continue scanning immediately without pausing on rejected codes. ## UI Customization :::tip Please refer to [SparkScanView](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) for the full list of parameters. ::: import Customization from '../../../partials/advanced/_sparkscan-customization.mdx'; ## Workflow Options This section explains all the available options to configure SparkScan to best fit your case, in case you found something that didn't work well in the default configuration (that remains our recommended option). Developers can set a combination of scanning mode, scanning behavior and camera preview behavior - defining the initial state of the scanner. This can be done by setting the default scanning mode ([`SparkScanViewSettings.defaultScanningMode`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.DefaultScanningMode)). This combination allows for flexible configurations to suit different scanning needs. ### Scanning Mode The scanning mode determines the programmatic presence of an aimer in the preview to help with precision scanning. | Mode | Description | | ----------- | --------------------------------------------------- | | **Default** | Generally recommended. This mode will display a small camera preview to aid with aiming. The preview size and zoom level can be adjusted as needed. User can aim easily at the intended barcode. | | **Target** | This mode will always add an aimer to the camera preview to precisely select the barcode to scan. This is recommended only when selecting among many close barcodes is the common task. | :::tip Even in the *Default* mode, SparkScan will automatically show an aimer when multiple barcodes are present in the view and no clear intention from the user to scan a single one is recorded ([`SparkScanSettings.ScanIntention`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/spark-scan-settings.html#property-scandit.datacapture.barcode.spark.SparkScanSettings.ScanIntention)). Enabling the *Target* mode will simply force this "precision selection" state to be on at all time. ::: ### Scanning Behavior The scanning behavior determines how barcodes are scanned - one at a time or continuously. | Behavior | Description | | ------------------- | ---------------------------------------------------------- | | **Single scan** | Scan one barcode at a time. The user needs to trigger the scanner every time to scan a barcode. This allows for a more controlled scanning and lower battery consumption. | | **Continuous scan** | Scan barcodes consecutively. The user needs to trigger the scanner once and barcodes will be scanned without any further interaction before each scan. This allows for a smoother experience when multiple barcodes need to be scanned consecutively. | :::tip Users can enable continuous scanning by holding down the trigger button. This gesture can be disabled ([`SparkScanViewSettings.holdToScanEnabled`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HoldToScanEnabled)). ::: ### Preview Behavior The preview behavior determines how the camera preview behaves when the scanner is not actively scanning. | Behavior | Description | | -------------- | -------------------------- | | **Default** | Preview fades away when the scanner is off. This lets the user check important information displayed by the app and reduces battery consumption. | | **Persistent** | Preview remains visible, but darkened, even when the scanner is off. This is useful for scenarios where you want to select a barcode (among many) or need to look through the preview at all times (to ensure the right scan) - especially if used in conjunction with the target mode. | --- ## Get Started # Get Started This page describes the step-by-step instructions that helps you to add SparkScan to your application: - Create a new Data Capture Context instance - Configure the Spark Scan Mode - Create the SparkScanView with the desired settings and bind it to the application’s lifecycle - Register the listener to be informed when new barcodes are scanned and update your data whenever this event occurs :::note If you’re looking to integrate SparkScan into a Compose view hierarchy, there are additional steps you need to follow: Create an `AndroidView` to wrap the `SparkScanView` instance, initialized as described in the rest of this section. Monitor the view lifecycle so you can call the view lifecycle methods in `SparkScanView` when necessary. This can be done using a combination of `DisposableEffect` and the `onRelease` callback of `AndroidView`. ::: ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/android/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### External Dependencies import ExternalDependencies from '../../../partials/get-started/_external-deps-android.mdx'; ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create a New Data Capture Context Instance The first step to add capture capabilities to your application is to create a new Data Capture Context. The context expects a valid Scandit Data Capture SDK license key during construction. ```kotlin val dataCaptureContext = DataCaptureContext.forLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --") ``` ## Configure the SparkScan Mode The SparkScan Mode is configured through SparkScanSettings and allows you to register one or more listeners that are informed whenever a new barcode is scanned. For this tutorial, we set up SparkScan for scanning EAN13 codes. You can change this to the correct symbologies for your use case (for instance, Code 128, Code 39…). ```kotlin val settings = SparkScanSettings().apply { val symbologies = setOf(Symbology.EAN13_UPCA) enableSymbologies(symbologies) } ``` Next, create a SparkScan instance with the settings initialized in the previous step: ```kotlin val sparkScan = SparkScan(settings) ``` ## Create the SparkScan View The SparkScan built-in user interface includes the camera preview and scanning UI elements. These guide the user through the scanning process. The [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/spark-scan-view.html) appearance can be customized through [`SparkScanViewSettings`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/ui/spark-scan-view-settings.html). ```kotlin val viewSettings = SparkScanViewSettings() // setup the desired appearance settings by updating the fields in the object above ``` By adding a `SparkScanView`, the scanning interface (camera preview and scanning UI elements) gets added automatically to your application. Construct a new SparkScan view. The SparkScan view is automatically added to the provided parentView: ```kotlin val sparkScanView = SparkScanView.newInstance(parentView, dataCaptureContext, sparkScan, viewSettings) ``` See the [SparkScan Workflow Options](./advanced.md#workflow-options) section for more information. Additionally, make sure to call `sparkScanView.onPause()` and `sparkScanView.onResume()` in your Fragment/Activity `onPause` and `onResume` callbacks. You have to call these for the correct functioning of the `SparkScanView`. ```kotlin override fun onPause() { sparkScanView.onPause() super.onPause() } override fun onResume() { sparkScanView.onResume() super.onResume() } ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [SparkScanListener](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface and register the listener to the SparkScan mode. ```kotlin // Register self as a listener to monitor the spark scan session. sparkScan.addListener(this) ``` [SparkScanListener.onBarcodeScanned()](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/spark-scan-listener.html#method-scandit.datacapture.barcode.spark.ISparkScanListener.OnBarcodeScanned) is called when a new barcode has been scanned. This result can be retrieved from the first object in the provided barcodes list: [SparkScanSession.newlyRecognizedBarcode](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/spark-scan-session.html#property-scandit.datacapture.barcode.spark.SparkScanSession.NewlyRecognizedBarcode). :::note Note that this list only contains one barcode entry. ::: ```kotlin override fun onBarcodeScanned( sparkScan: SparkScan, session: SparkScanSession, data: FrameData?, ){ // Gather the recognized barcode val barcode = session.newlyRecognizedBarcode // This method is invoked from a recognition internal thread. // Run the specified action in the UI thread to update the internal barcode list. runOnUiThread { // Update the internal list and the UI with the barcode retrieved above this.latestBarcode = barcode } } ``` ## Scan Some Barcodes Now that you’re up and running, go find some barcodes to scan. Don’t feel like getting up from your desk? Here’s a [handy pdf of barcodes](https://github.com/Scandit/.github/blob/main/images/PrintTheseBarcodes.pdf) you can print out. --- ## About SparkScan # About SparkScan SparkScan is our pre-built smartphone scanning interface designed for high-performance barcode scanning. It fits on top of any smartphone application, providing an intuitive user interface for simple, fast and ergonomic scanning in scan-intensive workflows, such as inventory management in retail, or goods receiving in logistics. SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs. ## UI Overview The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience. Two main elements compose the UI: ![SparkScan UI](/img/sparkscan/features_web.png) - **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc). - **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space. There are additional UI elements available for displaying additional scanning modes, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section. ## Workflow Description When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use. To start scanning, the user can simply tap on it. When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app). In the default configuration: - Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away. - Tapping on the trigger button or the mini preview will restart immediately the scanner. Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state. If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released. List building use case using SparkScan. The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field. But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more. ## Supported Symbologies SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx). ## AI-Powered Features SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide. --- ## Installation # Installation This page describes how to integrate the Scandit Data Capture SDK into your Capacitor project. ## Prerequisites - Capacitor Version 5-7 [and other related tools and dependencies](https://capacitorjs.com/docs/getting-started). - A project with: - minimum iOS deployment target of 15.0 or higher - an Android project with target SDK version 24 (Android 7, Nougat) or higher - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). :::tip Android devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ### Internal Dependencies import InternalDependencies from '../../partials/get-started/_internal-deps-no-label-capture.mdx'; ## Get a License Key 1. [Sign up](https://ssl.scandit.com/dashboard/sign-up?p=test) or [Sign in](https://ssl.scandit.com/dashboard/sign-in) to your Scandit account 2. Create a project 3. Create a license key If you have a paid subscription, please reach out to [Scandit Support](mailto:support@scandit.com) if you need a new license key. ## Add the SDK Currently we support adding the Scandit Data Capture SDK Capacitor plugins to your project in two ways. The simplest way is to use the npm registry, alternatively you can manually download the plugins and add them to your project. :::note You should always make sure to add the scandit-capacitor-datacapture-core plugin, as all other plugins depend on it. ::: ### Create a new project If you do not have a Capacitor project yet that you’ll use, you should create a new one. ```sh npx cap init npx cap add ios npx cap add android ``` ### Add the SDK from npm To add Scandit plugins via npm, run the corresponding commands from your project’s root folder. In the following snippet we’re adding multiple plugins for different functionalities, but you can add only the ones you need as described in the [Internal Dependencies](#internal-dependencies) section. ```sh yarn add scandit-capacitor-datacapture-core yarn add scandit-capacitor-datacapture-barcode yarn add scandit-capacitor-datacapture-parser yarn add scandit-capacitor-datacapture-id ``` :::note You can also specify a version `@`. ::: ### Add the SDK manually After you download the [archive](https://ssl.scandit.com/dashboard/downloads) containing all the plugins, unzip the archive. It includes the available Capacitor plugins, including the `scandit-capacitor-datacapture-core` plugin that all other plugins depend on. First add the `scandit-capacitor-datacapture-core` plugin: ```sh yarn add ``` Once this is done, you can continue with adding the plugin(s) for your desired functionality: ```sh yarn add yarn add yarn add ``` ### Update the project After adding the plugins, you'll want to make sure they're added to your project properly. **For iOS, first set up Scandit's private CocoaPods repository:** **Important:** This project uses Scandit's private CocoaPods repository. First-time setup: ```sh # Add Scandit's private CocoaPods repository (one-time setup) pod repo add scandit-private-specs https://github.com/Scandit/scandit-cocoapods-specs.git ``` Then sync your project: ```sh # iOS npx cap sync # Android npx cap update android npx cap sync ``` :::note The public CocoaPods trunk repository is becoming read-only. Scandit has migrated to a private CocoaPods specs repository to ensure continued support and updates for iOS framework integrations. The repository is publicly accessible at https://github.com/Scandit/scandit-cocoapods-specs. **Troubleshooting**: If you encounter issues: - Verify the repo is added: `pod repo list | grep scandit-private-specs` - Update the repo: `pod repo update scandit-private-specs` ::: ## Additional Information ### Android Configuration On Android, the Scandit SDK uses content providers to initialize the scanning capabilities properly. If your own content providers depend on the Scandit SDK, choose an **initOrder** lower than 10 to make sure the SDK is ready first. If not specified, **initOrder** is zero by default and you have nothing to worry about. Check [the official `` documentation](https://developer.android.com/guide/topics/manifest/provider-element). ### Camera Permissions When using the Scandit Data Capture SDK you will want to set the camera as the frame source for various capture modes. The camera permissions are handled by the plugins, so you don’t need to specify anything explicitly. import OSSLicense from '../../partials/_third-party-licenses-js.mdx'; --- ## Agent Skills import SkillsPage from '@site/src/components/SkillsPage'; # Agent Skills for Capacitor --- ## Configure Barcode Symbologies # Configure Barcode Symbologies import Intro from '../../../partials/configure-symbologies/_intro.mdx' ## Enable the Symbologies You Want to Read import EnableSymbologies from '../../../partials/configure-symbologies/_enable-symbologies.mdx' The following lines of code show you how to enable scanning Code 128 codes for barcode capture: ```js const settings = new BarcodeCaptureSettings(); settings.enableSymbology(Symbology.Code128, true); ``` import CapturePresents from '../../../partials/configure-symbologies/_capture-presents.mdx' ## Configure the Active Symbol Count Barcode symbologies (such as Code 128, Code 39, Code 93, or Interleaved Two of Five) can store variable-length data. For example, Code 39 can be used to store a string from 1 to 40-50 symbols. There is no fixed upper limit, though there are practical limitations to the code’s length for it to still be conveniently readable by barcode scanners. For performance reasons, the Scandit Data Capture SDK limits the [possible symbol range](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.ActiveSymbolCounts) for variable-length symbologies. If you want to read codes that are shorter/longer than the specified default range or you want to tailor your app to only read codes of a certain length, you need to change the active symbol count of the symbology to accommodate the data length you want to use in your application. The below lines of code show how to change the active symbol count for Code 128 to read codes with 6, 7 and 8 symbols. ```js const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code128); symbologySettings.activeSymbolCounts = [6, 7, 8]; ``` import CalculateSymbolCount from '../../../partials/configure-symbologies/_calculate-symbol-count.mdx' ## Read Bright-on-Dark Barcodes Most barcodes are printed using dark ink on a bright background. Some symbologies allow the colors to be inverted and can also be printed using bright ink on a dark background. This is not possible for all symbologies as it could lead to false reads when the symbology is not designed for this use case. See [symbology properties](../symbology-properties.mdx) to learn which symbologies allow color inversion. When you enable a symbology as described above, only dark-on-bright codes are enabled (see [SymbologySettings.isEnabled](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.IsEnabled 'SymbologySettings.isEnabled property')). When you also want to read bright-on-dark codes, color-inverted reading for that symbology must also be enabled (see [SymbologySettings.isColorInvertedEnabled](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.IsColorInvertedEnabled)): ```js const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code128); symbologySettings.isColorInvertedEnabled = true; ``` ## Enforce Checksums Some symbologies have a mandatory checksum that will always be enforced while others only have optional [checksums](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/checksum.html#enum-scandit.datacapture.barcode.Checksum). Enforcing an optional checksum will reduce false positives as an additional check can be performed. When enabling a checksum you have to make sure that the data of your codes contains the calculated checksum otherwise the codes will be discarded as they checksum doesn’t match. All available checksums per symbology can be found in the documentation on [symbology properties](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/symbology-properties.html). You can enforce a specific checksum by setting it through [SymbologySettings.checksums](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.Checksums): ```js const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code39); symbologySettings.checksums = [Checksum.Mod43]; ``` ## Enable Symbology-Specific Extensions Some symbologies allow further configuration. These configuration options are available as symbology extensions that can be enabled/disabled for each symbology individually. Some extensions affect how the data in the code is formatted, others allow for more relaxed recognition modes that are disabled by default to eliminate false reads. All available extensions per symbology and a description of what they do can be found in the documentation on [symbology properties](../symbology-properties.mdx). To enable/disable a symbology extension, use [SymbologySettings.setExtensionEnabled()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/symbology-settings.html#method-scandit.datacapture.barcode.SymbologySettings.SetExtensionEnabled). The following code shows how to enable the full ASCII extension for Code 39. ```js const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code39); symbologySettings.setExtensionEnabled('full_ascii', true); ``` This extension allows Code 39 to encode all 128 ASCII characters instead of only the 43 characters defined in the standard. The extension is disabled by default as it can lead to false reads when enabled. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Barcode Capture to your application. The general steps are: - Include the ScanditBarcodeCapture library and its dependencies to your project, if any. - Initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with your license key. - Create a [barcode capture settings](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and enable the [barcode symbologies](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology) you want to read in your application. - Create a new [barcode capture mode](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance and initialize it with the settings created above. - Register a [barcode capture listener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Scanning Behavior Barcode scanning is orchestrated by the [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) [data capture mode](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). This class is the main entry point for scanning barcodes. It is configured through [BarcodeCaptureSettings](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) that will get informed whenever new codes have been recognized. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```js const settings = new BarcodeCaptureSettings(); settings.enableSymbologies([ Symbology.Code128, Symbology.Code39, Symbology.QR, Symbology.EAN8, Symbology.UPCE, Symbology.EAN13UPCA, ]); ``` If you are not disabling barcode capture immediately after having scanned the first code, consider setting the [BarcodeCaptureSettings.codeDuplicateFilter](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture-settings.html#property-scandit.datacapture.barcode.BarcodeCaptureSettings.CodeDuplicateFilter) to around 500 or even \-1 if you do not want codes to be scanned more than once. Next, create a [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance with the settings initialized in the previous step: ```js const barcodeCapture = new BarcodeCapture(settings); DataCaptureContext.sharedInstance.addMode(barcodeCapture); ``` ## Register the Barcode Capture Listener To get informed whenever a new code has been recognized, add a [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) through [BarcodeCapture.addListener()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.AddListener) and implement the listener methods to suit your application’s needs. First implement the [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) interface. For example: ```js const listener = { didScan: (barcodeCapture, session) => { const recognizedBarcodes = session.newlyRecognizedBarcode; // Do something with the barcodes }, }; ``` Then add the listener: ```js barcodeCapture.addListener(listener); ``` ### Rejecting Barcodes To prevent scanning unwanted codes, you can reject them by adding the desired logic to the `onBarcodeScanned` method. This will prevent the barcode from being added to the session and will not trigger the `onSessionUpdated` method. The example below will only scan barcodes beginning with the digits `09` and ignore all others, using a transparent brush to distinguish a rejected barcode from a recognized one: ```js ... if (!barcode.data || !barcode.data.startsWith('09:')) { window.overlay.brush = Brush.transparent; return; } ... ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```js const cameraSettings = BarcodeCapture.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. const camera = Camera.default; if (camera) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js DataCaptureContext.sharedInstance.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```js camera.switchToDesiredState(FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js const view = DataCaptureView.forContext(DataCaptureContext.sharedInstance); view.connectToElement(htmlElement); ``` To visualize the results of barcode scanning, the following [overlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) can be added: ```js const overlay = new BarcodeCaptureOverlay(barcodeCapture); view.addOverlay(overlay); ``` ## Disabling Barcode Capture To disable barcode capture, for instance as a consequence of a barcode being recognized, set [BarcodeCapture.isEnabled](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-capture.html#property-scandit.datacapture.barcode.BarcodeCapture.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## Barcode Generator # Barcode Generator The Barcode Generator is a simple tool to generate barcodes directly from the Scandit SDK. In this guide, we will show you how to use the Barcode Generator to generate barcodes and QR codes. The Barcode Generator supports the following formats: * Code 39 * Code 128 * EAN 13 * UPCA * ITF * QR * DataMatrix * PDF417 (SDK version >= 8.2) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/capacitor/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Generating Barcodes To generate barcodes, you need to initialize the [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`BarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.BarcodeGeneratorBuilder), and use the method of [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) for the symbology you are interested in, in this example Code 128. You can configure the colors used in the resulting image: ```javascript DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); const builder = BarcodeGenerator.code128BarcodeGeneratorBuilder(DataCaptureContext.sharedInstance) .withBackgroundColor(Color.fromHex('#ffffff')) .withForegroundColor(Color.fromHex('#000000')); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: When the builder is configured get the `BarcodeGenerator` and try to generate the image: ```javascript try { const generator = builder.build(); const image = await generator.generate(dataString, 200); // Use the image } catch (error) { // Handle the error console.error(error); } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-generator.html) for more information. ## Generating QR Codes To generate barcodes, you need to initialize the [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`QRCodeBarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder) using the method of [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) specific for QR codes. You can configure the colors used in the resulting image, and the two settings that can be configured for QR codes: [`QRCodeBarcodeGeneratorBuilder.errorCorrectionLevel`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithErrorCorrectionLevel) and [`QRCodeBarcodeGeneratorBuilder.versionNumber`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithVersionNumber). ```javascript DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); const builder = BarcodeGenerator.qrCodeBarcodeGeneratorBuilder(DataCaptureContext.sharedInstance) .withBackgroundColor(Color.fromHex('#ffffff')) .withForegroundColor(Color.fromHex('#000000')) .withErrorCorrectionLevel(QrCodeErrorCorrectionLevel.Medium) .withVersionNumber(4); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: When the builder is configured get the `BarcodeGenerator` and try to generate the image: ```javascript try { const generator = builder.build(); const image = await generator.generate(dataString, 200); // Use the image } catch (error) { // Handle the error console.error(error); } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-generator.html) for more information. --- ## Get Started # Get Started :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/capacitor/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: In this guide you will learn step-by-step how to add Barcode Selection to your application. The general steps are: - Initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with your license key. - Create a [barcode selection settings](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and choose the right configuration. - Create a new [barcode selection mode](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection 'barcode selection mode class') instance and initialize it with the settings created above. - Register a [barcode selection listener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-selection-basic-overlay.html#class-scandit.datacapture.barcode.selection.ui.BarcodeSelectionBasicOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext 'data capture context class') with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Selection Behavior _Symbologies_ Barcode selection is orchestrated by the [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) [data capture mode](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). It is configured through [BarcodeSelectionSettings](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) that will get informed whenever new codes have been selected. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```js const settings = new BarcodeSelectionSettings(); settings.enableSymbologies([ Symbology.Code128, Symbology.EAN8, Symbology.UPCE, Symbology.EAN13UPCA, ]); ``` _Selection Types_ The behavior of Barcode Selection can be changed by using a different [selection type](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-type.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionType). This defines the method used by [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) to select codes. Currently there are two types. If you want the user to select barcodes with a tap, then use [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection). This selection type can automatically freeze the camera preview to make the selection easier. You can configure the freezing behavior via [BarcodeSelectionTapSelection.freezeBehavior](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.FreezeBehavior). With [BarcodeSelectionTapSelection.tapBehavior](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.TapBehavior) you can decide if a second tap on a barcode means that the barcode is unselected or if it is selected another time (increasing the counter). :::note Using [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection) requires the MatrixScan add-on. ::: If you want the selection to happen automatically based on where the user points the camera, then use [BarcodeSelectionAimerSelection](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-aimer-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAimerSelection). It is possible to choose between two different [selection strategies](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-strategy.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionStrategy). Use [BarcodeSelectionAutoSelectionStrategy](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAutoSelectionStrategy) if you want the barcodes to be selected automatically when aiming at them as soon as the intention is understood by our internal algorithms. Use [BarcodeSelectionManualSelectionStrategy](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionManualSelectionStrategy) if you want the barcodes to be selected when aiming at them and tapping anywhere on the screen. _Single Barcode Auto Detection_ If you want to automatically select a barcode when it is the only one on screen, turn on [BarcodeSelectionSettings.singleBarcodeAutoDetection](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-settings.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionSettings.SingleBarcodeAutoDetection). _Creating the mode_ Next, create a [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance with the settings initialized in the previous step: ```js const barcodeSelection = new BarcodeSelection(settings); await DataCaptureContext.sharedInstance.addMode(barcodeSelection); ``` ## Register the Barcode Selection Listener To get informed whenever a new code has been recognized, add a [BarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) through [BarcodeSelection.addListener()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection.html#method-scandit.datacapture.barcode.selection.BarcodeSelection.AddListener) and implement the listener methods to suit your application’s needs. First implement the [BarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) interface. For example: ```js const listener = { didUpdateSelection: (barcodeSelection, session) => { const newlySelectedBarcodes = session.newlySelectedBarcodes; // Do something with the barcodes }, }; ``` Then add the listener: ```js barcodeSelection.addListener(listener); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```js const cameraSettings = BarcodeSelection.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. const camera = Camera.default; if (camera) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js DataCaptureContext.sharedInstance.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```js camera.switchToDesiredState(FrameSourceState.On); ``` ## Disabling Barcode Selection To disable barcode selection, for instance when the selection is complete, set [BarcodeSelection.isEnabled](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelection.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## About Barcode Selection # About Barcode Selection :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/capacitor/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: Barcode Selection enables you to increase scanning accuracy and prevent users from scanning the wrong code in scenarios where there are multiple barcodes present, such as a crowded shelf, an order catalog with barcodes printed closely together, or a label with multiple barcodes. Barcode Selection provides two key capabilities: - **Aim to Select** allows users to select one code at a time. This is especially useful for one-handed operation. - **Tap to Select** is a quick way for users to select several codes from the same view. Selection is done by tapping on highlighted barcodes in the live camera preview or on a frozen screen. :::warning Barcode Selection does not support handling of duplicate codes. If a code appears twice in the visible preview both instances will be marked as selected even if only one of them was selected. ::: --- ## Get Started # Get Started Get up and running with SparkScan, the easiest way to start with Scandit barcode scanning. SparkScan provides top performance and optimized scanning UX with just a few lines of code, incorporating the best practices developed by Scandit across years of experience and billions of scans. The intentionally minimalistic UI floats on top of any smartphone application, without the need to adapt the existing app. The fastest way to get started is by running our sample application, so we'll cover that first. After that, we'll show you how to integrate SparkScan into your own application. ## Prerequisites Before you start, make sure you have the following: - Capacitor Version 5-8 [and other related tools and dependencies](https://capacitorjs.com/docs/getting-started). - A project with minimum iOS deployment target of 15.0 or higher. Or an Android project with target SDK version 24 (Android 7, Nougat) or higher. - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). ## Sample Application In this section, we'll show you how to try SparkScan in minutes by running our sample application. ### Running the Sample Application 1. First we need a copy of the sample application. It is available on GitHub and also bundled with the SDK archive you can download from your Scandit account dashboard. Here we'll use the GitHub repository. ```bash git clone https://github.com/Scandit/datacapture-capacitor-samples.git ``` 2. The repository contains many sample applications you can try. For this example, we'll use the **ListBuildingSample**. Navigate to the sample directory from the terminal or your preferred IDE: ```bash cd datacapture-capacitor-samples/ListBuildingSample ``` 3. From the `/www/js` directory, open the `app.js` file and enter your Scandit License Key: ```js ... DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ... ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: 4. Install the dependencies: ```bash npm install ``` 5. Start the development server: ```bash npm run dev ``` 6. Open your browser and navigate to `http://localhost:8888`. You should see the sample application running. ## Integrating SparkScan into Your Application This section will guide you through the general steps for integrating SparkScan into your own application. There may be additional steps depending on your specific use case, and you can always reach out to [Scandit Support](mailto:support@scandit.com) with any issues. ### 1. Installation First you need to install the required packages. You can this via npm: ```bash # Core library npm install scandit-capacitor-datacapture-core # Barcode scanning functionality npm install scandit-capacitor-datacapture-barcode ``` ### 2. Initialize the Data Capture Context The first step is to initialize the Data Capture Context with your license key: ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ### 3. Configure SparkScan Settings Next, you need to configure your desired settings for SparkScan, such as the symbologies you want to scan. This is done by creating an instance of the `SparkScanSettings` class: ```js const settings = new SparkScanSettings(); settings.enableSymbologies([Symbology.EAN13UPCA, Symbology.Code128]); settings.codeDuplicateFilter = 0; settings.scanIntention = ScanIntention.Smart; ``` In this example, we're: - Enabling both EAN-13 and Code 128 symbologies - Setting the code duplicate filter to 0, meaning the same code can be reported multiple times - Using the Smart [scan intention](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/scan-intention.html#enum-scandit.datacapture.core.ScanIntention) algorithm, to reduce the likelihood of unintended scans ### 4. Setup the SparkScanView Now we'll create and configure the scanner view and it's settings. This is done via the `SparkScanView` and `SparkScanViewSettings` classes: ```js const viewSettings = new SparkScanViewSettings(); viewSettings.defaultScanningMode = new SparkScanScanningModeTarget(SparkScanScanningBehavior.Single); viewSettings.soundEnabled = true; viewSettings.hapticEnabled = false; ``` In this example, we're: - Setting the default scanning mode to `SparkScanScanningModeTarget` for precision scanning - Enabling sound feedback - Disabling haptic feedback Next, we create the `SparkScanView` instance, adding the scanning interface to the application: ```js const sparkScanView = SparkScanView.forContext(DataCaptureContext.sharedInstance, sparkScan, viewSettings); ``` In your application's state handling logic, you must also call the `stopScanning` method when the scanner is no longer needed: ```js componentWillUnmount() { sparkScanView.stopScanning(); } handleAppStateChange = async (nextAppState) => { if (nextAppState.match(/inactive|background/)) { sparkScanView.stopScanning(); } }; ``` ### 5. Implement the Listener Lastly, you need to implement the listener to handle the scanned data. This is done by creating an instance of the [`SparkScanListener`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) class: ```js const listener = { didScan: (sparkScan, session, getFrameData) => { // Gather the recognized barcode const barcode = session.newlyRecognizedBarcode[0]; // Handle the barcode }, }; sparkScan.addListener(listener); ``` Here, `didScan()` is called when a barcode is recognized. You can access the recognized barcode data from the `SparkScanSession` object. ### 6. Next Steps This guide provides a basic overview of how to integrate SparkScan into your application. For more detailed information, check out the [SparkScan documentation](/sdks/capacitor/sparkscan/intro.md) and [SparkScan API Reference](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/spark-scan.html). If you have any questions or need help, feel free to reach out to [Scandit Support](mailto:support@scandit.com). --- ## Advanced Configurations # Advanced Configurations There are several advanced configurations that can be used to customize the behavior of the ID Capture SDK and enable additional features. ## Configure Data Anonymization By default, data extracted from documents is anonymized according to local regulations. See [Anonymized Documents](/sdks/capacitor/id-capture/supported-documents.md#anonymized-documents) for more information. That means certain data from certain fields won’t be returned, even if it’s present on a document. You control the anonymization level with the following setting: ```js // Default value: settings.anonymizationMode = IdAnonymizationMode.FieldsOnly; // Sensitive data is additionally covered with black boxes on returned images: settings.anonymizationMode = IdAnonymizationMode.FieldsAndImages; // Only images are anonymized: settings.anonymizationMode = IdAnonymizationMode.ImagesOnly; // No anonymization: settings.anonymizationMode = IdAnonymizationMode.None; ``` ## ID Images Your use can may require that you capture and extract images of the ID document. Use the [IdImageType](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/id-image-type.html#enum-scandit.datacapture.id.IdImageType) enum to specify the images you want to extract from the `CapturedId` object. :::tip Face and Cropped Document can be extracted only by either `SingleSideScanner` with `visualInspectionZone` enabled or by `FullDocumentScanner`. In the case of `FullDocumentScanner`, if the front & the back side of a document are scanned, Cropped Document and Full Frame are returned for both sides. ::: For the full frame of the document, you can use [`setShouldPassImageTypeToResult`](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/id-capture-settings.html#method-scandit.datacapture.id.IdCaptureSettings.SetShouldPassImageTypeToResult) when creating the `IdCaptureSettings` object. This will pass the image type to the result, which you can then access in the `CapturedId` object. ```js // Holder's picture as printed on a document: settings.setShouldPassImageTypeToResult(IdImageType.Face, true); // Cropped image of a document: settings.setShouldPassImageTypeToResult(IdImageType.CroppedDocument, true); // Full camera frame that contains the document: settings.setShouldPassImageTypeToResult(IdImageType.Frame, true); ``` ## Callbacks and Scanning Workflows The ID Capture Listener provides two callbacks: `onIdCaptured` and `onIdRejected`. The `onIdCaptured` callback is called when an acceptable document is successfully captured, while the `onIdRejected` callback is called when a document is captured but rejected. For a successful capture, the `onIdCaptured` callback provides a `CapturedId` object that contains the extracted information from the document. This object is specific to the type of document scanned. For example, a `CapturedId` object for a US Driver License will contain different fields than a `CapturedId` object for a Passport. For a rejected document, a [RejectionReason](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) is provided in the `onIdRejected` callback to help you understand why the document was rejected and to take appropriate action. These are: * NOT_ACCEPTED_DOCUMENT_TYPE: The document is not in the list of accepted documents. In this scenario, you could direct the user to scan a different document. * INVALID_FORMAT: The document is in the list of accepted documents, but the format is invalid. In this scenario, you could direct the user to scan the document again. * DOCUMENT_VOIDED: The document is in the list of accepted documents, but the document is voided. In this scenario, you could direct the user to scan a different document. * TIMEOUT: The document was not scanned within the specified time. In this scenario, you could direct the user to scan the document again. ## Detect Fake IDs *ID Validate* is a fake ID detection software. It currently supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). Fake ID detection can be performed automatically using the following settings: * [IdCaptureSettings.rejectForgedAamvaBarcodes](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectForgedAamvaBarcodes): Automatically rejects documents whose AAMVA barcode fails authenticity validation. * [IdCaptureSettings.rejectInconsistentData](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectInconsistentData): Automatically rejects documents whose human‑readable data does not match the data encoded in the barcode or MRZ. To enable ID validation for your subscription, please reach out to [Scandit Support](mailto:support@scandit.com). --- ## Get Started # Get Started In this guide you will learn step-by-step how to add ID Capture to your application. The general steps are: - Initializing the Data Capture Context - Accessing a Camera - Configuring the Capture Settings - Implementing a Listener to Receive Scan Results - Setting up the Capture View and Overlay - Starting the Capture Process :::warning Using ID Capture at the same time as other modes (e.g. Barcode Capture) is not supported. ::: ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](/sdks/capacitor/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: Please note that your license may support only a subset of ID Capture features. If you would like to use additional features please contact us at [Scandit Support](mailto:support@scandit.com). ### Module Overview import IdModuleOverview from '../../../partials/get-started/_id-module-overview-no-eu-dl.mdx'; ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Add the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/camera.html#class-scandit.datacapture.core.Camera): ```js const camera = Camera.default; DataCaptureContext.sharedInstance.setFrameSource(camera); const cameraSettings = IdCapture.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. if (camera != null) { camera.applySettings(cameraSettings); } ``` ## Create ID Capture Settings Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scanner type to use and the documents that should be accepted and/or rejected. Check [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) for all available options. :::tip By default, [anonymized data](./advanced.md#configure-data-anonymization) is not returned in accordance with local regulations for specific documents. This setting can be disabled for testing purposes, but be sure to comply with local laws and requirements in production. ::: ```ts const settings = new IdCaptureSettings(); // Documents from any region: settings.acceptedDocuments.push(new IdCard(IdCaptureRegion.Any)); // Only documents issued by a specific country: settings.acceptedDocuments.push(new IdCard(IdCaptureRegion.Germany)); // Regional documents: settings.acceptedDocuments.push(new RegionSpecific(RegionSpecificSubtype.ApecBusinessTravelCard)); // Reject passports from certain regions: settings.rejectedDocuments.push(new Passport(IdCaptureRegion.Cuba)); // To scan only one-sided documents and a given zone: settings.scanner = new SingleSideScanner(true, false, false); // or settings.scanner = new SingleSideScanner(false, true, false); // or settings.scanner = new SingleSideScanner(false, false, true); // To scan both sides of the document: settings.scanner = new FullDocumentScanner(); ``` Create a new ID Capture mode with the chosen settings: ```ts const idCapture = new IdCapture(settings); DataCaptureContext.sharedInstance.addMode(idCapture); ``` ## Implement the Listener To receive scan results, implement [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener). The listener provides two callbacks: `onIdCaptured` and `onIdRejected`. ```ts idCapture.addListener({ onIdCaptured: (data) => { // Success! Handle extracted data here. }, onIdRejected: (data, reason) => { // Something went wrong. Inspect the reason to determine the follow-up action. } }); ``` ### Handling Success Capture results are delivered as a [CapturedId](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/captured-id.html#class-scandit.datacapture.id.CapturedId). This class contains data common for all kinds of personal identification documents. For more specific information, use its non-null result properties (e.g. [CapturedId.barcode](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/captured-id.html#property-scandit.datacapture.id.CapturedId.Barcode)). On a successful scan you may read the extracted data from `CapturedId`: ```ts onIdCaptured: (data) => { const fullName = data.fullName; const dateOfBirth = data.dateOfBirth; const dateOfExpiry = data.dateOfExpiry; const documentNumber = data.documentNumber; // Process data: processData(fullName, dateOfBirth, dateOfExpiry, documentNumber); } ``` :::tip All data fields are optional, so it's important to verify whether the required information is present if some of the accepted documents may not contain certain data. ::: ### Handling Rejection The ID scanning process may fail for various reasons. Start from inspecting [RejectionReason](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) to understand the cause. You may wish to implement the follow-up action based on the reason of failure: ```ts onIdRejected: (data, reason) => { if (reason === RejectionReason.Timeout) { // Ask the user to retry, or offer alternative input method. } else if (reason === RejectionReason.DocumentExpired) { // Ask the user to provide alternative document. } else if (reason === RejectionReason.HolderUnderage) { // Reject the process. } } ``` ## Set up Capture View and Overlay When using the built-in camera as [frameSource](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/frame-source.html#interface-scandit.datacapture.core.IFrameSource), you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js const view = DataCaptureView.forContext(DataCaptureContext.sharedInstance); view.connectToElement(htmlElement); ``` Then create an instance of [IdCaptureOverlay](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) attached to the view: ```js const overlay = new IdCaptureOverlay(idCapture); view.addOverlay(overlay); ``` The overlay chooses the displayed UI automatically, based on the selected [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings). If you prefer to show a different UI or to temporarily hide it, set the appropriate [IdCaptureOverlay.idLayout](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/ui/id-capture-overlay.html#property-scandit.datacapture.id.ui.IdCaptureOverlay.IdLayout). ## Start the Capture Process Finally, turn on the camera to start scanning: ```js camera.switchToDesiredState(FrameSourceState.On); ``` And this is it. You can now scan documents. --- ## About ID Capture import AboutIdCapture from '../../../partials/intro/_about-id-capture.mdx'; --- ## Supported Documents ## ID Scanning Supported Documents Scandit ID Capture provides various [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/capacitor/id-capture/api/id-capture-scanner.html#id-capture-scanner) types, each designed for specific scanning workflows. These workflows can involve scanning either specific parts of a document or the entire document, including both the front and back sides. This section details the types of documents supported by each scanner type. import IdDocumentsFull from '../../../partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from '../../../partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents import IdValidateDocuments from '../../../partials/advanced/_id-documents-validate.mdx'; --- ## Advanced Configurations import ValidationFlowHowItWorks from '../../../partials/advanced/_validation-flow-how-it-works.mdx'; import ValidationFlowCustomButtons from '../../../partials/advanced/_validation-flow-custom-buttons.mdx'; import ValidationFlowTypingHints from '../../../partials/advanced/_validation-flow-typing-hints.mdx'; import ValidationFlowCloudVLM from '../../../partials/advanced/_validation-flow-cloud-vlm.mdx'; import ReceiptScanning from '../../../partials/advanced/_receipt-scanning.mdx'; import ValidationFlowRequiredOptional from '../../../partials/advanced/_validation-flow-required-optional.mdx'; import ValidationFlowCustomToasts from '../../../partials/advanced/_validation-flow-custom-toasts.mdx'; import ValidationFlowCustomField from '../../../partials/advanced/_validation-flow-custom-field.mdx'; # Advanced Configurations ## Customize the Overlay Appearance To customize the appearance of the overlay, you can implement a [LabelCaptureBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/ui/label-capture-basic-overlay-listener.html#interface-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener). The method [brushForLabel()](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForLabel) is called every time a label captured and [brushForFieldOfLabel()](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForField) is called for each of its fields to determine the brush for the label or field. ```js // Create the overlay for the label capture mode. const overlay = new LabelCaptureBasicOverlay(labelCapture); // Set the listener to customize the appearance of captured labels and fields. overlay.listener = { /** * Called for each field of a captured label to determine its brush. * Return a Brush to customize the field's appearance, or null to use the default. */ brushForFieldOfLabel: (overlay, field, label) => { // Create colors with transparency (alpha 0.5 = 50% opacity). const cyanColor = Color.fromRGBA(0, 255, 255, 0.5); const orangeColor = Color.fromRGBA(255, 165, 0, 0.5); switch (field.name) { case "": // Highlight barcode fields with a cyan color. return new Brush(cyanColor, cyanColor, 0); case "": // Highlight expiry date fields with an orange color. return new Brush(orangeColor, orangeColor, 0); default: // Use a transparent brush for other fields. return Brush.transparent; } }, /** * Called for each captured label to determine its brush. * Return a Brush to customize the label's appearance, or null to use the default. */ brushForLabel: (overlay, label) => { // Use a transparent brush for the label itself. return Brush.transparent; }, /** * Called when the user taps on a label. */ didTapLabel: (overlay, label) => { // Handle user tap gestures on the label. } }; // Add the overlay to the data capture view. dataCaptureView.addOverlay(overlay); ``` :::tip Use brush colors with transparency (alpha ```js // Create the overlay const validationFlowOverlay = new LabelCaptureValidationFlowOverlay(labelCapture); dataCaptureView.addOverlay(validationFlowOverlay); // Set the listener to receive validation events validationFlowOverlay.listener = validationFlowListener; ``` ### Define a Listener When the user has verified that all fields are correctly captured and presses the finish button, the Validation Flow triggers a callback with the final results. To receive these results, implement the [LabelCaptureValidationFlowListener](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/ui/label-capture-validation-flow-listener.html) interface: ```js const validationFlowListener = { // This is called by the validation flow overlay when a label has been fully captured and validated didCaptureLabelWithFields: (fields) => { const barcodeData = fields.find(f => f.name === "")?.barcode?.data; const expiryDate = fields.find(f => f.name === "")?.text; // Handle the captured values } }; ``` ```js const validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.create(); validationFlowOverlaySettings.setPlaceholderTextForLabelDefinition("Expiry Date", "MM/DD/YYYY"); validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.create(); validationFlowOverlaySettings.restartButtonText = "Borrar todo"; validationFlowOverlaySettings.pauseButtonText = "Pausar"; validationFlowOverlaySettings.finishButtonText = "Finalizar"; validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.create(); validationFlowOverlaySettings.standbyHintText = "No label detected, camera paused"; validationFlowOverlaySettings.validationHintText = "data fields collected"; // X/Y (X fields out of total Y) is shown in front of this string validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.create(); validationFlowOverlaySettings.validationErrorText = "Incorrect format."; validationFlowOverlaySettings.scanningText = "Scan in progress"; validationFlowOverlaySettings.adaptiveScanningText = "Processing"; validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const customBarcode = CustomBarcode.initWithNameAndSymbologies('Barcode', [ Symbology.EAN13UPCA, Symbology.GS1DatabarExpanded, Symbology.Code128, ]); customBarcode.optional = false; const expiryDateText = new ExpiryDateText('Expiry Date'); expiryDateText.labelDateFormat = new LabelDateFormat(LabelDateComponentFormat.MDY, false); expiryDateText.optional = false; const label = new LabelDefinition('Retail Item'); label.fields = [customBarcode, expiryDateText]; label.adaptiveRecognitionMode = AdaptiveRecognitionMode.Auto; const settings = LabelCaptureSettings.settingsFromLabelDefinitions([label], {}); ``` See [AdaptiveRecognitionMode](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/label-definition.html#property-scandit.datacapture.label.LabelDefinition.AdaptiveRecognitionMode) for available options. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Smart Label Capture to your application. The general steps are: - Create a component to handle the capture process - Initialize the Data Capture Context - Initialize the Label Capture Mode - Implement a listener to handle captured labels - Visualize the scan process - Start the camera - Provide feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/capacitor/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import LabelCaptureModuleOverview from '../../../partials/get-started/_smart-label-capture-module-overview-web.mdx'; ## Initialize the Data Capture Context import DataCaptureContextWeb from '../../../partials/get-started/_create-data-capture-context-web.mdx'; ## Initialize the Label Capture Mode The main entry point for the Label Capture Mode is the [LabelCapture](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/label-capture.html#class-scandit.datacapture.label.LabelCapture) object. It is configured through [LabelCaptureSettings](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/label-capture-settings.html#class-scandit.datacapture.label.LabelCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) that get informed whenever a new frame has been processed. ```js import { Symbology } from "scandit-capacitor-datacapture-barcode"; import { CustomBarcode, ExpiryDateText, ImeiOneBarcode, ImeiTwoBarcode, LabelCapture, LabelCaptureSettings, LabelDateComponentFormat, LabelDateFormat, LabelDefinition, SerialNumberBarcode, TotalPriceText, UnitPriceText, WeightText, } from "scandit-capacitor-datacapture-label"; // Create a label definition for an ISOF (In-Store Order Fulfillment) label. // This label type typically includes a barcode, price fields, expiry date, and weight. const isofLabel = new LabelDefinition("ISOF Label"); // Add a barcode field that expects an EAN-13 or UPC-A barcode. const barcodeField = CustomBarcode.initWithNameAndSymbology("Barcode", Symbology.EAN13UPCA); barcodeField.optional = false; isofLabel.addField(barcodeField); // Add a total price text field. const totalPriceField = new TotalPriceText("Total Price"); totalPriceField.optional = false; isofLabel.addField(totalPriceField); // Add a unit price text field. const unitPriceField = new UnitPriceText("Unit Price"); unitPriceField.optional = false; isofLabel.addField(unitPriceField); // Add an expiry date text field with a specific date format (Month-Day-Year). const expiryDateField = new ExpiryDateText("Expiry Date"); expiryDateField.optional = false; expiryDateField.labelDateFormat = new LabelDateFormat(LabelDateComponentFormat.MDY, false); isofLabel.addField(expiryDateField); // Add a weight text field. const weightField = new WeightText("Weight"); weightField.optional = false; isofLabel.addField(weightField); // Create a label definition for a smart device label. // This label type is commonly found on electronic devices and includes IMEI numbers and serial numbers. const smartDeviceLabel = new LabelDefinition("Smart Device Label"); // Add an IMEI barcode field (first IMEI number). const imeiField = ImeiOneBarcode.initWithNameAndSymbology("IMEI", Symbology.Code128); imeiField.optional = false; smartDeviceLabel.addField(imeiField); // Add a second IMEI barcode field (for dual-SIM devices). const imei2Field = ImeiTwoBarcode.initWithNameAndSymbology("IMEI2", Symbology.Code128); imei2Field.optional = false; smartDeviceLabel.addField(imei2Field); // Add a serial number barcode field. const serialNumberField = SerialNumberBarcode.initWithNameAndSymbology("Serial Number", Symbology.Code128); serialNumberField.optional = false; smartDeviceLabel.addField(serialNumberField); // Add a custom barcode field for EID (Electronic ID). const eidField = CustomBarcode.initWithNameAndSymbology("EID", Symbology.Code128); eidField.optional = false; smartDeviceLabel.addField(eidField); // Create the label capture settings from the label definitions. const settings = LabelCaptureSettings.settingsFromLabelDefinitions( [isofLabel, smartDeviceLabel], null // Optional properties ); // Create the label capture mode with the settings. const labelCapture = new LabelCapture(settings); // Add the mode to the data capture context created earlier. dataCaptureContext.addMode(labelCapture); ``` ## Implement a Listener to Handle Captured Labels To get informed whenever a new label has been recognized, add a [LabelCaptureListener](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) through [LabelCapture.addListener()](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/label-capture.html#method-scandit.datacapture.label.LabelCapture.AddListener) and implement the listener methods to suit your application’s needs. First conform to the `LabelCaptureListener` interface. Here is an example of how to implement a listener that processes the captured labels based on the label capture settings defined above. ```js import { Feedback } from "scandit-capacitor-datacapture-core"; import { LabelCaptureListener } from "scandit-capacitor-datacapture-label"; // Create a listener to handle captured labels. const labelCaptureListener = { // Called for every processed frame. Check session.capturedLabels for results. didUpdateSession: (labelCapture, session) => { // Early return if no label has been captured in this frame. if (session.capturedLabels.length === 0) { return; } // Process each captured label. session.capturedLabels.forEach((capturedLabel) => { const fields = capturedLabel.fields; // Access the barcode field by its name (as defined in the label definition). // The barcode property contains the scanned barcode data. const barcodeField = fields.find((field) => field.name === "Barcode"); const barcodeData = barcodeField?.barcode?.data; // Access the expiry date field. Use the text property for OCR-captured text, // or the asDate() method to get a parsed LabelDateResult. const expiryDateField = fields.find((field) => field.name === "Expiry Date"); const expiryDateText = expiryDateField?.text; const expiryDateResult = expiryDateField?.asDate(); // Handle the captured data as needed, for example: // - Update your app's state // - Navigate to a results screen // - Send data to your backend console.log("Barcode:", barcodeData); console.log("Expiry Date:", expiryDateText); }); // Disable label capture to prevent capturing the same labels multiple times. // Re-enable it when you're ready to scan again. labelCapture.isEnabled = false; // Emit feedback to indicate a successful scan. // See the Feedback section for customization options. Feedback.defaultFeedback.emit(); } }; // Register the listener with the label capture mode. labelCapture.addListener(labelCaptureListener); ``` ## Visualize the Scan Process The capture process can be visualized by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy. The view controls the UI elements, such as the viewfinder and overlays, that are shown to visualize captured labels. To visualize the results of Label Capture, you can choose between two overlays, [LabelCaptureBasicOverlay](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/ui/label-capture-basic-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureBasicOverlay) and [LabelCaptureAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/ui/label-capture-advanced-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureAdvancedOverlay). Here is an example of how to add a `LabelCaptureBasicOverlay` to the `DataCaptureView`. ```js import { RectangularViewfinder, RectangularViewfinderStyle } from "scandit-capacitor-datacapture-core"; import { LabelCaptureBasicOverlay } from "scandit-capacitor-datacapture-label"; // Create the overlay for the label capture mode created earlier. const overlay = new LabelCaptureBasicOverlay(labelCapture); // Add the overlay to the data capture view. dataCaptureView.addOverlay(overlay); // Optionally, add a viewfinder to guide users through the capture process. const viewfinder = new RectangularViewfinder(RectangularViewfinderStyle.Square); overlay.viewfinder = viewfinder; ``` :::tip See the [Advanced Configurations](advanced.md) section for more information about how to customize the appearance of the overlays and how to use the advanced overlay to display arbitrary Android views such as text views, icons or images. ::: ## Start the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/camera.html#class-scandit.datacapture.core.Camera): ```js import { Camera, FrameSourceState } from "scandit-capacitor-datacapture-core"; import { LabelCapture } from "scandit-capacitor-datacapture-label"; // Get the default camera (usually the back-facing camera). const camera = Camera.default; // Set the camera as the frame source for the data capture context. await dataCaptureContext.setFrameSource(camera); // Use the recommended camera settings for label capture. const cameraSettings = LabelCapture.createRecommendedCameraSettings(); // Depending on the use case, further camera settings adjustments can be made here. await camera.applySettings(cameraSettings); ``` Once the `Camera`, `DataCaptureContext`, `DataCaptureView` and `LabelCapture` are initialized, you can switch on the camera to start capturing labels. Typically, this is done once the view becomes active and the user granted permission to use the camera, or once the user presses continue scanning after handling a previous scan. ```js // Turn on the camera to start capturing labels. await camera.switchToDesiredState(FrameSourceState.On); ``` Please refer to the available [sample apps](https://github.com/Scandit/datacapture-capacitor-samples) for detailed examples of camera permission handling and view lifecycle management. ## Provide Feedback Smart Label Capture provides customizable feedback, emitted automatically when a label is recognized and successfully processed, configurable via [`LabelCapture.feedback`](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/label-capture.html#property-scandit.datacapture.label.LabelCapture.Feedback). You can use the default feedback, or configure your own sound or vibration. :::tip If you already have a [Feedback](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/feedback.html#class-scandit.datacapture.core.Feedback) instance implemented in your application, remove it to avoid double feedback. ::: ```js import { LabelCaptureFeedback } from "scandit-capacitor-datacapture-label"; // Get the default feedback configuration. const feedback = LabelCaptureFeedback.defaultFeedback; // Assign the feedback to the label capture mode. labelCapture.feedback = feedback; ``` :::note Audio feedback is only played if the device is not muted. ::: --- ## About Smart Label Capture import AboutLabelCapture from '../../../partials/intro/_about-smart-label-capture.mdx'; --- ## Label Definitions # Label Definitions A **Label Definition** is a configuration that defines the label, and its relevant fields, that Smart Label Capture should recognize and extract during scans. Smart Label Capture provides a [Label Definition](https://docs.scandit.com/data-capture-sdk/capacitor/label-capture/api/label-definition.html#label-definition) API, enabling you to configure and extract structured data from predefined and custom labels. This feature provides a flexible way to recognize and decode fields within a specific label layout such as price tags, VIN labels, or packaging stickers without needing to write custom code for each label type. There are two approaches to using label definitions: - [**Pre-built Labels**](#pre-built-labels) - [**Custom Labels**](#custom-labels) ## Pre-built Labels Smart Label Capture includes ready-made label definitions for common use cases. These pre-built options let you recognize and extract information from standard label types without creating custom configurations: ### Example: Price label Use `LabelDefinition.createPriceCaptureDefinition()` to create a pre-built label definition for price labels, such as those found in retail environments: ![Price Label Example](/img/slc/price-label.png) ```js import { LabelCaptureSettings, LabelDefinition } from "scandit-capacitor-datacapture-label"; // Create a pre-built price capture label definition. const priceLabel = LabelDefinition.createPriceCaptureDefinition("price-label"); // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([priceLabel], null); ``` ## Custom Labels If Smart Label Capture’s pre-built options don’t fit your needs, define a custom label instead. Custom labels can combine your own fields with any of the available pre-built ones. :::tip The following characters are recognized: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ()-./:,$¶"`. ::: ### Custom Fields There are two types of custom fields you can define: The following properties are available to configure custom fields: | Property | Required | Description | |----------|----------|-------------| | `valueRegexes` | Yes | The regex patterns that identify the target string in the scanned content. | | `anchorRegexes` | No | Used to specify keywords or phrases that help identify the context of the field. This is particularly useful when the label contains multiple fields that could match the same pattern (e.g., when both packaging and expiry dates are present). | | `symbologies` | Yes (barcode fields) | The barcode symbologies to match for barcode fields. This is important for ensuring that the field only captures data from specific barcode types, enhancing accuracy and relevance. | | `optional` | No | Whether the field is optional or mandatory. This is helpful when certain fields may not be present on every scan. | #### Example: Fish Shipping Box This example shows how to create a custom label definition for a fish shipping box, which includes fields for barcode and batch number. ![Fish Shipping Box Example](/img/slc/fish-shipping-box.png) ```js import { Symbology } from "scandit-capacitor-datacapture-barcode"; import { CustomBarcode, CustomText, LabelCaptureSettings, LabelDefinition, } from "scandit-capacitor-datacapture-label"; // Create a custom label definition for a fish shipping box. const shippingLabel = new LabelDefinition("shipping-label"); // Add a barcode field with Code 128 symbology. const barcodeField = CustomBarcode.initWithNameAndSymbology("barcode-field", Symbology.Code128); shippingLabel.addField(barcodeField); // Add a custom text field for the batch number. // Use anchorRegexes to specify keywords that help identify the field context. // Use valueRegexes to specify the expected format of the field data. const batchNumberField = new CustomText("batch-number-field"); batchNumberField.anchorRegexes = ["Batch"]; batchNumberField.valueRegexes = ["FZ\\d{5,10}"]; batchNumberField.optional = true; shippingLabel.addField(batchNumberField); // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([shippingLabel], null); ``` ### Pre-built Fields You can also build your label using pre-built fields. These common fields speed up integration because their `valueRegexes`, `anchorRegexes`, and `symbologies` are already predefined. Customization of pre-built fields is done via the `valueRegexes`, `anchorRegexes`, and `isOptional` methods, which allow you to specify the expected format of the field data. :::tip All pre-built fields come with default `valueRegexes` and `anchorRegexes` that are suitable for most use cases. **Setting either property is optional and will override the defaults**. You can set `anchorRegexes` to an empty array to remove the default anchor patterns, allowing you to rely solely on the `valueRegexes` for detection. ::: import FeatureList from '@site/src/components/FeatureList'; #### Barcode Fields #### Price and Weight Fields #### Date and Custom Text Fields #### Example: Hard disk drive label This example demonstrates how to configure a label definition for a hard disk drive (HDD) label, which typically includes common fields like serial number and part number. ![Hard Disk Drive Label Example](/img/slc/hdd-label.png) ```js import { Symbology } from "scandit-capacitor-datacapture-barcode"; import { LabelCaptureSettings, LabelDefinition, PartNumberBarcode, SerialNumberBarcode, } from "scandit-capacitor-datacapture-label"; // Create a custom label definition for an HDD label. const hddLabel = new LabelDefinition("hdd-label"); // Add a serial number barcode field. // Pre-built fields like SerialNumberBarcode have predefined valueRegexes and anchorRegexes. const serialNumberField = SerialNumberBarcode.initWithNameAndSymbology("serial-number", Symbology.Code128); hddLabel.addField(serialNumberField); // Add a part number barcode field. const partNumberField = PartNumberBarcode.initWithNameAndSymbology("part-number", Symbology.Code128); hddLabel.addField(partNumberField); // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([hddLabel], null); ``` --- ## Adding AR Overlays # Adding AR Overlays To add advanced AR overlays to a Data Capture View you can take advantage of the [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) class, which provides a ready-to-use implementation for view-based AR overlays. ## Using BarcodeBatchAdvancedOverlay As mentioned above, the advanced overlay combined with its [listener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) offers an easy way of adding augmentations to your [DataCaptureView](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). In this guide we will add a view above each barcode showing its content. First of all, create a new instance of [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) and add it to the [DataCaptureView](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). ```js const overlay = new BarcodeBatchAdvancedOverlay(barcodeBatch); view.addOverlay(overlay); ``` At this point, you have two options. - Add a [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) to the overlay. - Use the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) to specify the view, anchor and offset for each barcode. :::note The second way will take priority over the first one, which means that if a view for a barcode has been set using [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), the function [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) won’t be invoked for that specific barcode. ::: Using [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) - You need to implement [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener). This interface’s methods are invoked every time a barcode is newly tracked. - [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) asks for a view to animate on top of the barcode. Returning _null_ will show no view. - [BarcodeBatchAdvancedOverlayListener.anchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode) asks how to anchor the view to the barcode through [Anchor](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/anchor.html#enum-scandit.datacapture.core.Anchor). Be aware that it anchors the view’s center to the anchor point. To achieve anchoring the top of the view or the bottom etc. you will have to set an offset as explained in the next point. - [BarcodeBatchAdvancedOverlayListener.offsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode) asks for an offset that is applied on the already anchored view. This offset is expressed through a [PointWithUnit](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/common.html#struct-scandit.datacapture.core.PointWithUnit). ```js overlay.listener = { viewForTrackedBarcode: (overlay, trackedBarcode) => { // Create and return the view you want to show for this tracked barcode. You can also return null, to have no view for this barcode. let element = document.createElement('span'); element.innerText = trackedBarcode.barcode.data; element.style.backgroundColor = '#FFFFFFFF'; return TrackedBarcodeView.withHTMLElement(element, null); }, anchorForTrackedBarcode: (overlay, trackedBarcode) => { // As we want the view to be above the barcode, we anchor the view's center to the top-center of the barcode quadrilateral. // Use the function 'offsetForTrackedBarcode' below to adjust the position of the view by providing an offset. return Anchor.TopCenter; }, offsetForTrackedBarcode: (overlay, trackedBarcode) => { // This is the offset that will be applied to the view. // You can use .fraction to give a measure relative to the view itself, the sdk will take care of transforming this into pixel size. // We now center horizontally and move up the view to make sure it's centered and above the barcode quadrilateral by half of the view's height. return new PointWithUnit( new NumberWithUnit(0, MeasureUnit.Fraction), new NumberWithUnit(-1, MeasureUnit.Fraction) ); }, }; ``` Using the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) The function [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) gives you access to a [session](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession), which contains all added, updated and removed tracked barcodes. From here you can create the view you want to display, and then call [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), [BarcodeBatchAdvancedOverlay.setAnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode) and [BarcodeBatchAdvancedOverlay.setOffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode) ```js didUpdateSession: (barcodeBatch, session) => { session.addedTrackedBarcodes.map((trackedBarcode) => { let element = document.createElement('span'); element.innerText = trackedBarcode.barcode.data; element.style.backgroundColor = '#FFFFFFFF'; let trackedBarcodeView = TrackedBarcodeView.withHTMLElement( element, null ); window.overlay.setViewForTrackedBarcode(trackedBarcodeView, trackedBarcode); window.overlay.setAnchorForTrackedBarcode( Anchor.TopCenter, trackedBarcode ); window.overlay.setOffsetForTrackedBarcode( new PointWithUnit( new NumberWithUnit(0, MeasureUnit.Fraction), new NumberWithUnit(-1, MeasureUnit.Fraction) ), trackedBarcode ); }); }; ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan to your application. The general steps are: - Initializing the Data Capture Context - Configuring the MatrixScan mode - Using the built-in camera - Visualizing the scan process - Providing feedback - Disabling barcode tracking ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Batch Mode The main entry point for the Barcode Batch Mode is the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object. It is configured through [BarcodeBatchSettings](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) that will get informed whenever a new frame has been processed. Most of the times, you will not need to implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener), instead you will add a [BarcodeBatchBasicOverlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) and implement a [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener). For this tutorial, we will setup Barcode Batch for tracking QR codes. ```js const settings = new BarcodeBatchSettings(); settings.enableSymbology(Symbology.QR, true); ``` Next, create a [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance with the data capture context and the settings initialized in the previous steps: ```js const barcodeBatch = new BarcodeBatch(settings); DataCaptureContext.sharedInstance.addMode(barcodeBatch); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```js const cameraSettings = BarcodeBatch.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. const camera = Camera.default; if (camera != null) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js DataCaptureContext.sharedInstance.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```js camera.switchToDesiredState(FrameSourceState.On); ``` There is a separate guide for [more advanced camera functionality](advanced.md). ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js const view = DataCaptureView.forContext(DataCaptureContext.sharedInstance); view.connectToElement(htmlElement); ``` To visualize the results of Barcode Batch, first you need to add the following [overlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay): ```js const overlay = new BarcodeBatchBasicOverlay(barcodeBatch, BarcodeBatchBasicOverlayStyle.Frame); view.addOverlay(overlay); ``` Once the overlay has been added, you should implement the [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) interface. The method [BarcodeBatchBasicOverlayListener.brushForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode) is invoked every time a new tracked barcode appears and it can be used to set a [brush](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/ui/brush.html#class-scandit.datacapture.core.ui.Brush) that will be used to highlight that specific barcode in the [overlay](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay). ```js overlay.listener = { brushForTrackedBarcode: (overlay, trackedBarcode) => { // Return a custom Brush based on the tracked barcode. }, }; ``` If you would like to make the highlights tappable, you need to implement the [BarcodeBatchBasicOverlayListener.didTapTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped) method. ```js overlay.listener = { didTapTrackedBarcode: (overlay, trackedBarcode) => { // A tracked barcode was tapped. }, }; ``` ## Get Barcode Batch Feedback Barcode Batch, unlike Barcode Capture, doesn’t emit feedback (sound or vibration) when a new barcode is recognized. However, you may implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) to provide a similar experience. Below, we use the default [Feedback](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration if you want. ```js const feedback = Feedback.defaultFeedback; ``` Next, use this [feedback](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/feedback.html#class-scandit.datacapture.core.Feedback) in a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener): ```js const feedbackListener = { didUpdateSession: (barcodeBatch, session) => { if (session.addedTrackedBarcodes.length > 0) { feedback.emit(); } }, }; ``` [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) is invoked for every processed frame. The [session](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession) parameter contains information about the currently tracked barcodes, in particular, the newly recognized ones. We check if there are any and if so, we emit the feedback. As the last step, register the listener responsible for emitting the feedback with the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance. ```js barcodeBatch.addListener(feedbackListener); ``` ## Disabling Barcode Batch To disable barcode tracking set [BarcodeBatch.isEnabled](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-batch.html#property-scandit.datacapture.barcode.batch.BarcodeBatch.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off or put it in standby calling [SwitchToDesiredState](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [StandBy](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.Standby). --- ## About MatrixScan Batch # About MatrixScan Batch import AboutMatrixScan from '../../../partials/intro/_about-matrixscan.mdx' --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan AR to your application. Implementing MatrixScan AR involves two primary elements: - Barcode AR: The data capture mode that is used for scan and check functionality. - A Barcode AR View: The pre-built UI elements used to highlight items to be checked. The general steps are: - Initializing the Data Capture Context - Configuring the Barcode AR Mode - Setup the Barcode AR View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode AR Mode The main entry point for the Barcode AR Mode is the `BarcodeAr` object. You can configure the supported Symbologies through its [`BarcodeArSettings`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-ar-settings.html), and set up the list of items that you want MatrixScan AR to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```js const settings = new BarcodeArSettings(); settings.enableSymbology(Symbology.EAN13UPCA, true); ``` The create the mode with the previously created settings: ```js const mode = new BarcodeAr(settings); ``` ## Setup the `BarcodeArView` MatrixScan AR's built-in AR user interface includes buttons and overlays that guide the user through the scan and check process. By adding a [`BarcodeArView`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView), the scanning interface is added automatically to your application. The `BarcodeArView` is where you provide the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider) to supply the highlight and annotation information for the barcodes to be checked. If *null*, a default highlight is used and no annotations are provided. The `BarcodeArView` appearance can be customized through [`BarcodeArViewSettings`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-ar-view-settings.html#class-scandit.datacapture.barcode.check.ui.BarcodeArViewSettings), and the corresponding settings for your desired highlights and/or annotations, to match your application's look and feel. The following settings can be customized: * Audio and haptic feedback * Torch button visibility and its position * Switch camera button visibility and its position * Zoom control visibility and its position * The size, colors, and styles of the highlight and annotation overlays ```js const viewSettings = new BarcodeArViewSettings(); ``` Next, create a `BarcodeArView` instance with the Data Capture Context and the settings initialized in the previous step. Then connect it to an HTML element in your view hierarchy. ```js const barcodeArView = new BarcodeArView({ context: DataCaptureContext.sharedInstance, barcodeAr: mode, settings: viewSettings, }); barcodeArView.connectToElement(htmlElement); ``` ## Register the Listener Register a [BarcodeArViewUiListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-ar-view.html#interface-scandit.datacapture.barcode.check.ui.IBarcodeArViewUiListener) to be notified when a highlighted barcode is tapped. ```js barcodeArView.uiListener = { didTapHighlightForBarcode(barcodeAr, barcode, highlight) { // Handle the tapped barcode. }, }; ``` ## Start Searching As soon as everything is set up, control the [BarcodeArView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView) to start the search. ```js barcodeArView.start(); ``` --- ## About MatrixScan AR # About MatrixScan AR import AboutMatrixScanCheck from '../../../partials/intro/_about-matrixscan-ar.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Count is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Count to best fit your needs. ## Scanning Against A List There is a function to set a list of expected barcodes if you are scanning against a manifest or item list. If this is used, a progress bar is added to the UI, so you can keep track of the process while scanning. When scanning against a list, the UI will also show red icons to mark scanned barcodes that aren’t present on the list. ```js const barcodeCountCaptureListListener = { didUpdateSession: (barcodeCountCaptureList, session) => { // Handling the session }, }; const targetBarcodes = [TargetBarcode.create('data', 1)]; const barcodeCountCaptureList = BarcodeCountCaptureList.create( barcodeCountCaptureListListener, targetBarcodes ); barcodeCount.setBarcodeCountCaptureList(barcodeCountCaptureList); ``` ## Clustering import Clustering from '../../../partials/count/_clustering.mdx' ## Tote Mapping import Totes from '../../../partials/count/_tote-mapping.mdx' ## Strap Mode It can be difficult to reach the shutter button if the smart device is attached to the user’s wrist by a strap or similar. In this instance, you can enable a floating shutter button that can be positioned by the end user in a more ergonomically suitable position. ```js barcodeCountView.shouldShowFloatingShutterButton = true; ``` ## Filtering If you have several types of barcodes on your label/package, you may want to scan only one of them. In this case, you can filter the others out. This can be done by symbology, symbol count, or setting a regex. For example, you might want to scan only Code 128 barcodes and no PDF417 ones. ```js const settings = new BarcodeCountSettings(); settings.enableSymbologies(enabledSymbologies); const excludedSymbologies = [Symbology.PDF417]; const filterSettings = settings.filterSettings; filterSettings.excludedSymbologies = excludedSymbologies; ``` Or, you want to exclude all the barcodes starting with 4 numbers: ```js const settings = new BarcodeCountSettings(); const filterSettings = settings.filterSettings; filterSettings.excludedCodesRegex = '^1234.*'; ``` By default the filters applied to the relevant barcodes are transparent, but you can use [`BarcodeFilterHighlightSettings`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-filter-highlight-settings.html#barcode-filter-highlight-settings) to change the color and level of transparency. ![Different Filters in MatrixScan Count](/img/matrixscan-count/filtering_styles.png) ## Clear Screen Button There are situations in which the user may find it helpful to clean up their screen (i.e. clear all the AR overlays) but keep the list of barcodes scanned. If this is the case, you can enable the “Clear screen” button. ```js barcodeCountView.shouldShowClearHighlightsButton = true; ``` ## Customize Overlay Colors MatrixScan Count comes with recommended and user-tested AR overlays. However, if you wish to customize the overlay colors, once the overlay has been added, you can conform to the [BarcodeCountViewListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view-listener.html#interface-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener) interface. The methods [BarcodeCountViewListener.brushForRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForRecognizedBarcode) and [BarcodeCountViewListener.brushForUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForUnrecognizedBarcode) are invoked every time a new recognized or unrecognized barcode appears. These can be used to set a brush that will be used to highlight that specific barcode in the overlay. Keep in mind that these methods are relevant only when using the style [BarcodeCountViewStyle.Dot](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view.html#value-scandit.datacapture.barcode.count.ui.BarcodeCountViewStyle.Dot). ```js const viewListener = { brushForRecognizedBarcode(view, trackedBarcode) { // Return a custom brush }, brushForUnrecognizedBarcode(view, trackedBarcode) { // Return a custom brush }, }; barcodeCountView.listener = viewListener; ``` ## Notifications If you want to be notified when a user taps on an overlay, you need to implement the[BarcodeCountViewListener.didTapRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnRecognizedBarcodeTapped) and [BarcodeCountViewListener.didTapUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped) methods. ```js const viewListener = { didTapRecognizedBarcode: (view, trackedBarcode) => { console.log( `Tapped recognized barcode with data ${trackedBarcode.barcode.data}` ); }, didTapUnrecognizedBarcode: (view, trackedBarcode) => { console.log( `Tapped unrecognized barcode with data ${trackedBarcode.barcode.data}` ); }, }; barcodeCountView.listener = viewListener; ``` ## Disable UI Elements The UI is an integral part of MatrixScan Count and we do not recommend that you use it without it. However, if you wish to disable UI elements you can do it as follows. Disable buttons: ```js barcodeCountView.shouldShowListButton = false; barcodeCountView.shouldShowExitButton = false; barcodeCountView.shouldShowShutterButton = false; ``` Disable feedback and hints: ```js barcodeCountView.shouldShowUserGuidanceView = false; barcodeCountView.shouldShowHints = false; ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Count to your application. The general steps are: 1. Initialize the Data Capture Context 2. Configure the Barcode Count Mode 3. Obtain camera instance and set frame source used 4. Register the listener to be informed when scanned phase is over 5. Set capture view and AR overlays 6. Set up the camera so that it switches on when you are in scanning view 7. Store and retrieve scanned barcodes 8. Reset Barcode Count mode 9. List and Exit callbacks ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure The Barcode Count Mode The main entry point for the Barcode Count Mode is the [BarcodeCount](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) object. It is configured through [BarcodeCountSettings](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count-settings.html#class-scandit.datacapture.barcode.count.BarcodeCountSettings) and allows you to register one or more listeners that are informed whenever a scan phase has finished. For this tutorial, we will set up Barcode Count for tracking EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```js const settings = new BarcodeCountSettings(); settings.enableSymbologies([Symbology.EAN13UPCA]); ``` If you are sure that your environment will only have unique barcodes (i.e. no duplicated values), you can also enable [BarcodeCountSettings.expectsOnlyUniqueBarcodes](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count-settings.html#property-scandit.datacapture.barcode.count.BarcodeCountSettings.ExpectsOnlyUniqueBarcodes). This option improves scanning performance as long as you are sure that no duplicates will be present. Next, create a [BarcodeCount](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) instance with the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) and the settings initialized in the previous step: ```js const barcodeCount = new BarcodeCount(settings); DataCaptureContext.sharedInstance.addMode(barcodeCount); ``` ## Obtain Camera Instance And Set Frame Source Used Our recommended camera settings should be used to achieve the best performance and user experience. The following couple of lines show how to get the recommended settings for MatrixScan Count and create the camera from it: ```js const cameraSettings = BarcodeCount.createRecommendedCameraSettings(); const camera = Camera.default; if (camera != null) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js DataCaptureContext.sharedInstance.setFrameSource(camera); ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [BarcodeCountListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) interface and register the listener. [BarcodeCountListener.didScan()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan) is called when the scan phase has finished and results can be retrieved from [BarcodeCountSession](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession). ## Set Capture View And AR Overlays MatrixScan Count’s built-in AR user interface includes buttons and overlays that guide the user through the capturing process. By adding a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) to your view hierarchy: ```js const barcodeCountView = BarcodeCountView.forContextWithMode(DataCaptureContext.sharedInstance, barcodeCount); barcodeCountView.connectToElement(htmlElement); ``` ## Set Up The Camera So That It Switches On When You Are In Scanning View The camera is not automatically turned on when you are in a scanning view. You need to set up the camera so that it switches on when needed and it switches off when not needed anymore. Similarly [BarcodeCount](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) should also be enabled and disabled. For instance, you should switch off the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is not visible anymore (including when the app goes in the background), similarly you want to switch on the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is visible (including when the app goes to the foreground). One way to achieve this is the following: ```js import { App } from '@capacitor/app'; App.addListener('appStateChange', ({ isActive }) => { if (isActive) { camera.switchToDesiredState(FrameSourceState.On); } else { camera.switchToDesiredState(FrameSourceState.Off); } }); ``` ## Store And Retrieve Scanned Barcodes The values captured as part of the scanning process are part of the [session](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession), and the session is not accessible outside [BarcodeCountListener.didScan()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan). Therefore, we recommend that you store the values to present a list, for example when the user taps the list icon. To do this, make a copy of [BarcodeCountSession.recognizedBarcodes](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count-session.html#property-scandit.datacapture.barcode.count.BarcodeCountSession.RecognizedBarcodes): ```js const listener = { didScan: (barcodeCapture, session, getFrameData) => { const allRecognizedBarcodes = session.recognizedBarcodes; // Handle barcodes }, }; barcodeCount.addListener(listener); ``` ## Reset Barcode Count Mode When the scanning process is over, you need to reset the mode to make it ready for the next process. This clears the list of barcodes scanned and all the AR overlays. To reset Barcode Count’s scanning process, you need to call the [BarcodeCount.reset()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-count.html#method-scandit.datacapture.barcode.count.BarcodeCount.Reset) method. ```js barcodeCount.reset(); ``` ## List And Exit Callbacks The UI includes two icons (buttons) named “List” and “Exit”. The SDK provides the callbacks so you can add the desired action when those icons are tapped by the user. ```js const viewUiListener = { didTapListButton: (view) => { // Show the current progress but the order is not completed }, didTapExitButton: (view) => { // The order is completed }, }; barcodeCountView.uiListener = viewUiListener; ``` --- ## About MatrixScan Count # About MatrixScan Count import AboutMatrixScanCount from '../../../partials/intro/_about-matrixscan-count.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Find is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Find to best fit your needs. ## Set up a listener on the BarcodeFind mode You may want more fine-grained knowledge over the different events happening during the life of the BarcodeFind mode, such as when the search starts, pauses and stops. To do this, you can directly register a [BarcodeFindListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-find-listener.html#interface-scandit.datacapture.barcode.find.IBarcodeFindListener) on the mode itself. Be aware that these listeners will be called from a background thread. ```js mode.addListener({ didStartSearch() { // The mode was started }, didPauseSearch(foundItems) { // The mode was paused }, didStopSearch(foundItems) { // The mode was stopped after the finish button was clicked }, }); ``` ## UI configuration The [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) will by default show a set of UI elements, which can be optionally hidden: - A play/pause button - A finish button - A searched items carousel - Guidance hints There is also a progress bar but this is hidden by default. Each of these elements can be shown or hidden at will. ```js barcodeFindView.shouldShowCarousel = false; barcodeFindView.shouldShowProgressBar = true; // … ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Find to your application. Implementing MatrixScan Find involves two primary elements: - Barcode Find: The data capture mode that is used for search and find functionality. - A Barcode Find View: The pre-built UI elements used to highlight found items. The general steps are: 1. Initialize the Data Capture Context. 2. Configure the Barcode Find Mode. 3. Setup the BarcodeFindView. 4. Register a listener to be notified with found items 5. Start searching ## Initialize the Data Capture Context The first step to add find capabilities to your application is to initialize the [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Find Mode The main entry point for the Barcode Find Mode is the [BarcodeFind](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind) object. You can configure the supported Symbologies through its [BarcodeFindSettings](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-find-settings.html#class-scandit.datacapture.barcode.find.BarcodeFindSettings), and set up the list of items that you want MatrixScan Find to highlight (e.g. a list of products). For this tutorial, we will set up Barcode Find for tracking EAN13 codes. Change this to the correct symbologies for your use case (e.g. Code 128, Code 39…). First create the settings: ```js const settings = new BarcodeFindSettings(); settings.enableSymbology(Symbology.EAN13UPCA, true); ``` Then you have to create the list of items that will be actively searched for. In this tutorial, let’s look up two items based on their EAN13 codes. We will attach to the first item some optional information that can be used by the BarcodeFindView to display extra information. ```js const items = [ new BarcodeFindItem(new BarcodeFindItemSearchOptions("9783598215438"), new BarcodeFindItemContent("Mini Screwdriver Set", "(6-Piece)", null)), new BarcodeFindItem(new BarcodeFindItemSearchOptions("9783598215414"), null) // Item information is optional, used for display only ] ``` Create the mode with the previously created settings and set the items: ```js const mode = new BarcodeFind(settings); mode.setItemList(items); ``` ## Setup the BarcodeFindView MatrixScan Find’s built-in AR user interface includes buttons and overlays that guide the user through the searching process. By adding a [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView), the scanning interface (camera preview and searching UI elements) will be added automatically to your application. The BarcodeFindView appearance can be customized through [BarcodeFindViewSettings](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-find-view-settings.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindViewSettings): - Colors of dots in augmented reality overlay - Enable sound and haptic alerts ```js const viewSettings = new BarcodeFindViewSettings(); ``` Construct a new BarcodeFindView. The BarcodeFindView is automatically added to the provided parent view. ```js const barcodeFindView = new BarcodeFindView({ context: DataCaptureContext.sharedInstance, barcodeFind: mode, viewSettings }); barcodeFindView.connectToElement(htmlElement); ``` ## Register a listener to be notified with found items The BarcodeFindView displays next to its shutter button a handy “finish” button. Register a [BarcodeFindViewUiListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-find-view.html#interface-scandit.datacapture.barcode.find.ui.IBarcodeFindViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```js barcodeFindView.barcodeFindViewUiListener = { didTapFinishButton(foundItems) { // This method is called when the user presses the // finish button. It returns the list of all items that were found during // the session. }, }; ``` ## Start searching As soon as everything is set up, control the [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) to start the search. ```js barcodeFindView.startSearching(); ``` This is the equivalent of pressing the “Play” button programmatically. It will start the search process, turn on the camera and hide the item carousel. --- ## About MatrixScan Find # About MatrixScan Find import AboutFind from '../../../partials/intro/_about-matrixscan-find.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Pick is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Pick to best fit your needs. ## BarcodePick Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodePick` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodePickViewListener`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-pick-view.html#interface-scandit.datacapture.barcode.pick.IBarcodePickViewListener) on the view itself, keeping in mind that these listeners are called from a background thread. ```js const viewListener = { didStartScanning(view) { // The view started scanning }, didFreezeScanning(view) { // The view was frozen }, didPauseScanning(view) { // The view was paused }, didStopScanning(view) { // The view stopped scanning }, }; barcodePickView.addListener(viewListener); ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Pick to your application. Implementing MatrixScan Pick involves two primary elements: - Barcode Pick: The data capture mode that is used for scan and pick functionality. - A Barcode Pick View: The pre-built UI elements used to highlight items to be picked. The general steps are: - Initializing the Data Capture Context - Configuring the Barcode Pick Mode - Setup the Barcode Pick View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the Data Capture Context with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Pick Mode The main entry point for the Barcode Pick Mode is the `BarcodePick` object. You can configure the supported Symbologies through its [`BarcodePickSettings`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-pick-settings.html), and set up the list of items that you want MatrixScan Pick to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```js const settings = new BarcodePickSettings(); settings.enableSymbology(Symbology.EAN13UPCA, true); ``` Then you have to create the list of items that will be picked and quantity to be picked for each item. ```js const items = [ new BarcodePickProduct(new BarcodePickProductIdentifier("9783598215438"), new BarcodePickProductQuantityToPick(3)), new BarcodePickProduct(new BarcodePickProductIdentifier("9783598215414"), new BarcodePickProductQuantityToPick(3)), ]; ``` Create the mode with the previously created settings: ```js const mode = new BarcodePick(settings); ``` ## Setup the `BarcodePickView` MatrixScan Pick’s built-in AR user interface includes buttons and overlays that guide the user through the scan and pick process. By adding a [`BarcodePickView`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-pick-view.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickView), the scanning interface is added automatically to your application. The `BarcodePickView` appearance can be customized through [`BarcodePickViewSettings`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-pick-view-settings.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickViewSettings) to match your application’s look and feel. The following settings can be customized: * Colors of dots in augmented reality overlay * Enable sound and haptic alerts * Guidelines text * Showing hints * Finish button * Pause button * Zoom button * Loading Dialog ```js const viewSettings = new BarcodePickViewSettings(); // ... ``` Construct a new `BarcodePickView`. The `BarcodePickView` will be attached to the HTMLElement provided in the ConnectToElement function. ```js const barcodePickView = new BarcodePickView({ context: DataCaptureContext.sharedInstance, barcodePick: mode, settings: viewSettings }); // Connect the view to the HTML element, so it can fill up its size and follow its position. barcodePickView.connectToElement(document.getElementById('html-element-id')); ``` ## Register the Listener The `BarcodePickView` displays a **Finish** button next to its shutter button. Register a [BarcodePickViewUiListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/barcode-pick-view.html#interface-scandit.datacapture.barcode.pick.ui.IBarcodePickViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```js barcodePickView.uiListener = { didTapFinishButton(foundItems) { // This method is called when the user presses the finish button. // It returns the list of all items that were found during the session. }, }; ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `BarcodePickView.start()`. ```js barcodePickView.start(); ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Pick # About MatrixScan Pick MatrixScan Pick is a pre-built UI that uses augmented reality overlays to highlight specific items that need to be picked. Whereas MatrixScan AR is fully customizable, MatrixScan Pick is a pre-built solution that allows you to add a scan and pick experience with augmented reality to an existing native app, with just a few lines of code. MatrixScan Pick is implemented through functionality provided by [`BarcodePick`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/barcode-pick.html). ## UI Overview * MatrixScan Pick is inspired by the familiar paradigm of a camera, including a shutter button that the user operates in order start and pause the scanning view. The Finish button is used at any time to exit the workflow. * It highlights items with obvious and colorful visual dots on screen. * When paused, MatrixScan Pick freezes the display at the last view, even if the device is moved. The Play button transitions back to the live view. * Textual guidance is displayed from the beginning of the session and as the workflow progresses, informing of the user of changes in item status (i.e. Detected, Ignored, To-Pick, or Picked). * Status icons can be defined to provide further information to users for a given barcode. In the live view, the icons are displayed but not tappable. In the frozen view, the status icons can be tapped and expanded to provide additional textual information. * The Quick Start Guide takes you through the process to install the full UI. However, you can then customize it by choosing to remove any elements on the screen except for the AR overlays. This allows you to create custom UIs suitable for your own workflows. ## Supported Symbologies MatrixScan Find supports all [symbologies](../barcode-symbologies.mdx) **except** DotCode, MaxiCode and postal codes (KIX, RM4SCC). If you are not familiar with the symbologies that are relevant for your use case, you can use capture presets that are tailored for different verticals (e.g. retail, logistics, etc.). --- ## Get Started # Get Started The parser parses data strings, e.g. as found in barcodes, into a set of key-value mappings. In this guide, you will know briefly how to use a parser and what types of parser are currently supported by Scandit. These data formats are supported: [Health Industry Bar Code (HIBC)](https://docs.scandit.com/data-capture-sdk/capacitor/parser/hibc.html), [GS1 Application Identifier (https://docs.scandit.com/data-capture-sdk/capacitor/parser/AI) system](https://docs.scandit.com/data-capture-sdk/capacitor/parser/gs1ai.html) and [Swiss QR Codes](https://docs.scandit.com/data-capture-sdk/capacitor/parser/swissqr.html), [VIN Vehicle Identification Number](https://docs.scandit.com/data-capture-sdk/capacitor/parser/vin.html), [IATA Bar Coded Boarding Pass (BCBP)](https://docs.scandit.com/data-capture-sdk/capacitor/parser/iata-bcbp.html), [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/capacitor/parser/epc.html). More data formats will be added in future releases. Please contact us if the data format you are using is not yet supported, or you want to use the parser on a currently unsupported platform. ## Format-Specific Documentation - [Supported Data Formats](https://docs.scandit.com/data-capture-sdk/capacitor/parser/formats.html) - [HIBC](https://docs.scandit.com/data-capture-sdk/capacitor/parser/hibc.html) - [GS1 AI](https://docs.scandit.com/data-capture-sdk/capacitor/parser/gs1ai.html) - [GS1 Digital Link](https://docs.scandit.com/data-capture-sdk/capacitor/parser/gs1-digital-link.html) - [Swiss QR](https://docs.scandit.com/data-capture-sdk/capacitor/parser/swissqr.html) - [VIN](https://docs.scandit.com/data-capture-sdk/capacitor/parser/vin.html) - [IATA BCBP](https://docs.scandit.com/data-capture-sdk/capacitor/parser/iata-bcbp.html) - [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/capacitor/parser/epc.html) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: First of all, include the ScanditParser library and its dependencies to your project, if any. ## Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### New Features #### Barcode * Added the SelectionMode API to replace the SparkScan target-mode APIs and `ScanIntention.smartSelection`: Set `selectionMode` (off/on/auto) in the `BarcodeCaptureSettings` and `SparkScanSettings` to control whether an aimed-at barcode is scanned automatically or requires explicit selection. #### Id * Added Irish Garda Age Card as `RegionSpecificSubtype.IrelandAgeCard`. * Added double-sided support for the Oman residence card. * Added single-sided support for extraction of issue date and birth date from the 2025 NYC Municipal ID. #### Smart Label Capture * Extended VIN label capture to also scan Code 128 barcodes (in addition to QR, Code 39, and Data Matrix) via `createVinLabelDefinition()`. * Extended LabelCapture to accept label definitions where both "barcode" and "text" field types use the "semantics" feature simultaneously; previously this was restricted to only one field type at a time. ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Smart Label Capture * Improved Receipt Scanning efficiency by optimizing receipt image processing before extraction. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. * Updated `SymbologyDescription.forIdentifier` to return `null` for unrecognized identifiers (e.g. `"EAN-8"` instead of `"ean8"`); previously such input was silently mapped to `Codabar`. ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in item-based scanning. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Id * Fixed an issue where cropped document images were rotated when Frame Image was also enabled. * Corrected the orientation of cropped Visa document images that were being rotated incorrectly when scanned using a single-frame image source. * Fixed parser handling of non-standard Surrey BC AAMVA barcodes that were incorrectly returning "Invalid Format". #### Smart Label Capture * Fixed a memory leak in LabelCapture. * Fixed a bug where setting `valueRegexes` or `anchorRegexes` to null in frameworks was incorrectly treated the same as setting them to an empty list; they now correctly fall back to the definition type's defaults. #### Core * Fixed SPM resolution failure in Capacitor 8 / Xcode 26 projects (CapApp-SPM) caused by an invalid Package.swift header and an outdated capacitor-swift-pm version pin. * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a crash when the `DataCaptureContext` singleton was initialized more than once. ### Deprecations #### Barcode * The SparkScan target-mode APIs and `ScanIntention.smartSelection` are deprecated in favour of selectionMode. ## 8.4.1 **Released**: June 23, 2026 ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in SparkScan when using the item-based API. #### Id * Fixed an issue where cropped document images were rotated when they are recovered using the getFrame API. * Resolved a duplicate Objective-C class registration that could trigger spurious casting failures or crashes when an app links both ScanditCaptureCore and ScanditIdCapture. ## 8.4.0 **Released**: May 18, 2026 ### New Features #### Barcode * Added `dotRadius` property to `BarcodeBatchBasicOverlay` to allow customizing the size of dots when using the Dot overlay style. * Added custom view support for barcode pick highlighting in JavaScript frameworks. * Added support for PDF417 in the Barcode Generator. #### Id * Added support for reading the vehicle table on the back of New Zealand driving licences, with the latest expiry date returned; supported vehicle classes are 1–6, including L=learner and R=restricted variants. * Added support for new versions of USA, California – Driver's License; USA, North Carolina – Driver's License; USA, Texas – Driver's License; and USA, Oklahoma – Driver's License. #### Core * Redesigned `ZoomSwitchControl` to support multiple configurable zoom levels; the control now displays as a compact button that expands to show all available zoom levels, automatically filtered to those supported by the device hardware. * Added a new `PinchToZoom` gesture. ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. #### Core * Updated mbedtls from version 3.6.5 to 3.6.6. ### Bug Fixes #### Barcode * Fixed an issue in `BarcodeCount` where the floating shutter button was not visible after setting `shouldShowFloatingShutterButton` to `true`. * Fixed an issue preventing `BarcodeFind` from finding binary barcodes. * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. * Fixed an issue where `BarcodeCountView` would display incorrectly after rotating the device when a sibling view was present in the same parent view. * Fixed an unnecessary second scan callback that occurs after freezing barcode recognition. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed an issue where the Smart Scan Selection aimer would become too small when scan-area margins restricted the visible scan area; the aimer is now sized relative to the view, keeping a consistent on-screen size regardless of margins. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. #### Id * Fixed an issue where the US Permanent Residence Card was not processed through the VizMrz flow. * Fixed an issue where AAMVA verification was being performed even when no AAMVA document types were enabled in the accepted documents. #### Smart Label Capture * Fixed a memory leak in LabelCapture * Fixed an issue where the validation flow viewfinder was not displayed. * Fixed a race condition in the validation flow. * Fixed a bug where the label capture validation flow overlay sometimes did not reflect label capture settings when reused. * Fixed a bug that caused error messages in `DataCaptureView` to be rendered partially out-of-view. * Fixed a rare race condition in Label Capture. * Added `.asDate()` support to `ExpiryDate` and `PackingDate` label fields when the text is provided as manual input or as an Adaptive-Recognition-Engine response. * Fixed a bug where the receipt scanning overlay and validation flow overlay could not be used on the same LabelCapture mode instance. #### Core * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. * Fixed a rare crash when opening the camera. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed custom sound not working in Barcode Find on Android. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. * Fixed a rare crash when starting camera capture while under memory pressure. ## 8.3.1 **Released**: April 14, 2026 ### Bug Fixes #### Smart Label Capture * Fixed the validation flow to accept dates in more formats when manually entered * Fixed a race condition in the validation flow ## 8.3.0 **Released**: March 26, 2026 ### New Features #### Barcode * Added support for composite codes in SparkScan #### Id * Added support for OCR scanning of the 2026 version of Victoria mobile driver licenses * Added IdCaptureSettings.anonymizeDefaultFields setting that controls whether the SDK applies default anonymization rules for specific document types and regions #### Smart Label Capture * Fixed a rare race condition #### Core * Added Camera-related APIs for macro mode, torch, accessibility hints, as well as ImageBuffer and Timestamp for FrameData. * Added shouldShowZoomNotification and setProperty to DataCaptureView * Added new SparkScan APIs related to feedback, scanning mode change, and periscope mode. * Added BarcodeFilterSettings public constructor and exposed excludedSymbolCounts property for JavaScript frameworks * Added BarcodeCount-related APIs for BarcodeCountNotInListActionSettings, BarcodeCountToolbarSettings, BarcodeCountMappingFlowSettings, status mode and accessibility properties on BarcodeCountView, BarcodeCountStatusProvider with status items and callbacks, cluster support, capture list completion listener, and session update listener * Added moduleCountX and moduleCountY to Barcode API ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Improved speed of MatrixScan Count scanning phase for mid- and high-end devices ### Bug Fixes #### Barcode * Fixed an issue in BarcodeCount where the floating shutter button was not visible after setting shouldShowFloatingShutterButton to true. * Fixed a bug that was causing BarcodeFind to render barcodes filtered out by the Transformer as if they were valid targets. * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. #### Id * Fixed BarcodeDictionary anonymization setting for iOS and Web * Fixed support for UAE Esaad card * Sanitized name fields on ACT driver license to split FullName and populate first and last name properties * Added support for scanning MRZ from the back of Argentinian DN when using `FullDocumentScanner` * Fixed misplaced MRZ anonymization on FullFrame images. #### Smart Label Capture * Fixed an issue in the `LabelCaptureValidationFlowOverlay` when using it with Jetpack Compose that caused focus loss when opening the keyboard * Added `LabelCaptureValidationFlowOverlay.ShouldHandleKeyboardInsetsInternally` for cases when customers don't want to follow official Android edge-to-edge and inset guidelines #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.2.1 **Released**: March 5, 2026 ### Bug Fixes #### Id * Sanitized name fields on ACT DL. Splits FullName to populate first and last name properties #### Smart Label Capture * Fixed LabelCaptureValidationFlowOverlay possible issue with Jetpack Compose that caused focus loss when opening the keyboard * Added LabelCaptureValidationFlowOverlay::ShouldHandleKeyboardInsetsInternally in case customers don't want to follow official Android guidelines for edge-to-edge and insets * Fixed a rare race condition ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Barcode * Added new getFeedbackForScannedItem method to SparkScanFeedbackDelegate * Added BarcodeArResponsiveAnnotation API * Added BarcodeAr API to Capacitor * Added some missing BarcodePick APIs to React-Native, Capacitor and Cordova #### Smart Label Capture * The Validation Flow, our ready‑to‑use workflow in Smart Label Capture for capturing and validating label data with minimal code, now features a completely redesigned user interface. The update improves ergonomics through a simplified API and highly requested customization options, making Smart Label Capture more intuitive and significantly reducing integration and customization effort across a wider range of use cases * Smart Label Capture now supports Receipt Scanning Capture. The feature is available in beta (contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out). * Added `getFrameData` to `didUpdateSession` of the LabelCaptureListener #### Core * Added Electronic Product Code (EPC) data format * Added support for Capacitor 8 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes * Barcode Generator: Improved DataMatrix encoding efficiency, which depending on input data may result in smaller generated codes ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed BarcodeCount Scan Preview issues including: fixed an issue where preview barcodes were used to populate the scanning list, the correct feedback is played when a barcode not in list is scanned, fixed an issue where scanning was not possible after the app was put in background, and corrected highlight orientation in landscape * Added cameraStateOnStop property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed an issue where the successful hint in BarcodeFind is not displayed * Fixed the missing found item icon in the MatrixScan Find carousel #### Id * Fixed an issue affecting MRZ scanning performance when using the user facing camera in portrait mode on Android * Fixed a memory issue leading to a persistent black screen during ID Capture startup * Treated Puerto Rico driver licenses as AAMVA to enforce barcode capture with FullScanner * Fixed a bug that would cause Canada Northwest Territories driver license scans to be incomplete #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed an issue where some LabelCapture fields were being returned incorrectly on TS frameworks * Fixed a crash in the DataCaptureView overlay management that could occur during rapid view updates. ### Deprecations #### Smart Label Capture * Deprecated some LabelCaptureValidationFlowSetting APIs: requiredFieldErrorText, missingFieldsHintText, manualInputButtonText, as those don't make sense anymore with the redesign of Validation Flow in 8.2 ## 8.1.5 **Released**: June 10, 2026 ### Bug Fixes #### Barcode * Fixed a memory leak in item-based scanning. #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a rare native crash (SIGABRT in BitTube::recvObjects) that could occur on Android during camera preview rendering. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. #### Core * Fixed a rare issue that was causing a crash when the app moved to the background. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed crashes caused by RuntimeExceptions thrown by OEM camera code that are not part of the standard Android Camera API contract; these exceptions are now caught and logged instead of crashing. ## 8.1.3 **Released**: March 25, 2026 ### Bug Fixes #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.1.2 **Released**: March 9, 2026 ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session #### Smart Label Capture * Fixed a rare race condition ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Id * Fixed a memory issue leading to a persistent black screen during ID Capture startup #### Core * Fixed a crash in the DataCaptureView overlay management that could occur during rapid view updates * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Smart Scan Selection is now available in Barcode Capture. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * [SparkScan](/sdks/capacitor/sparkscan/intro.md) is not limited to only barcodes anymore, but can also scan items - in other words any combinations of barcodes and text present on a target to be scanned. The feature is available in beta at the moment, please contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out. * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. #### Id * Added NationalityISO property that maps results from Nationality field to country ISO code * Added RejectionDiagnosticJSON property to CapturedId to report debug info during Timeout rejections * Added support for new California DL, new South Carolina DL, Arizona Medical Marijuana Card, Kuwait Civil card, and new Texas DL * Our SDK can now scan the following documents both in single-side and double-side mode: - All Mexican DLs - Mexican Voter Cards #### Core * Added webViewContentOnTop to DataCaptureView so hybrid apps can place HTML overlays above the camera preview without sacrificing native gestures. Default behaviour stays unchanged; when you enable the property, the bridge now mirrors Android and iOS touch routing—JS UI elements receive taps first, and any unhandled touch paths through to the native DataCaptureView. Improved resilience: both platforms fall back automatically if the WebView can't evaluate the hit-test logic, preventing stalled gestures even under heavy load. ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the [“strict" symbology extension](../symbology-properties#symbology-extension-descriptions) #### Smart Label Capture * Incremental improvements in accuracy across all use-cases for the OCR model powering Smart Label Capture. ### Behavioral Changes #### Barcode * Enabling the [“ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 (“Missing Resource”) #### Smart Label Capture * Validation Flow: Manually input values for barcodes will go through a stricter validation. Some values may no longer be accepted if they do not match the symbology specs for the symbology’s definition ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Fixed a bug in the default color of BarcodeCapture highlights * Fixed an issue where popover annotations with HIGHLIGHT_TAP_AND_BARCODE_SCAN trigger could not be opened again * Fixed an issue in BarcodeSequence where camera would not be ON in portrait * Fixed an issue where SparkScan mini preview would sometimes stay in regular when entering target mode * Fixed the app becoming unresponsive after being in the background for extended periods * Added the `cameraStateOnStop` property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed an issue where the successful notification in BarcodeFind was not displayed #### Id * Fixed an issue where front expiry date anonymization rectangle is erroneously drawn on front and back * Fixed a bug that prevented VizResult anonymization of the following fields: additionalAddressInformation, bloodType, employer, fathersName, issuingAuthority, maritalStatus, mothersName, placeOfBirth, profession, race, residentialStatus * Fixed a bug concerning return complete instead of cropped images on the back of EU driving licenses #### Smart Label Capture * Fixed an issue where LabelCapture fields would return default data in some frameworks #### Core * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only * Fixed an issue where barcode scanning would permanently stop after the app returned from background, particularly when camera permission dialogs were shown during initialization ## 8.0.1 **Released**: January 14, 2026 ### Bug Fixes #### Barcode * Fixed an issue where the successful hint in BarcodeFind was not displayed * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. #### Core * The Capacitor Kotlin plugin version used is now `1.9.25`, enabling support for projects using Capacitor 7. #### Barcode * Updated the Gradle version for all sample applications to 8.14.3. * `BarcodeBatchBasicOverlay` and `BarcodeBatchBasicOverlayListener` now allow for nullable brushes. #### Smart Label Capture * [Smart Label Capture](/sdks/capacitor/label-capture/intro.md) is now available for Capacitor. It enables the capture of any label, regardless of its layout or format, and extracts the relevant information automatically. This is achieved through a combination of AI-based text recognition and barcode scanning, allowing users to capture all necessary data in a single scan. Smart Label Capture is ideal for applications such as inventory management, asset tracking, and logistics, where labels can vary widely in design and content. * We’re introducing an enhancement that makes Smart Label Capture more robust and scalable by complementing its on-device model with a larger, more capable model. When the on-device model can’t capture certain labels, the SDK automatically escalates to this enhancement to handle complex or unforeseen cases with high accuracy and reliability. This capability is currently available in `beta`. If you’re interested in trying it, please contact Scandit Support. For configuration details, see `labelDefinition.adaptiveRecognitionEngine`. #### ID * Added `ElementsToRetain` to `MobileDocumentScanner`: The set of data elements that the application intends to retain from scanned mobile documents. This information is used to set the `IntentToRetain` flag in ISO 18013-5 mdoc requests, which is required for legal compliance with data protection standards. An empty set indicates no elements will be retained, and `IntentToRetain` will be set to `false` for all fields. * ID Capture now supports full-frame anonymization. * The result of `decodeMobileDriverLicenseViz`, which is currently returned as part of the `VizResult` within `CapturedId`, will now be provided through a new field named `mobileDocumentOcr`. * Added `CapturedId::isCitizenPassport`, which indicates whether the passport was issued to a citizen of the issuing country. Returns `false` for travel documents such as refugee, stateless, or alien passports, and for any passports issued by organizations rather than states. * The following Chinese travel permits now extract VIZ + MIZ data during double-sided scanning flows: * CT - Taiwan Residents Mainland Travel Permit * W - Mainland Residents Exit-Entry Permit to and from Hong Kong and Macao * CD - Mainland Residents Entry-Exit Permit to and from Taiwan ### Behavioral Changes #### Barcode * Symbology `RM4SCC` has been renamed to `ROYAL_MAIL_4STATE`. * Changed the default highlight brush in SparkScan and Barcode Capture. #### ID * The configuration for the following documents has been changed as detailed below: * Australian mobile driver licenses (mDL) are now treated as normal documents, with no separate mode. * US Green Cards are now treated as residence permits. * Removed the deprecated API `DateResult::toDate`. Use `DateResult::toLocalDate` or `DateResult::toUtcDate` instead. * `fullName` now an optional field on all `IdCapture` result types and `capturedMrz` now an optional field on `MrzResult`. ### Bug Fixes #### ID * Fixed a bug that could get the scanner stuck when scanning a US passport card. ### Deprecations #### Core * `VideoResolution::Auto` is now deprecated. Please use the capture mode's `recommendedCameraSettings` for the best results. ## 7.6.7 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/capacitor/release-notes) --- ## Advanced Configurations # Advanced Configurations SparkScan is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are some cases where you might want to customize the behavior of SparkScan. This guide will show you how to add additional capabilities and further customize SparkScan to best fit your needs. ## Advanced Capabilities ### Hardware Button Control Allowing the end user to control the scanner with hardware buttons can be useful if your users typically wear gloves. It can also improve ergonomics in some workflows. SparkScan offers a built-in API to let you do this via [`SparkScanViewSettings.hardwareTriggerEnabled`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled). ### Trigger Error State You may want to introduce logic in your app to show an error message when scanning specific barcodes (e.g. barcodes already added to the list, barcodes from the wrong lot etc.). SparkScan offers a built-in error state you can easily set to trigger an error feedback prompt to the user. You will be able to customize: - The text message - The timeout of the error message: the scanner will be paused for the specified amount of time, but the user can quickly restart the scanning process by tapping the trigger button. :::tip A high timeout (>10s) typically requires the users to interact with the UI to start scanning again. This is a good choice when you want to interrupt the scanning workflow (e.g. because a wrong barcode is scanned and some actions need to be performed). A small timeout (\ { if (isValidBarcode(barcode)) { return new SparkScanBarcodeSuccessFeedback(); } else { return new SparkScanBarcodeErrorFeedback( 'This code should not have been scanned', 60 * 1000, Color.fromHex('#FF0000'), new Brush(Color.fromHex('#FF0000'), Color.fromHex('#FF0000'), 1), ); } }, }; ``` You can have different error states triggered by different logic conditions. For example you can trigger an error state when a wrong barcode is scanned, and another one when a duplicate barcode is scanned. These errors can show different colors and have different timeouts. This error state for a code that should not have been scanned. This error state for a code that has been scanned more than once. ### Reject Barcodes To prevent scanning unwanted barcodes (like those already listed or from incorrect lots), use SparkScan’s built-in error state. Setting the [`SparkScanBarcodeErrorFeedback.resumeCapturingDelay`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/spark-scan-barcode-feedback.html#property-scandit.datacapture.barcode.spark.feedback.Error.ResumeCapturingDelay) parameter to 0 allows the user to continue scanning immediately without pausing on rejected codes. ## UI Customization :::tip Please refer to [SparkScanView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) for the full list of parameters. ::: import Customization from '../../../partials/advanced/_sparkscan-customization.mdx'; ## Workflow Options This section explains all the available options to configure SparkScan to best fit your case, in case you found something that didn't work well in the default configuration (that remains our recommended option). Developers can set a combination of scanning mode, scanning behavior and camera preview behavior - defining the initial state of the scanner. This can be done by setting the default scanning mode (SDCSparkScanViewSettings.defaultScanningMode). This combination allows for flexible configurations to suit different scanning needs. ### Scanning Mode The scanning mode determines the programmatic presence of an aimer in the preview to help with precision scanning. | Mode | Description | | ----------- | --------------------------------------------------- | | **Default** | Generally recommended. This mode will display a small camera preview to aid with aiming. The preview size and zoom level can be adjusted as needed. User can aim easily at the intended barcode. | | **Target** | This mode will always add an aimer to the camera preview to precisely select the barcode to scan. This is recommended only when selecting among many close barcodes is the common task. | :::tip Even in the *Default* mode, SparkScan will automatically show an aimer when multiple barcodes are present in the view and no clear intention from the user to scan a single one is recorded ([`SDCSparkScanSettings.ScanIntention`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/spark-scan-settings.html#property-scandit.datacapture.barcode.spark.SparkScanSettings.ScanIntention)). Enabling the *Target* mode will simply force this "precision selection" state to be on at all time. ::: ### Scanning Behavior The scanning behavior determines how barcodes are scanned - one at a time or continuously. | Behavior | Description | | ------------------- | ---------------------------------------------------------- | | **Single scan** | Scan one barcode at a time. The user needs to trigger the scanner every time to scan a barcode. This allows for a more controlled scanning and lower battery consumption. | | **Continuous scan** | Scan barcodes consecutively. The user needs to trigger the scanner once and barcodes will be scanned without any further interaction before each scan. This allows for a smoother experience when multiple barcodes need to be scanned consecutively. | :::tip Users can enable continuous scanning by holding down the trigger button. This gesture can be disabled (`SDCSparkScanViewSettings.holdToScanEnabled`). ::: ### Preview Behavior The preview behavior determines how the camera preview behaves when the scanner is not actively scanning. | Behavior | Description | | -------------- | -------------------------- | | **Default** | Preview fades away when the scanner is off. This lets the user check important information displayed by the app and reduces battery consumption. | | **Persistent** | Preview remains visible, but darkened, even when the scanner is off. This is useful for scenarios where you want to select a barcode (among many) or need to look through the preview at all times (to ensure the right scan) - especially if used in conjunction with the target mode. | ### Configuring the default scanning mode Combine a scanning mode, scanning behavior, and preview behavior and assign it to [`SparkScanViewSettings.defaultScanningMode`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/spark-scan-view-settings.html). For example, to start in continuous scanning with the preview always visible: ```ts const viewSettings = new SparkScanViewSettings(); viewSettings.defaultScanningMode = new SparkScanScanningModeDefault( SparkScanScanningBehavior.Continuous, // or .Single SparkScanPreviewBehavior.Persistent, // or .Default ); ``` Pass both arguments — the single-argument constructor is deprecated. Use `SparkScanScanningModeTarget` instead of `SparkScanScanningModeDefault` to force the aimer (target mode). --- ## Get Started # Get Started In this guide you will learn step-by-step how to add SparkScan to your application. The general steps are: 1. Initialize the Data Capture Context. 2. Configure the Spark Scan Mode. 3. Create the SparkScanView with the desired settings and bind it to the application’s lifecycle. 4. Register the listener to be informed when new barcodes are scanned and update your data whenever this event occurs. ## Prerequisites - The latest stable version of [Node.js and npm](https://nodejs.org/en/download/) (required only if including and building the SDK as part of an app, instead of just including it as an external resource from a CDN in HTML). - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). - If you have not already done so, see [this guide](../add-sdk.md) for information on how to add the Scandit Data Capture SDK to your project :::note Devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/capacitor/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the SparkScan Mode The SparkScan Mode is configured through [`SparkScanSettings`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/spark-scan-settings.html#class-scandit.datacapture.barcode.spark.SparkScanSettings) and allows you to register one or more listeners that are informed whenever a new barcode is scanned. For this tutorial, we will set up SparkScan for scanning EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```js const settings = new SparkScanSettings(); settings.enableSymbologies([Symbology.EAN13UPCA]); ``` Next, create a SparkScan instance with the settings initialized in the previous step: ```js const sparkScan = new SparkScan(settings); ``` ## Setup the Spark Scan View The SparkScan built-in user interface includes the camera preview and scanning UI elements. These guide the user through the scanning process. The [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/spark-scan-view-settings.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) appearance can be customized through [`SparkScanViewSettings`](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/spark-scan-view-settings.html#class-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings). ```js const viewSettings = new SparkScanViewSettings(); // setup the desired appearance settings by updating the fields in the object above ``` See the [SparkScan Workflow Options](./advanced.md#workflow-options) section for more information. By adding a `SparkScanView`, the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a `SparkScanView` to your view hierarchy. Construct a new SparkScan view. The `SparkScan` view is automatically added to the provided parentView: ```js const sparkScanView = SparkScanView.forContext(DataCaptureContext.sharedInstance, sparkScan, viewSettings); ``` Additionally, make sure to call [SparkScanView.stopScanning()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.StopScanning) in your app state handling logic. You have to call this for the correct functioning of the [SparkScanView](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView). ```js componentWillUnmount() { sparkScanView.stopScanning(); } handleAppStateChange = async (nextAppState) => { if (nextAppState.match(/inactive|background/)) { sparkScanView.stopScanning(); } } ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [SparkScanListener](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface and register the listener to the SparkScan mode. ```js // Register a listener object to monitor the spark scan session. const listener = { didScan: (sparkScan, session, getFrameData) => { // Gather the recognized barcode const barcode = session.newlyRecognizedBarcode[0]; // Handle the barcode }, }; sparkScan.addListener(listener); ``` [SparkScanListener.didScan()](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/spark-scan-listener.html#method-scandit.datacapture.barcode.spark.ISparkScanListener.OnBarcodeScanned) is called when a new barcode has been scanned. This result can be retrieved from the first object in the provided barcodes list: [SparkScanSession.newlyRecognizedBarcode](https://docs.scandit.com/data-capture-sdk/capacitor/barcode-capture/api/spark-scan-session.html#property-scandit.datacapture.barcode.spark.SparkScanSession.NewlyRecognizedBarcode). Please note that this list only contains one barcode entry. ## Scan Some Barcodes Now that you’re up and running, go find some barcodes to scan. Don’t feel like getting up from your desk? Here’s a [handy pdf of barcodes](https://github.com/Scandit/.github/blob/main/images/PrintTheseBarcodes.pdf) you can print out. --- ## About SparkScan # About SparkScan SparkScan is our pre-built smartphone scanning interface designed for high-performance barcode scanning. It fits on top of any smartphone application, providing an intuitive user interface for simple, fast and ergonomic scanning in scan-intensive workflows such as inventory management in retail, or goods receiving in logistics. SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs. ## UI Overview The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience. Two main elements compose the UI: ![SparkScan UI](/img/sparkscan/features_web.png) - **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc). - **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space. There are additional UI elements available for displaying additional scanning modes, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section. ## Workflow Description When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use. To start scanning, the user can simply tap on it. When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app). In the default configuration: - Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away. - Tapping on the trigger button or the mini preview will restart immediately the scanner. Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state. If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released. List building use case using SparkScan. The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field. But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more. ## Supported Symbologies SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx). ## AI-Powered Features SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide. --- ## Installation # Installation This guide shows you how to add the Scandit Data Capture SDK to your existing project. ## Prerequisites - The latest stable version of [Cordova](https://github.com/apache/cordova-cli#installation), [Node.js and npm](https://nodejs.org/en/download/). - A project with: - minimum iOS deployment target of 15.0 or higher - an Android project with target SDK version 23 (Android 6, Marshmallow) or higher (version 24 or higher for ID Capture) - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). :::warning Android devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ### Internal Dependencies import InternalDependencies from '../../partials/get-started/_internal-deps-no-label-capture.mdx'; ## Get a License Key 1. [Sign up](https://ssl.scandit.com/dashboard/sign-up?p=test) or [Sign in](https://ssl.scandit.com/dashboard/sign-in) to your Scandit account 2. Create a project 3. Create a license key If you have a paid subscription, please reach out to [Scandit Support](mailto:support@scandit.com) if you need a new license key. ## Add the SDK Currently we support adding the Scandit Data Capture SDK Cordova plugins to your project in two ways. The simplest way is to use npm, alternatively you can manually download the plugins and add them to your Cordova project. :::tip You should first always add the `scandit-cordova-datacapture-core` plugin, as all other plugins depend on it. ::: ### Create a new project If you do not have a Cordova project yet that you’ll use, you should create a new one. ```sh > cordova create helloscandit --id "com.scandit.helloscandit" > cd helloscandit > cordova platform add [ios | android] ``` ### Add dependencies The Scandit Data Capture SDK depends on WKWebView on iOS, so you’ll manually have to add this dependency if your project doesn’t use WKWebView yet. :::tip The `cordova-plugin-wkwebview-engine` is only supported in `cordova-ios` `>=4`-` cordova plugin add cordova-plugin-wkwebview-engine ``` ### Install via npm or GitHub repo To add Scandit plugins via npm or GitHub repo, run the corresponding commands from your project’s root folder. In the following snippet we’re adding multiple plugins for different functionalities, but you can add only the ones you need as described in the [Internal Dependencies](#internal-dependencies) section. ```sh # npm package cordova plugin add scandit-cordova-datacapture-core cordova plugin add scandit-cordova-datacapture-barcode cordova plugin add scandit-cordova-datacapture-parser cordova plugin add scandit-cordova-datacapture-id # git repo cordova plugin add https://github.com/Scandit/scandit-cordova-datacapture-core.git cordova plugin add https://github.com/Scandit/scandit-cordova-datacapture-barcode.git cordova plugin add https://github.com/Scandit/scandit-cordova-datacapture-parser.git cordova plugin add https://github.com/Scandit/scandit-cordova-datacapture-id.git ``` :::note For npm dependencies, you can also specify a version using `@`. For GitHub dependencies, you can specify the version using `#`. ::: ### Add the Scandit Data Capture SDK manually After you download the [archive containing all the plugins](https://ssl.scandit.com/dashboard/downloads), unzip the archive. It includes the available Cordova plugins, including the `scandit-cordova-datacapture-core` plugin that all other plugins depend on. ### Add the plugin to your project Use the Cordova CLI to add the plugin(s) to your already existing project. First add `scandit-cordova-datacapture-core` plugin: ```sh cordova plugin add ``` If your project is not yet configured to use Swift on iOS, you’ll need to add the following lines to your _config.xml_ file to specify the iOS version targeted and the Swift version you’d like to use: ```jsx ... ... ``` Once this is done, you can continue with adding the plugin for your desired functionality, e.g. for barcode capture, add the `scandit-cordova-datacapture-barcode` plugin: ```sh cordova plugin add ``` To update plugins, make sure to follow Cordova best practices and remove the plugin before adding the new version: ```sh cordova plugin remove cordova plugin add ``` ### iOS Setup For iOS development, Cordova uses CocoaPods to manage native dependencies. You'll need to set up Scandit's private CocoaPods repository: **Important:** This project uses Scandit's private CocoaPods repository. First-time setup: ```sh # Add Scandit's private CocoaPods repository (one-time setup) pod repo add scandit-private-specs https://github.com/Scandit/scandit-cocoapods-specs.git ``` After adding plugins, build your iOS project to install the CocoaPods dependencies: ```sh cordova build ios ``` :::note The public CocoaPods trunk repository is becoming read-only. Scandit has migrated to a private CocoaPods specs repository to ensure continued support and updates for iOS framework integrations. The repository is publicly accessible at https://github.com/Scandit/scandit-cocoapods-specs. **Troubleshooting**: If you encounter issues: - Verify the repo is added: `pod repo list | grep scandit-private-specs` - Update the repo: `pod repo update scandit-private-specs` ::: ## Additional Information ### Android Configuration On Android, the Scandit SDK uses content providers to initialize the scanning capabilities properly. If your own content providers depend on the Scandit SDK, choose an **initOrder** lower than 10 to make sure the SDK is ready first. If not specified, **initOrder** is zero by default and you have nothing to worry about. Check [the official `` documentation](https://developer.android.com/guide/topics/manifest/provider-element). ### Camera Permissions When using the Scandit Data Capture SDK you will want to set the camera as the frame source for various capture modes. The camera permissions are handled by the plugins, so you don’t need to specify anything explicitly. import OSSLicense from '../../partials/_third-party-licenses-js.mdx'; --- ## Agent Skills import SkillsPage from '@site/src/components/SkillsPage'; # Agent Skills for Cordova --- ## Configure Barcode Symbologies # Configure Barcode Symbologies import Intro from '../../../partials/configure-symbologies/_intro.mdx' ## Enable the Symbologies You Want to Read import EnableSymbologies from '../../../partials/configure-symbologies/_enable-symbologies.mdx' The following lines of code show you how to enable scanning Code 128 codes for barcode capture: ```js const settings = new Scandit.BarcodeCaptureSettings(); settings.enableSymbology(Scandit.Symbology.Code128, true); ``` import CapturePresents from '../../../partials/configure-symbologies/_capture-presents.mdx' ## Configure the Active Symbol Count Barcode symbologies (such as Code 128, Code 39, Code 93, or Interleaved Two of Five) can store variable-length data. For example, Code 39 can be used to store a string from 1 to 40-50 symbols. There is no fixed upper limit, though there are practical limitations to the code’s length for it to still be conveniently readable by barcode scanners. For performance reasons, the Scandit Data Capture SDK limits the [possible symbol range](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.ActiveSymbolCounts) for variable-length symbologies. If you want to read codes that are shorter/longer than the specified default range or you want to tailor your app to only read codes of a certain length, you need to change the active symbol count of the symbology to accommodate the data length you want to use in your application. The below lines of code show how to change the active symbol count for Code 128 to read codes with 6, 7 and 8 symbols. ```js const settings = new Scandit.BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology( Scandit.Symbology.Code128 ); symbologySettings.activeSymbolCounts = [6, 7, 8]; ``` import CalculateSymbolCount from '../../../partials/configure-symbologies/_calculate-symbol-count.mdx' ## Read Bright-on-Dark Barcodes Most barcodes are printed using dark ink on a bright background. Some symbologies allow the colors to be inverted and can also be printed using bright ink on a dark background. This is not possible for all symbologies as it could lead to false reads when the symbology is not designed for this use case. See [symbology properties](../symbology-properties.mdx) to learn which symbologies allow color inversion. When you enable a symbology as described above, only dark-on-bright codes are enabled. If you also want to read bright-on-dark codes, color-inverted reading for that symbology must be enabled ( `SymbologySettings.isColorInvertedEnabled`). The following code shows how to enable color-inverted reading for Code 128: ```js const settings = new Scandit.BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology( Scandit.Symbology.Code128 ); symbologySettings.isColorInvertedEnabled = true; ``` ## Enforce Checksums Some symbologies have a mandatory checksum that will always be enforced while others only have optional [checksums](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/checksum.html#enum-scandit.datacapture.barcode.Checksum). Enforcing an optional checksum will reduce false positives as an additional check can be performed. When enabling a checksum you have to make sure that the data of your codes contains the calculated checksum otherwise the codes get discarded as the checksum doesn’t match. All available checksums per symbology can be found in [symbology properties](../symbology-properties.mdx). You can enforce a specific checksum by setting it through [SymbologySettings.checksums](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.Checksums): ```js const settings = new Scandit.BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology( Scandit.Symbology.Code39 ); symbologySettings.checksums = [Scandit.Checksum.Mod43]; ``` ## Enable Symbology-Specific Extensions Some symbologies allow further configuration. These configuration options are available as symbology extensions that can be enabled/disabled for each symbology individually. Some extensions affect how the data in the code is formatted, others allow for more relaxed recognition modes that are disabled by default to eliminate false reads. All available extensions per symbology and a description of what they do can be found in the documentation on [symbology properties](../symbology-properties.mdx). To enable/disable a symbology extension, use [SymbologySettings.setExtensionEnabled()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/symbology-settings.html#method-scandit.datacapture.barcode.SymbologySettings.SetExtensionEnabled). The following code shows how to enable the full ASCII extension for Code 39. ```js const settings = new Scandit.BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology( Scandit.Symbology.Code39 ); symbologySettings.setExtensionEnabled('full_ascii', true); ``` This extension allows Code 39 to encode all 128 ASCII characters instead of only the 43 characters defined in the standard. The extension is disabled by default as it can lead to false reads when enabled. --- ## Get Started # Get Started In this guide you will learn step by step how to add barcode capture to your application. The general steps are: - Include the ScanditBarcodeCapture library and its dependencies to your project, if any. - Initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with your license key. - Create a [barcode capture settings](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and enable the [barcode symbologies](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology) you want to read in your application. - Create a new [barcode capture mode](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance and initialize it with the settings created above. - Register a [barcode capture listener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/cordova/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ### Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Scanning Behavior Barcode scanning is orchestrated by the [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) [data capture mode](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). This class is the main entry point for scanning barcodes. It is configured through [BarcodeCaptureSettings](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) that will get informed whenever new codes have been recognized. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```js const settings = new Scandit.BarcodeCaptureSettings(); settings.enableSymbologies([ Scandit.Symbology.Code128, Scandit.Symbology.Code39, Scandit.Symbology.QR, Scandit.Symbology.EAN8, Scandit.Symbology.UPCE, Scandit.Symbology.EAN13UPCA, ]); ``` If you are not disabling barcode capture immediately after having scanned the first code, consider setting the [BarcodeCaptureSettings.codeDuplicateFilter](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture-settings.html#property-scandit.datacapture.barcode.BarcodeCaptureSettings.CodeDuplicateFilter) to around 500 or even \-1 if you do not want codes to be scanned more than once. Next, create a [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance with the settings initialized in the previous step: ```js const barcodeCapture = new Scandit.BarcodeCapture(settings); DataCaptureContext.sharedInstance.addMode(barcodeCapture); ``` ## Register the Barcode Capture Listener To get informed whenever a new code has been recognized, add a [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) through [BarcodeCapture.addListener()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.AddListener) and implement the listener methods to suit your application’s needs. First implement the [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) interface. For example: ```js const listener = { didScan: (barcodeCapture, session) => { const recognizedBarcodes = session.newlyRecognizedBarcode; // Do something with the barcodes }, }; ``` Then add the listener: ```js barcodeCapture.addListener(listener); ``` ### Rejecting Barcodes To prevent scanning unwanted codes, you can reject them by adding the desired logic to the `onBarcodeScanned` method. This will prevent the barcode from being added to the session and will not trigger the `onSessionUpdated` method. The example below will only scan barcodes beginning with the digits `09` and ignore all others, using a transparent brush to distinguish a rejected barcode from a recognized one: ```js ... if (!barcode.data || !barcode.data.startsWith('09:')) { window.overlay.brush = Scandit.Brush.transparent; return; } ... ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```js const cameraSettings = Scandit.BarcodeCapture.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. const camera = Scandit.Camera.default; if (camera) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js DataCaptureContext.sharedInstance.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/cordova/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/cordova/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```js camera.switchToDesiredState(Scandit.FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js const view = Scandit.DataCaptureView.forContext(DataCaptureContext.sharedInstance); view.connectToElement(htmlElement); ``` To visualize the results of barcode scanning, the following [overlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) can be added: ```js const overlay = new Scandit.BarcodeCaptureOverlay(barcodeCapture); view.addOverlay(overlay); ``` ## Disabling Barcode Capture To disable barcode capture, for instance as a consequence of a barcode being recognized, set [BarcodeCapture.isEnabled](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-capture.html#property-scandit.datacapture.barcode.BarcodeCapture.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## Barcode Generator # Barcode Generator The Barcode Generator is a simple tool to generate barcodes directly from the Scandit SDK. In this guide, we will show you how to use the Barcode Generator to generate barcodes and QR codes. The Barcode Generator supports the following formats: * Code 39 * Code 128 * EAN 13 * UPCA * ITF * QR * DataMatrix * PDF417 (SDK version >= 8.2) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/cordova/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Generating Barcodes To generate barcodes, you need to initialize the [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`BarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.BarcodeGeneratorBuilder), and use the method of [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) for the symbology you are interested in, in this example Code 128. You can configure the colors used in the resulting image: ```javascript DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); const builder = Scandit.BarcodeGenerator.code128BarcodeGeneratorBuilder(DataCaptureContext.sharedInstance) .withBackgroundColor(Scandit.Color.fromHex('#ffffff')) .withForegroundColor(Scandit.Color.fromHex('#000000')); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: When the builder is configured get the `BarcodeGenerator` and try to generate the image: ```javascript try { const generator = builder.build(); const image = await generator.generate(dataString, 200); // Use the image } catch (error) { // Handle the error console.error(error); } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-generator.html) for more information. ## Generating QR Codes To generate barcodes, you need to initialize the [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`QRCodeBarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder) using the method of [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) specific for QR codes. You can configure the colors used in the resulting image, and the two settings that can be configured for QR codes: [`QRCodeBarcodeGeneratorBuilder.errorCorrectionLevel`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithErrorCorrectionLevel) and [`QRCodeBarcodeGeneratorBuilder.versionNumber`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithVersionNumber). ```javascript DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); const builder = Scandit.BarcodeGenerator.qrCodeBarcodeGeneratorBuilder(DataCaptureContext.sharedInstance) .withBackgroundColor(Scandit.Color.fromHex('#ffffff')) .withForegroundColor(Scandit.Color.fromHex('#000000')) .withErrorCorrectionLevel(Scandit.QrCodeErrorCorrectionLevel.Medium) .withVersionNumber(4); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: When the builder is configured get the `BarcodeGenerator` and try to generate the image: ```javascript try { const generator = builder.build(); const image = await generator.generate(dataString, 200); // Use the image } catch (error) { // Handle the error console.error(error); } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-generator.html) for more information. --- ## Get Started # Get Started :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/cordova/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: In this guide you will learn step by step how to add barcode selection to your application. The general step are: - Initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with your license key. - Create a [barcode selection settings](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and choose the right configuration. - Create a new [barcode selection mode](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance and initialize it with the settings created above. - Register a [barcode selection listener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/cordova/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-selection-basic-overlay.html#class-scandit.datacapture.barcode.selection.ui.BarcodeSelectionBasicOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Selection Behavior _Symbologies_ Barcode selection is orchestrated by the [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) [data capture mode](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). It is configured through [BarcodeSelectionSettings](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) that will get informed whenever new codes have been selected. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```js const settings = new Scandit.BarcodeSelectionSettings(); settings.enableSymbologies([ Scandit.Symbology.Code128, Scandit.Symbology.EAN8, Scandit.Symbology.UPCE, Scandit.Symbology.EAN13UPCA, ]); ``` _Selection Types_ The behavior of Barcode Selection can be changed by using a different [selection type](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-type.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionType). This defines the method used by [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) to select codes. Currently there are two types. If you want the user to select barcodes with a tap, then use [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection). This selection type can automatically freeze the camera preview to make the selection easier. You can configure the freezing behavior via [BarcodeSelectionTapSelection.freezeBehavior](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.FreezeBehavior). With [BarcodeSelectionTapSelection.tapBehavior](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.TapBehavior) you can decide if a second tap on a barcode means that the barcode is unselected or if it is selected another time (increasing the counter). :::note Using [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection) requires the MatrixScan add-on. ::: If you want the selection to happen automatically based on where the user points the camera, then use [BarcodeSelectionAimerSelection](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-aimer-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAimerSelection). It is possible to choose between two different [selection strategies](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-strategy.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionStrategy). Use [BarcodeSelectionAutoSelectionStrategy](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAutoSelectionStrategy) if you want the barcodes to be selected automatically when aiming at them as soon as the intention is understood by our internal algorithms. Use [BarcodeSelectionManualSelectionStrategy](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionManualSelectionStrategy) if you want the barcodes to be selected when aiming at them and tapping anywhere on the screen. _Single Barcode Auto Detection_ If you want to automatically select a barcode when it is the only one on screen, turn on [BarcodeSelectionSettings.singleBarcodeAutoDetection](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-settings.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionSettings.SingleBarcodeAutoDetection). _Creating the mode_ Next, create a [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance with the settings initialized in the previous step: ```js const barcodeSelection = new Scandit.BarcodeSelection(settings); await Scandit.DataCaptureContext.sharedInstance.addMode(barcodeSelection); ``` ## Register the Barcode Selection Listener To get informed whenever a new code has been recognized, add a [BarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) through [BarcodeSelection.addListener()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection.html#method-scandit.datacapture.barcode.selection.BarcodeSelection.AddListener) and implement the listener methods to suit your application’s needs. First implement the [BarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) interface. For example: ```js const listener = { didUpdateSelection: (barcodeSelection, session) => { const newlySelectedBarcodes = session.newlySelectedBarcodes; // Do something with the barcodes }, }; ``` Then add the listener: ```js barcodeSelection.addListener(listener); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```js const cameraSettings = Scandit.BarcodeSelection.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. const camera = Scandit.Camera.default; if (camera) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js Scandit.DataCaptureContext.sharedInstance.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/cordova/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/cordova/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```js camera.switchToDesiredState(Scandit.FrameSourceState.On); ``` ## Disabling Barcode Selection To disable barcode selection, for instance when the selection is complete, set [BarcodeSelection.isEnabled](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelection.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## About Barcode Selection # About Barcode Selection :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/cordova/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: Barcode Selection enables you to increase scanning accuracy and prevent users from scanning the wrong code in scenarios where there are multiple barcodes present, such as a crowded shelf, an order catalog with barcodes printed closely together, or a label with multiple barcodes. Barcode Selection provides two key capabilities: - **Aim to Select** allows users to select one code at a time. This is especially useful for one-handed operation. - **Tap to Select** is a quick way for users to select several codes from the same view. Selection is done by tapping on highlighted barcodes in the live camera preview or on a frozen screen. :::warning Barcode Selection does not support handling of duplicate codes. If a code appears twice in the visible preview both instances will be marked as selected even if only one of them was selected. ::: --- ## Advanced Configurations # Advanced Configurations There are several advanced configurations that can be used to customize the behavior of the ID Capture SDK and enable additional features. ## Configure Data Anonymization By default, data extracted from documents is anonymized according to local regulations. See [Anonymized Documents](/sdks/cordova/id-capture/supported-documents.md#anonymized-documents) for more information. That means certain data from certain fields won’t be returned, even if it’s present on a document. You control the anonymization level with the following setting: ```js // Default value: settings.anonymizationMode = Scandit.IdAnonymizationMode.FieldsOnly; // Sensitive data is additionally covered with black boxes on returned images: settings.anonymizationMode = Scandit.IdAnonymizationMode.FieldsAndImages; // Only images are anonymized: settings.anonymizationMode = Scandit.IdAnonymizationMode.ImagesOnly; // No anonymization: settings.anonymizationMode = Scandit.IdAnonymizationMode.None; ``` ## ID Images Your use can may require that you capture and extract images of the ID document. Use the [IdImageType](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/id-image-type.html#enum-scandit.datacapture.id.IdImageType) enum to specify the images you want to extract from the `CapturedId` object. :::tip Face and Cropped Document can be extracted only by either `SingleSideScanner` with `visualInspectionZone` enabled or by `FullDocumentScanner`. In the case of `FullDocumentScanner`, if the front & the back side of a document are scanned, Cropped Document and Full Frame are returned for both sides. ::: For the full frame of the document, you can use [`setShouldPassImageTypeToResult`](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/id-capture-settings.html#method-scandit.datacapture.id.IdCaptureSettings.SetShouldPassImageTypeToResult) when creating the `IdCaptureSettings` object. This will pass the image type to the result, which you can then access in the `CapturedId` object. ```js // Holder's picture as printed on a document: settings.setShouldPassImageTypeToResult(Scandit.IdImageType.Face, true); // Cropped image of a document: settings.setShouldPassImageTypeToResult(Scandit.IdImageType.CroppedDocument, true); // Full camera frame that contains the document: settings.setShouldPassImageTypeToResult(Scandit.IdImageType.Frame, true); ``` ## Callbacks and Scanning Workflows The ID Capture Listener provides two callbacks: `onIdCaptured` and `onIdRejected`. The `onIdCaptured` callback is called when an acceptable document is successfully captured, while the `onIdRejected` callback is called when a document is captured but rejected. For a successful capture, the `onIdCaptured` callback provides a `CapturedId` object that contains the extracted information from the document. This object is specific to the type of document scanned. For example, a `CapturedId` object for a US Driver License will contain different fields than a `CapturedId` object for a Passport. For a rejected document, a [RejectionReason](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) is provided in the `onIdRejected` callback to help you understand why the document was rejected and to take appropriate action. These are: * NOT_ACCEPTED_DOCUMENT_TYPE: The document is not in the list of accepted documents. In this scenario, you could direct the user to scan a different document. * INVALID_FORMAT: The document is in the list of accepted documents, but the format is invalid. In this scenario, you could direct the user to scan the document again. * DOCUMENT_VOIDED: The document is in the list of accepted documents, but the document is voided. In this scenario, you could direct the user to scan a different document. * TIMEOUT: The document was not scanned within the specified time. In this scenario, you could direct the user to scan the document again. ## Detect Fake IDs *ID Validate* is a fake ID detection software. It currently supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). Fake ID detection can be performed automatically using the following settings: * [IdCaptureSettings.rejectForgedAamvaBarcodes](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectForgedAamvaBarcodes): Automatically rejects documents whose AAMVA barcode fails authenticity validation. * [IdCaptureSettings.rejectInconsistentData](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectInconsistentData): Automatically rejects documents whose human‑readable data does not match the data encoded in the barcode or MRZ. To enable ID validation for your subscription, please reach out to [Scandit Support](mailto:support@scandit.com). --- ## Get Started # Get Started This page will guide you through the process of adding ID Capture to your Cordova application. ID Capture is a mode of the Scandit Data Capture SDK that allows you to capture and extract information from personal identification documents, such as driver's licenses, passports, and ID cards. The general steps are: - Initializing the Data Capture Context - Accessing a Camera - Configuring the Capture Settings - Implementing a Listener to Receive Scan Results - Setting up the Capture View and Overlay - Starting the Capture Process :::warning Using ID Capture at the same time as other modes (e.g. Barcode Capture) is not supported. ::: ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](/sdks/cordova/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import IdModuleOverview from '../../../partials/get-started/_id-module-overview-no-eu-dl.mdx'; To learn more about specifying native dependencies on Cordova and the framework tag, take a look at the official [Cordova documentation](https://cordova.apache.org/docs/en/latest/plugin%5Fref/spec.html#framework). ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Add the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/cordova/core/api/camera.html#class-scandit.datacapture.core.Camera): ```js const camera = Scandit.Camera.default; DataCaptureContext.sharedInstance.setFrameSource(camera); const cameraSettings = Scandit.IdCapture.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. if (camera != null) { camera.applySettings(cameraSettings); } ``` ## Create ID Capture Settings Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scanner type and the accepted and rejected documents. Check [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) for all available options. :::tip By default, [anonymized data](./advanced.md#configure-data-anonymization) is not returned in accordance with local regulations for specific documents. This setting can be disabled for testing purposes, but be sure to comply with local laws and requirements in production. ::: ```ts const settings = new Scandit.IdCaptureSettings(); // Documents from any region: settings.acceptedDocuments.push(new Scandit.IdCard(Scandit.IdCaptureRegion.Any)); // Only documents issued by a specific country: settings.acceptedDocuments.push(new Scandit.IdCard(Scandit.IdCaptureRegion.Germany)); // Regional documents: settings.acceptedDocuments.push(new Scandit.RegionSpecific(Scandit.RegionSpecificSubtype.ApecBusinessTravelCard)); // Reject passports from certain regions: settings.rejectedDocuments.push(new Scandit.Passport(Scandit.IdCaptureRegion.Cuba)); // To scan only one-sided documents and a given zone: settings.scanner = new Scandit.SingleSideScanner(true, false, false); // or settings.scanner = new Scandit.SingleSideScanner(false, true, false); // or settings.scanner = new Scandit.SingleSideScanner(false, false, true); // To scan both sides of the document: settings.scanner = new Scandit.FullDocumentScanner(); ``` Create a new ID Capture mode with the chosen settings: ```ts const idCapture = new Scandit.IdCapture(settings); DataCaptureContext.sharedInstance.addMode(idCapture); ``` ## Implement the Listener To receive scan results, implement [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener). The listener provides two callbacks: `onIdCaptured` and `onIdRejected`. ```ts idCapture.addListener({ onIdCaptured: (data) => { // Success! Handle extracted data here. }, onIdRejected: (data, reason) => { // Something went wrong. Inspect the reason to determine the follow-up action. } }); ``` ### Handling Success Capture results are delivered as a [CapturedId](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/captured-id.html#class-scandit.datacapture.id.CapturedId). This class contains data common for all kinds of personal identification documents. For more specific information, use its non-null result properties (e.g. [CapturedId.barcode](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/captured-id.html#property-scandit.datacapture.id.CapturedId.Barcode)). On a successful scan you may read the extracted data from `CapturedId`: ```ts onIdCaptured: (data) => { const fullName = data.fullName; const dateOfBirth = data.dateOfBirth; const dateOfExpiry = data.dateOfExpiry; const documentNumber = data.documentNumber; // Process data: processData(fullName, dateOfBirth, dateOfExpiry, documentNumber); } ``` :::tip All data fields are optional, so it's important to verify whether the required information is present if some of the accepted documents may not contain certain data. ::: ### Handling Rejection The ID scanning process may fail for various reasons. Start from inspecting [RejectionReason](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) to understand the cause. You may wish to implement the follow-up action based on the reason of failure: ```ts onIdRejected: (data, reason) => { if (reason === Scandit.RejectionReason.Timeout) { // Ask the user to retry, or offer alternative input method. } else if (reason === Scandit.RejectionReason.DocumentExpired) { // Ask the user to provide alternative document. } else if (reason === Scandit.RejectionReason.HolderUnderage) { // Reject the process. } } ``` ## Set up Capture View and Overlay When using the built-in camera as [frameSource](https://docs.scandit.com/data-capture-sdk/cordova/core/api/frame-source.html#interface-scandit.datacapture.core.IFrameSource), you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js const view = Scandit.DataCaptureView.forContext(DataCaptureContext.sharedInstance); view.connectToElement(htmlElement); ``` Then create an instance of [IdCaptureOverlay](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) attached to the view: ```js const overlay = new Scandit.IdCaptureOverlay(idCapture); view.addOverlay(overlay); ``` The overlay chooses the displayed UI automatically, based on the selected [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings). If you prefer to show a different UI or to temporarily hide it, set the appropriate [IdCaptureOverlay.idLayout](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/ui/id-capture-overlay.html#property-scandit.datacapture.id.ui.IdCaptureOverlay.IdLayout). ## Start the Capture Process Finally, turn on the camera to start scanning: ```js camera.switchToDesiredState(Scandit.FrameSourceState.On); ``` And this is it. You can now scan documents. --- ## About ID Capture import AboutIdCapture from '../../../partials/intro/_about-id-capture.mdx'; --- ## Supported Documents ## ID Scanning Supported Documents Scandit ID Capture provides various [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/cordova/id-capture/api/id-capture-scanner.html#id-capture-scanner) types, each designed for specific scanning workflows. These workflows can involve scanning either specific parts of a document or the entire document, including both the front and back sides. This section details the types of documents supported by each scanner type. import IdDocumentsFull from '../../../partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from '../../../partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents import IdValidateDocuments from '../../../partials/advanced/_id-documents-validate.mdx'; --- ## Advanced Configurations import ValidationFlowHowItWorks from '../../../partials/advanced/_validation-flow-how-it-works.mdx'; import ValidationFlowCustomButtons from '../../../partials/advanced/_validation-flow-custom-buttons.mdx'; import ValidationFlowTypingHints from '../../../partials/advanced/_validation-flow-typing-hints.mdx'; import ValidationFlowCloudVLM from '../../../partials/advanced/_validation-flow-cloud-vlm.mdx'; import ReceiptScanning from '../../../partials/advanced/_receipt-scanning.mdx'; import ValidationFlowRequiredOptional from '../../../partials/advanced/_validation-flow-required-optional.mdx'; import ValidationFlowCustomToasts from '../../../partials/advanced/_validation-flow-custom-toasts.mdx'; import ValidationFlowCustomField from '../../../partials/advanced/_validation-flow-custom-field.mdx'; # Advanced Configurations ## Customize the Overlay Appearance To customize the appearance of the overlay, you can implement a [LabelCaptureBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/ui/label-capture-basic-overlay-listener.html#interface-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener). The method [brushForLabel()](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForLabel) is called every time a label captured and [brushForFieldOfLabel()](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForField) is called for each of its fields to determine the brush for the label or field. ```js // Create the overlay for the label capture mode. const overlay = new LabelCaptureBasicOverlay(labelCapture); // Set the listener to customize the appearance of captured labels and fields. overlay.listener = { /** * Called for each field of a captured label to determine its brush. * Return a Brush to customize the field's appearance, or null to use the default. */ brushForFieldOfLabel: (overlay, field, label) => { // Create colors with transparency (alpha 0.5 = 50% opacity). const cyanColor = Color.fromRGBA(0, 255, 255, 0.5); const orangeColor = Color.fromRGBA(255, 165, 0, 0.5); switch (field.name) { case "": // Highlight barcode fields with a cyan color. return new Brush(cyanColor, cyanColor, 0); case "": // Highlight expiry date fields with an orange color. return new Brush(orangeColor, orangeColor, 0); default: // Use a transparent brush for other fields. return Brush.transparent; } }, /** * Called for each captured label to determine its brush. * Return a Brush to customize the label's appearance, or null to use the default. */ brushForLabel: (overlay, label) => { // Use a transparent brush for the label itself. return Brush.transparent; }, /** * Called when the user taps on a label. */ didTapLabel: (overlay, label) => { // Handle user tap gestures on the label. } }; // Add the overlay to the data capture view. dataCaptureView.addOverlay(overlay); ``` :::tip Use brush colors with transparency (alpha ```js // Create the overlay const validationFlowOverlay = new LabelCaptureValidationFlowOverlay(labelCapture); dataCaptureView.addOverlay(validationFlowOverlay); // Set the listener to receive validation events validationFlowOverlay.listener = validationFlowListener; ``` ### Define a Listener When the user has verified that all fields are correctly captured and presses the finish button, the Validation Flow triggers a callback with the final results. To receive these results, implement the [LabelCaptureValidationFlowListener](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/ui/label-capture-validation-flow-listener.html) interface: ```js const validationFlowListener = { // This is called by the validation flow overlay when a label has been fully captured and validated didCaptureLabelWithFields: (fields) => { const barcodeData = fields.find(f => f.name === "")?.barcode?.data; const expiryDate = fields.find(f => f.name === "")?.text; // Handle the captured values } }; ``` ```js const validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.create(); validationFlowOverlaySettings.setPlaceholderTextForLabelDefinition("Expiry Date", "MM/DD/YYYY"); validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.create(); validationFlowOverlaySettings.restartButtonText = "Borrar todo"; validationFlowOverlaySettings.pauseButtonText = "Pausar"; validationFlowOverlaySettings.finishButtonText = "Finalizar"; validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.create(); validationFlowOverlaySettings.standbyHintText = "No label detected, camera paused"; validationFlowOverlaySettings.validationHintText = "data fields collected"; // X/Y (X fields out of total Y) is shown in front of this string validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.create(); validationFlowOverlaySettings.validationErrorText = "Incorrect format."; validationFlowOverlaySettings.scanningText = "Scan in progress"; validationFlowOverlaySettings.adaptiveScanningText = "Processing"; validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const customBarcode = CustomBarcode.initWithNameAndSymbologies('Barcode', [ Symbology.EAN13UPCA, Symbology.GS1DatabarExpanded, Symbology.Code128, ]); customBarcode.optional = false; const expiryDateText = new ExpiryDateText('Expiry Date'); expiryDateText.labelDateFormat = new LabelDateFormat(LabelDateComponentFormat.MDY, false); expiryDateText.optional = false; const label = new LabelDefinition('Retail Item'); label.fields = [customBarcode, expiryDateText]; label.adaptiveRecognitionMode = AdaptiveRecognitionMode.Auto; const settings = LabelCaptureSettings.settingsFromLabelDefinitions([label], {}); ``` See [AdaptiveRecognitionMode](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/label-definition.html#property-scandit.datacapture.label.LabelDefinition.AdaptiveRecognitionMode) for available options. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Smart Label Capture to your application. The general steps are: - Create a component to handle the capture process - Initialize the Data Capture Context - Initialize the Label Capture Mode - Implement a listener to handle captured labels - Visualize the scan process - Start the camera - Provide feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/cordova/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import LabelCaptureModuleOverview from '../../../partials/get-started/_smart-label-capture-module-overview-web.mdx'; ## Initialize the Data Capture Context import DataCaptureContextWeb from '../../../partials/get-started/_create-data-capture-context-web.mdx'; ## Initialize the Label Capture Mode The main entry point for the Label Capture Mode is the [LabelCapture](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/label-capture.html#class-scandit.datacapture.label.LabelCapture) object. It is configured through [LabelCaptureSettings](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/label-capture-settings.html#class-scandit.datacapture.label.LabelCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) that get informed whenever a new frame has been processed. ```js import { Symbology } from "scandit-cordova-datacapture-barcode"; import { CustomBarcode, ExpiryDateText, ImeiOneBarcode, ImeiTwoBarcode, LabelCapture, LabelCaptureSettings, LabelDateComponentFormat, LabelDateFormat, LabelDefinition, SerialNumberBarcode, TotalPriceText, UnitPriceText, WeightText, } from "scandit-cordova-datacapture-label"; // Create a label definition for an ISOF (In-Store Order Fulfillment) label. // This label type typically includes a barcode, price fields, expiry date, and weight. const isofLabel = new LabelDefinition("ISOF Label"); // Add a barcode field that expects an EAN-13 or UPC-A barcode. const barcodeField = CustomBarcode.initWithNameAndSymbology("Barcode", Symbology.EAN13UPCA); barcodeField.optional = false; isofLabel.addField(barcodeField); // Add a total price text field. const totalPriceField = new TotalPriceText("Total Price"); totalPriceField.optional = false; isofLabel.addField(totalPriceField); // Add a unit price text field. const unitPriceField = new UnitPriceText("Unit Price"); unitPriceField.optional = false; isofLabel.addField(unitPriceField); // Add an expiry date text field with a specific date format (Month-Day-Year). const expiryDateField = new ExpiryDateText("Expiry Date"); expiryDateField.optional = false; expiryDateField.labelDateFormat = new LabelDateFormat(LabelDateComponentFormat.MDY, false); isofLabel.addField(expiryDateField); // Add a weight text field. const weightField = new WeightText("Weight"); weightField.optional = false; isofLabel.addField(weightField); // Create a label definition for a smart device label. // This label type is commonly found on electronic devices and includes IMEI numbers and serial numbers. const smartDeviceLabel = new LabelDefinition("Smart Device Label"); // Add an IMEI barcode field (first IMEI number). const imeiField = ImeiOneBarcode.initWithNameAndSymbology("IMEI", Symbology.Code128); imeiField.optional = false; smartDeviceLabel.addField(imeiField); // Add a second IMEI barcode field (for dual-SIM devices). const imei2Field = ImeiTwoBarcode.initWithNameAndSymbology("IMEI2", Symbology.Code128); imei2Field.optional = false; smartDeviceLabel.addField(imei2Field); // Add a serial number barcode field. const serialNumberField = SerialNumberBarcode.initWithNameAndSymbology("Serial Number", Symbology.Code128); serialNumberField.optional = false; smartDeviceLabel.addField(serialNumberField); // Add a custom barcode field for EID (Electronic ID). const eidField = CustomBarcode.initWithNameAndSymbology("EID", Symbology.Code128); eidField.optional = false; smartDeviceLabel.addField(eidField); // Create the label capture settings from the label definitions. const settings = LabelCaptureSettings.settingsFromLabelDefinitions( [isofLabel, smartDeviceLabel], null // Optional properties ); // Create the label capture mode with the settings. const labelCapture = new LabelCapture(settings); // Add the mode to the data capture context created earlier. dataCaptureContext.addMode(labelCapture); ``` ## Implement a Listener to Handle Captured Labels To get informed whenever a new label has been recognized, add a [LabelCaptureListener](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) through [LabelCapture.addListener()](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/label-capture.html#method-scandit.datacapture.label.LabelCapture.AddListener) and implement the listener methods to suit your application's needs. First conform to the `LabelCaptureListener` interface. Here is an example of how to implement a listener that processes the captured labels based on the label capture settings defined above. ```js import { Feedback } from "scandit-cordova-datacapture-core"; import { LabelCaptureListener } from "scandit-cordova-datacapture-label"; // Create a listener to handle captured labels. const labelCaptureListener = { // Called for every processed frame. Check session.capturedLabels for results. didUpdateSession: (labelCapture, session) => { // Early return if no label has been captured in this frame. if (session.capturedLabels.length === 0) { return; } // Process each captured label. session.capturedLabels.forEach((capturedLabel) => { const fields = capturedLabel.fields; // Access the barcode field by its name (as defined in the label definition). // The barcode property contains the scanned barcode data. const barcodeField = fields.find((field) => field.name === "Barcode"); const barcodeData = barcodeField?.barcode?.data; // Access the expiry date field. Use the text property for OCR-captured text, // or the asDate() method to get a parsed LabelDateResult. const expiryDateField = fields.find((field) => field.name === "Expiry Date"); const expiryDateText = expiryDateField?.text; const expiryDateResult = expiryDateField?.asDate(); // Handle the captured data as needed, for example: // - Update your app's state // - Navigate to a results screen // - Send data to your backend console.log("Barcode:", barcodeData); console.log("Expiry Date:", expiryDateText); }); // Disable label capture to prevent capturing the same labels multiple times. // Re-enable it when you're ready to scan again. labelCapture.isEnabled = false; // Emit feedback to indicate a successful scan. // See the Feedback section for customization options. Feedback.defaultFeedback.emit(); } }; // Register the listener with the label capture mode. labelCapture.addListener(labelCaptureListener); ``` ## Visualize the Scan Process The capture process can be visualized by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy. The view controls the UI elements, such as the viewfinder and overlays, that are shown to visualize captured labels. To visualize the results of Label Capture, you can choose between two overlays, [LabelCaptureBasicOverlay](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/ui/label-capture-basic-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureBasicOverlay) and [LabelCaptureAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/ui/label-capture-advanced-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureAdvancedOverlay). Here is an example of how to add a `LabelCaptureBasicOverlay` to the `DataCaptureView`. ```js import { RectangularViewfinder, RectangularViewfinderStyle } from "scandit-cordova-datacapture-core"; import { LabelCaptureBasicOverlay } from "scandit-cordova-datacapture-label"; // Create the overlay for the label capture mode created earlier. const overlay = new LabelCaptureBasicOverlay(labelCapture); // Add the overlay to the data capture view. dataCaptureView.addOverlay(overlay); // Optionally, add a viewfinder to guide users through the capture process. const viewfinder = new RectangularViewfinder(RectangularViewfinderStyle.Square); overlay.viewfinder = viewfinder; ``` :::tip See the [Advanced Configurations](advanced.md) section for more information about how to customize the appearance of the overlays and how to use the advanced overlay to display arbitrary views such as text views, icons or images. ::: ## Start the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/cordova/core/api/camera.html#class-scandit.datacapture.core.Camera): ```js import { Camera, FrameSourceState } from "scandit-cordova-datacapture-core"; import { LabelCapture } from "scandit-cordova-datacapture-label"; // Get the default camera (usually the back-facing camera). const camera = Camera.default; // Set the camera as the frame source for the data capture context. await dataCaptureContext.setFrameSource(camera); // Use the recommended camera settings for label capture. const cameraSettings = LabelCapture.createRecommendedCameraSettings(); // Depending on the use case, further camera settings adjustments can be made here. await camera.applySettings(cameraSettings); ``` Once the `Camera`, `DataCaptureContext`, `DataCaptureView` and `LabelCapture` are initialized, you can switch on the camera to start capturing labels. Typically, this is done once the view becomes active and the user granted permission to use the camera, or once the user presses continue scanning after handling a previous scan. ```js // Turn on the camera to start capturing labels. await camera.switchToDesiredState(FrameSourceState.On); ``` Please refer to the available [sample apps](https://github.com/Scandit/datacapture-cordova-samples) for detailed examples of camera permission handling and view lifecycle management. ## Provide Feedback Smart Label Capture provides customizable feedback, emitted automatically when a label is recognized and successfully processed, configurable via [`LabelCapture.feedback`](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/label-capture.html#property-scandit.datacapture.label.LabelCapture.Feedback). You can use the default feedback, or configure your own sound or vibration. :::tip If you already have a [Feedback](https://docs.scandit.com/data-capture-sdk/cordova/core/api/feedback.html#class-scandit.datacapture.core.Feedback) instance implemented in your application, remove it to avoid double feedback. ::: ```js import { LabelCaptureFeedback } from "scandit-cordova-datacapture-label"; // Get the default feedback configuration. const feedback = LabelCaptureFeedback.defaultFeedback; // Assign the feedback to the label capture mode. labelCapture.feedback = feedback; ``` :::note Audio feedback is only played if the device is not muted. ::: --- ## About Smart Label Capture import AboutLabelCapture from '../../../partials/intro/_about-smart-label-capture.mdx'; --- ## Label Definitions # Label Definitions A **Label Definition** is a configuration that defines the label, and its relevant fields, that Smart Label Capture should recognize and extract during scans. Smart Label Capture provides a [Label Definition](https://docs.scandit.com/data-capture-sdk/cordova/label-capture/api/label-definition.html#label-definition) API, enabling you to configure and extract structured data from predefined and custom labels. This feature provides a flexible way to recognize and decode fields within a specific label layout such as price tags, VIN labels, or packaging stickers without needing to write custom code for each label type. There are two approaches to using label definitions: - [**Pre-built Labels**](#pre-built-labels) - [**Custom Labels**](#custom-labels) ## Pre-built Labels Smart Label Capture includes ready-made label definitions for common use cases. These pre-built options let you recognize and extract information from standard label types without creating custom configurations: ### Example: Price label Use `LabelDefinition.createPriceCaptureDefinition()` to create a pre-built label definition for price labels, such as those found in retail environments: ![Price Label Example](/img/slc/price-label.png) ```js import { LabelCaptureSettings, LabelDefinition } from "scandit-cordova-datacapture-label"; // Create a pre-built price capture label definition. const priceLabel = LabelDefinition.createPriceCaptureDefinition("price-label"); // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([priceLabel], null); ``` ## Custom Labels If Smart Label Capture's pre-built options don't fit your needs, define a custom label instead. Custom labels can combine your own fields with any of the available pre-built ones. :::tip The following characters are recognized: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ()-./:,$¶"`. ::: ### Custom Fields There are two types of custom fields you can define: The following properties are available to configure custom fields: | Property | Required | Description | |----------|----------|-------------| | `valueRegexes` | Yes | The regex patterns that identify the target string in the scanned content. | | `anchorRegexes` | No | Used to specify keywords or phrases that help identify the context of the field. This is particularly useful when the label contains multiple fields that could match the same pattern (e.g., when both packaging and expiry dates are present). | | `symbologies` | Yes (barcode fields) | The barcode symbologies to match for barcode fields. This is important for ensuring that the field only captures data from specific barcode types, enhancing accuracy and relevance. | | `optional` | No | Whether the field is optional or mandatory. This is helpful when certain fields may not be present on every scan. | #### Example: Fish Shipping Box This example shows how to create a custom label definition for a fish shipping box, which includes fields for barcode and batch number. ![Fish Shipping Box Example](/img/slc/fish-shipping-box.png) ```js import { Symbology } from "scandit-cordova-datacapture-barcode"; import { CustomBarcode, CustomText, LabelCaptureSettings, LabelDefinition, } from "scandit-cordova-datacapture-label"; // Create a custom label definition for a fish shipping box. const shippingLabel = new LabelDefinition("shipping-label"); // Add a barcode field with Code 128 symbology. const barcodeField = CustomBarcode.initWithNameAndSymbology("barcode-field", Symbology.Code128); shippingLabel.addField(barcodeField); // Add a custom text field for the batch number. // Use anchorRegexes to specify keywords that help identify the field context. // Use valueRegexes to specify the expected format of the field data. const batchNumberField = new CustomText("batch-number-field"); batchNumberField.anchorRegexes = ["Batch"]; batchNumberField.valueRegexes = ["FZ\\d{5,10}"]; batchNumberField.optional = true; shippingLabel.addField(batchNumberField); // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([shippingLabel], null); ``` ### Pre-built Fields You can also build your label using pre-built fields. These common fields speed up integration because their `valueRegexes`, `anchorRegexes`, and `symbologies` are already predefined. Customization of pre-built fields is done via the `valueRegexes`, `anchorRegexes`, and `isOptional` methods, which allow you to specify the expected format of the field data. :::tip All pre-built fields come with default `valueRegexes` and `anchorRegexes` that are suitable for most use cases. **Setting either property is optional and will override the defaults**. You can set `anchorRegexes` to an empty array to remove the default anchor patterns, allowing you to rely solely on the `valueRegexes` for detection. ::: import FeatureList from '@site/src/components/FeatureList'; #### Barcode Fields #### Price and Weight Fields #### Date and Custom Text Fields #### Example: Hard disk drive label This example demonstrates how to configure a label definition for a hard disk drive (HDD) label, which typically includes common fields like serial number and part number. ![Hard Disk Drive Label Example](/img/slc/hdd-label.png) ```js import { Symbology } from "scandit-cordova-datacapture-barcode"; import { LabelCaptureSettings, LabelDefinition, PartNumberBarcode, SerialNumberBarcode, } from "scandit-cordova-datacapture-label"; // Create a custom label definition for an HDD label. const hddLabel = new LabelDefinition("hdd-label"); // Add a serial number barcode field. // Pre-built fields like SerialNumberBarcode have predefined valueRegexes and anchorRegexes. const serialNumberField = SerialNumberBarcode.initWithNameAndSymbology("serial-number", Symbology.Code128); hddLabel.addField(serialNumberField); // Add a part number barcode field. const partNumberField = PartNumberBarcode.initWithNameAndSymbology("part-number", Symbology.Code128); hddLabel.addField(partNumberField); // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([hddLabel], null); ``` --- ## Adding AR Overlays # Adding AR Overlays ## Prerequisites To proceed, you need to setup a project that uses MatrixScan first, check out [this guide](./get-started.md) (you can ignore the bottom section about the visualization of tracked barcodes using [BarcodeBatchBasicOverlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay)). ## Getting started To add advanced AR overlays to a Data Capture View you can take advantage of the [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) class, which provides a ready-to-use implementation for view-based AR overlays. ### Using BarcodeBatchAdvancedOverlay As mentioned above, the advanced overlay combined with its [listener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) offers an easy way of adding augmentations to your [DataCaptureView](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). In this guide we will add a view above each barcode showing its content. First of all, create a new instance of [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) and add it to the [DataCaptureView](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). ```js const overlay = new Scandit.BarcodeBatchAdvancedOverlay(barcodeBatch); view.addOverlay(overlay); ``` At this point, you have two options. - Add a [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) to the overlay. - Use the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) to specify the view, anchor and offset for each barcode. :::note The second way will take priority over the first one, which means that if a view for a barcode has been set using [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), the function [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) won’t be invoked for that specific barcode. ::: Using [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) - You need to implement [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener). This interface’s methods are invoked every time a barcode is newly tracked. - [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) asks for a view to animate on top of the barcode. Returning _null_ will show no view. - [BarcodeBatchAdvancedOverlayListener.anchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode) asks how to anchor the view to the barcode through [Anchor](https://docs.scandit.com/data-capture-sdk/cordova/core/api/anchor.html#enum-scandit.datacapture.core.Anchor). Be aware that it anchors the view’s center to the anchor point. To achieve anchoring the top of the view or the bottom etc. you will have to set an offset as explained in the next point. - [BarcodeBatchAdvancedOverlayListener.offsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode) asks for an offset that is applied on the already anchored view. This offset is expressed through a [PointWithUnit](https://docs.scandit.com/data-capture-sdk/cordova/core/api/common.html#struct-scandit.datacapture.core.PointWithUnit). ```js overlay.listener = { viewForTrackedBarcode: (overlay, trackedBarcode) => { // Create and return the view you want to show for this tracked barcode. You can also return null, to have no view for this barcode. let element = document.createElement('span'); element.innerText = trackedBarcode.barcode.data; element.style.backgroundColor = '#FFFFFFFF'; return Scandit.TrackedBarcodeView.withHTMLElement(element, null); }, anchorForTrackedBarcode: (overlay, trackedBarcode) => { // As we want the view to be above the barcode, we anchor the view's center to the top-center of the barcode quadrilateral. // Use the function 'offsetForTrackedBarcode' below to adjust the position of the view by providing an offset. return Scandit.Anchor.TopCenter; }, offsetForTrackedBarcode: (overlay, trackedBarcode) => { // This is the offset that will be applied to the view. // You can use .fraction to give a measure relative to the view itself, the sdk will take care of transforming this into pixel size. // We now center horizontally and move up the view to make sure it's centered and above the barcode quadrilateral by half of the view's height. return new Scandit.PointWithUnit( new Scandit.NumberWithUnit(0, Scandit.MeasureUnit.Fraction), new Scandit.NumberWithUnit(-1, Scandit.MeasureUnit.Fraction), ); }, }; ``` Using the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) The function [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) gives you access to a [session](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession), which contains all added, updated and removed tracked barcodes. From here you can create the view you want to display, and then call [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), [BarcodeBatchAdvancedOverlay.setAnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode) and [BarcodeBatchAdvancedOverlay.setOffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode) ```js didUpdateSession: (barcodeBatch, session) => { session.addedTrackedBarcodes.map((trackedBarcode) => { let element = document.createElement('span'); element.innerText = trackedBarcode.barcode.data; element.style.backgroundColor = '#FFFFFFFF'; let trackedBarcodeView = Scandit.TrackedBarcodeView.withHTMLElement( element, null ); window.overlay.setViewForTrackedBarcode(trackedBarcodeView, trackedBarcode); window.overlay.setAnchorForTrackedBarcode( Scandit.Anchor.TopCenter, trackedBarcode ); window.overlay.setOffsetForTrackedBarcode( new Scandit.PointWithUnit( new Scandit.NumberWithUnit(0, Scandit.MeasureUnit.Fraction), new Scandit.NumberWithUnit(-1, Scandit.MeasureUnit.Fraction) ), trackedBarcode ); }); }; ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan to your application. The general steps are: - Include the ScanditBarcodeCapture library and its dependencies to your project, if any. - Initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with your license key. - Create a [barcode tracking settings](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) instance where you enable the [barcode symbologies](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology) you want to read in your application. - Create a new [barcode tracking](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object and initialize it with the settings created above. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/cordova/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context previously created. - Create a new [data capture view](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) and add a [basic overlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) instance to it for visual feedback. - Register an [overlay listener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) and implement [BrushForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode), which is called whenever a new tracked barcode appears. ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](/sdks/cordova/add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ### Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Batch Mode The main entry point for the Barcode Batch Mode is the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object. It is configured through [BarcodeBatchSettings](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) that will get informed whenever a new frame has been processed. Most of the times, you will not need to implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener), instead you will add a [BarcodeBatchBasicOverlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) and implement a [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener). For this tutorial, we will setup Barcode Batch for tracking QR codes. ```js const settings = new Scandit.BarcodeBatchSettings(); settings.enableSymbology(Scandit.Symbology.QR, true); ``` Next, create a [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance with the data capture context and the settings initialized in the previous steps: ```js const barcodeBatch = new Scandit.BarcodeBatch(settings); DataCaptureContext.sharedInstance.addMode(barcodeBatch); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```js const cameraSettings = Scandit.BarcodeBatch.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. const camera = Scandit.Camera.default; if (camera != null) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js DataCaptureContext.sharedInstance.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/cordova/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/cordova/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```js camera.switchToDesiredState(Scandit.FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js const view = Scandit.DataCaptureView.forContext(DataCaptureContext.sharedInstance); view.connectToElement(htmlElement); ``` To visualize the results of Barcode Batch, first you need to add the following [overlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay): ```js const overlay = new Scandit.BarcodeBatchBasicOverlay(barcodeBatch, Scandit.BarcodeBatchBasicOverlayStyle.Frame); view.addOverlay(overlay); ``` Once the overlay has been added, you should implement the [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) interface. The method [BarcodeBatchBasicOverlayListener.brushForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode) is invoked every time a new tracked barcode appears and it can be used to set a [brush](https://docs.scandit.com/data-capture-sdk/cordova/core/api/ui/brush.html#class-scandit.datacapture.core.ui.Brush) that will be used to highlight that specific barcode in the [overlay](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay). ```js overlay.listener = { brushForTrackedBarcode: (overlay, trackedBarcode) => { // Return a custom Brush based on the tracked barcode. }, }; ``` If you would like to make the highlights tappable, you need to implement the [BarcodeBatchBasicOverlayListener.didTapTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped) method. ```js overlay.listener = { didTapTrackedBarcode: (overlay, trackedBarcode) => { // A tracked barcode was tapped. }, }; ``` ## Get Barcode Batch Feedback Barcode Batch, unlike Barcode Capture, doesn’t emit feedback (sound or vibration) when a new barcode is recognized. However, you may implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) to provide a similar experience. Below, we use the default [Feedback](https://docs.scandit.com/data-capture-sdk/cordova/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration if you want. ```js const feedback = Scandit.Feedback.defaultFeedback; ``` Next, use this [feedback](https://docs.scandit.com/data-capture-sdk/cordova/core/api/feedback.html#class-scandit.datacapture.core.Feedback) in a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener): ```js const feedbackListener = { didUpdateSession: (barcodeBatch, session) => { if (session.addedTrackedBarcodes.length > 0) { feedback.emit(); } }, }; ``` [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) is invoked for every processed frame. The [session](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession) parameter contains information about the currently tracked barcodes, in particular, the newly recognized ones. We check if there are any and if so, we emit the feedback. As the last step, register the listener responsible for emitting the feedback with the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance. ```js barcodeBatch.addListener(feedbackListener); ``` ## Disabling Barcode Batch To disable barcode tracking set [BarcodeBatch.isEnabled](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-batch.html#property-scandit.datacapture.barcode.batch.BarcodeBatch.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off or put it in standby calling [SwitchToDesiredState](https://docs.scandit.com/data-capture-sdk/cordova/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [StandBy](https://docs.scandit.com/data-capture-sdk/cordova/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.Standby). --- ## About MatrixScan Batch # About MatrixScan Batch import AboutMatrixScan from '../../../partials/intro/_about-matrixscan.mdx' --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan AR to your application. Implementing MatrixScan AR involves two primary elements: - Barcode AR: The data capture mode that is used for scan and check functionality. - A Barcode AR View: The pre-built UI elements used to highlight items to be checked. The general steps are: - Initializing the Data Capture Context - Configuring the Barcode AR Mode - Setup the Barcode AR View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode AR Mode The main entry point for the Barcode AR Mode is the `BarcodeAr` object. You can configure the supported Symbologies through its [`BarcodeArSettings`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-ar-settings.html), and set up the list of items that you want MatrixScan AR to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```js const settings = new Scandit.BarcodeArSettings(); settings.enableSymbology(Scandit.Symbology.EAN13UPCA, true); ``` The create the mode with the previously created settings: ```js const mode = new Scandit.BarcodeAr(settings); ``` ## Setup the `BarcodeArView` MatrixScan AR's built-in AR user interface includes buttons and overlays that guide the user through the scan and check process. By adding a [`BarcodeArView`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView), the scanning interface is added automatically to your application. The `BarcodeArView` is where you provide the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider) to supply the highlight and annotation information for the barcodes to be checked. If *null*, a default highlight is used and no annotations are provided. The `BarcodeArView` appearance can be customized through [`BarcodeArViewSettings`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-ar-view-settings.html#class-scandit.datacapture.barcode.check.ui.BarcodeArViewSettings), and the corresponding settings for your desired highlights and/or annotations, to match your application's look and feel. The following settings can be customized: * Audio and haptic feedback * Torch button visibility and its position * Switch camera button visibility and its position * Zoom control visibility and its position * The size, colors, and styles of the highlight and annotation overlays ```js const viewSettings = new Scandit.BarcodeArViewSettings(); ``` Next, create a `BarcodeArView` instance with the Data Capture Context and the settings initialized in the previous step. Then connect it to an HTML element in your view hierarchy. ```js const barcodeArView = new Scandit.BarcodeArView({ context: DataCaptureContext.sharedInstance, barcodeAr: mode, settings: viewSettings, }); barcodeArView.connectToElement(htmlElement); ``` ## Register the Listener Register a [BarcodeArViewUiListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-ar-view.html#interface-scandit.datacapture.barcode.check.ui.IBarcodeArViewUiListener) to be notified when a highlighted barcode is tapped. ```js barcodeArView.uiListener = { didTapHighlightForBarcode(barcodeAr, barcode, highlight) { // Handle the tapped barcode. }, }; ``` ## Start Searching As soon as everything is set up, control the [BarcodeArView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView) to start the search. ```js barcodeArView.start(); ``` --- ## About MatrixScan AR # About MatrixScan AR import AboutMatrixScanCheck from '../../../partials/intro/_about-matrixscan-ar.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Count is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Count to best fit your needs. ## Scanning Against A List There is a function to set a list of expected barcodes if you are scanning against a manifest or item list. If this is used, a progress bar is added to the UI, so you can keep track of the process while scanning. When scanning against a list, the UI will also show red icons to mark scanned barcodes that aren’t present on the list. ```js const barcodeCountCaptureListListener = { didUpdateSession: (barcodeCountCaptureList, session) => { // Handling the session }, }; const targetBarcodes = [Scandit.TargetBarcode.create('data', 1)]; const barcodeCountCaptureList = Scandit.BarcodeCountCaptureList.create( barcodeCountCaptureListListener, targetBarcodes ); barcodeCount.setBarcodeCountCaptureList(barcodeCountCaptureList); ``` ## Clustering import Clustering from '../../../partials/count/_clustering.mdx' ## Tote Mapping import Totes from '../../../partials/count/_tote-mapping.mdx' ## Strap Mode It can be difficult to reach the shutter button if the smart device is attached to the user’s wrist by a strap or similar. In this instance, you can enable a floating shutter button that can be positioned by the end user in a more ergonomically suitable position. ```js barcodeCountView.shouldShowFloatingShutterButton = true; ``` ## Filtering If you have several types of barcodes on your label/package, you may want to scan only one of them. In this case, you can filter the others out. This can be done by symbology, symbol count, or setting a regex. For example, you might want to scan only Code 128 barcodes and no PDF417 ones. ```js const settings = new Scandit.BarcodeCountSettings(); settings.enableSymbologies(enabledSymbologies); const excludedSymbologies = [Scandit.Symbology.PDF417]; const filterSettings = settings.filterSettings; filterSettings.excludedSymbologies = excludedSymbologies; ``` Or, you want to exclude all the barcodes starting with 4 numbers: ```js const settings = new Scandit.BarcodeCountSettings(); const filterSettings = settings.filterSettings; filterSettings.excludedCodesRegex = '^1234.*'; ``` By default the filters applied to the relevant barcodes are transparent, but you can use [`BarcodeFilterHighlightSettings`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-filter-highlight-settings.html#barcode-filter-highlight-settings) to change the color and level of transparency. ![Different Filters in MatrixScan Count](/img/matrixscan-count/filtering_styles.png) ## Clear Screen Button There are situations in which the user may find it helpful to clean up their screen (i.e. clear all the AR overlays) but keep the list of barcodes scanned. If this is the case, you can enable the “Clear screen” button. ```js barcodeCountView.shouldShowClearHighlightsButton = true; ``` ## Customize Overlay Colors MatrixScan Count comes with recommended and user-tested AR overlays. However, if you wish to customize the overlay colors, once the overlay has been added, you can conform to the [BarcodeCountViewListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view-listener.html#interface-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener) interface. The methods [BarcodeCountViewListener.brushForRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForRecognizedBarcode) and [BarcodeCountViewListener.brushForUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForUnrecognizedBarcode) are invoked every time a new recognized or unrecognized barcode appears. These can be used to set a brush that will be used to highlight that specific barcode in the overlay. Keep in mind that these methods are relevant only when using the style [BarcodeCountViewStyle.Dot](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view.html#value-scandit.datacapture.barcode.count.ui.BarcodeCountViewStyle.Dot). ```js const viewListener = { brushForRecognizedBarcode(view, trackedBarcode) { // Return a custom brush }, brushForUnrecognizedBarcode(view, trackedBarcode) { // Return a custom brush }, }; barcodeCountView.listener = viewListener; ``` ## Notifications If you want to be notified when a user taps on an overlay, you need to implement the[BarcodeCountViewListener.didTapRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnRecognizedBarcodeTapped) and [BarcodeCountViewListener.didTapUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped) methods. ```js const viewListener = { didTapRecognizedBarcode: (view, trackedBarcode) => { console.log( `Tapped recognized barcode with data ${trackedBarcode.barcode.data}` ); }, didTapUnrecognizedBarcode: (view, trackedBarcode) => { console.log( `Tapped unrecognized barcode with data ${trackedBarcode.barcode.data}` ); }, }; barcodeCountView.listener = viewListener; ``` ## Disable UI Elements The UI is an integral part of MatrixScan Count and we do not recommend that you use it without it. However, if you wish to disable UI elements you can do it as follows. Disable buttons: ```js barcodeCountView.shouldShowListButton = false; barcodeCountView.shouldShowExitButton = false; barcodeCountView.shouldShowShutterButton = false; ``` Disable feedback and hints: ```js barcodeCountView.shouldShowUserGuidanceView = false; barcodeCountView.shouldShowHints = false; ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Count to your application. The general steps are: 1. Initialize the Data Capture Context 2. Configure the Barcode Count Mode 3. Obtain camera instance and set frame source used 4. Register the listener to be informed when scanned phase is over 5. Set capture view and AR overlays 6. Set up the camera so that it switches on when you are in scanning view 7. Store and retrieve scanned barcodes 8. Reset Barcode Count mode 9. List and Exit callbacks ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure The Barcode Count Mode The main entry point for the Barcode Count Mode is the [BarcodeCount](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) object. It is configured through [BarcodeCountSettings](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count-settings.html#class-scandit.datacapture.barcode.count.BarcodeCountSettings) and allows you to register one or more listeners that are informed whenever a scan phase has finished. For this tutorial, we will set up Barcode Count for tracking EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```js const settings = new Scandit.BarcodeCountSettings(); settings.enableSymbologies([Scandit.Symbology.EAN13UPCA]); ``` If you are sure that your environment will only have unique barcodes (i.e. no duplicated values), you can also enable [BarcodeCountSettings.expectsOnlyUniqueBarcodes](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count-settings.html#property-scandit.datacapture.barcode.count.BarcodeCountSettings.ExpectsOnlyUniqueBarcodes). This option improves scanning performance as long as you are sure that no duplicates will be present. Next, create a [BarcodeCount](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) instance with the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) and the settings initialized in the previous step: ```js const barcodeCount = new Scandit.BarcodeCount(settings); DataCaptureContext.sharedInstance.addMode(barcodeCount); ``` ## Obtain Camera Instance And Set Frame Source Used Our recommended camera settings should be used to achieve the best performance and user experience. The following couple of lines show how to get the recommended settings for MatrixScan Count and create the camera from it: ```js const cameraSettings = Scandit.BarcodeCount.createRecommendedCameraSettings(); const camera = Scandit.Camera.default; if (camera != null) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js DataCaptureContext.sharedInstance.setFrameSource(camera); ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [BarcodeCountListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) interface and register the listener. [BarcodeCountListener.didScan()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan) is called when the scan phase has finished and results can be retrieved from [BarcodeCountSession](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession). ## Set Capture View And AR Overlays MatrixScan Count’s built-in AR user interface includes buttons and overlays that guide the user through the capturing process. By adding a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) to your view hierarchy: ```js const barcodeCountView = Scandit.BarcodeCountView.forContextWithMode(DataCaptureContext.sharedInstance, barcodeCount); barcodeCountView.connectToElement(htmlElement); ``` ## Set Up The Camera So That It Switches On When You Are In Scanning View The camera is not automatically turned on when you are in a scanning view. You need to set up the camera so that it switches on when needed and it switches off when not needed anymore. Similarly [BarcodeCount](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) should also be enabled and disabled. For instance, you should switch off the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is not visible anymore (including when the app goes in the background), similarly you want to switch on the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is visible (including when the app goes to the foreground). One way to achieve this is the following: ```js document.addEventListener('pause', () => { camera.switchToDesiredState(Scandit.FrameSourceState.Off); }, false); document.addEventListener('resume', () => { camera.switchToDesiredState(Scandit.FrameSourceState.On); }, false); ``` ## Store And Retrieve Scanned Barcodes The values captured as part of the scanning process are part of the [session](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession), and the session is not accessible outside [BarcodeCountListener.didScan()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan). Therefore, we recommend that you store the values to present a list, for example when the user taps the list icon. To do this, make a copy of [BarcodeCountSession.recognizedBarcodes](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count-session.html#property-scandit.datacapture.barcode.count.BarcodeCountSession.RecognizedBarcodes): ```js const listener = { didScan: (barcodeCapture, session, getFrameData) => { const allRecognizedBarcodes = session.recognizedBarcodes; // Handle barcodes }, }; barcodeCount.addListener(listener); ``` ## Reset Barcode Count Mode When the scanning process is over, you need to reset the mode to make it ready for the next process. This clears the list of barcodes scanned and all the AR overlays. To reset Barcode Count’s scanning process, you need to call the [BarcodeCount.reset()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-count.html#method-scandit.datacapture.barcode.count.BarcodeCount.Reset) method. ```js barcodeCount.reset(); ``` ## List And Exit Callbacks The UI includes two icons (buttons) named “List” and “Exit”. The SDK provides the callbacks so you can add the desired action when those icons are tapped by the user. ```js const viewUiListener = { didTapListButton: (view) => { // Show the current progress but the order is not completed }, didTapExitButton: (view) => { // The order is completed }, }; barcodeCountView.uiListener = viewUiListener; ``` --- ## About MatrixScan Count # About MatrixScan Count import AboutMatrixScanCount from '../../../partials/intro/_about-matrixscan-count.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Find is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Find to best fit your needs. ## Set up a listener on the BarcodeFind mode You may want more fine-grained knowledge over the different events happening during the life of the BarcodeFind mode, such as when the search starts, pauses and stops. To do this, you can directly register a [BarcodeFindListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-find-listener.html#interface-scandit.datacapture.barcode.find.IBarcodeFindListener) on the mode itself. Be aware that these listeners will be called from a background thread. ```js mode.addListener({ didStartSearch() { // The mode was started }, didPauseSearch(foundItems) { // The mode was paused }, didStopSearch(foundItems) { // The mode was stopped after the finish button was clicked }, }); ``` ## UI configuration The [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) will by default show a set of UI elements, which can be optionally hidden: - A play/pause button - A finish button - A searched items carousel - Guidance hints There is also a progress bar but this is hidden by default. Each of these elements can be shown or hidden at will. ```js barcodeFindView.shouldShowCarousel = false; barcodeFindView.shouldShowProgressBar = true; // … ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Find to your application. Implementing MatrixScan Find involves two primary elements: - Barcode Find: The data capture mode that is used for search and find functionality. - A Barcode Find View: The pre-built UI elements used to highlight found items. The general steps are: 1. Initialize the Data Capture Context. 2. Configure the Barcode Find Mode. 3. Setup the BarcodeFindView. 4. Register a listener to be notified with found items 5. Start searching ## Initialize the Data Capture Context The first step to add find capabilities to your application is to initialize the [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Find Mode The main entry point for the Barcode Find Mode is the [BarcodeFind](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind) object. You can configure the supported Symbologies through its [BarcodeFindSettings](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-find-settings.html#class-scandit.datacapture.barcode.find.BarcodeFindSettings), and set up the list of items that you want MatrixScan Find to highlight (e.g. a list of products). For this tutorial, we will set up Barcode Find for tracking EAN13 codes. Change this to the correct symbologies for your use case (e.g. Code 128, Code 39…). First create the settings: ```js const settings = new Scandit.BarcodeFindSettings(); settings.enableSymbology(Scandit.Symbology.EAN13UPCA, true); ``` Then you have to create the list of items that will be actively searched for. In this tutorial, let’s look up two items based on their EAN13 codes. We will attach to the first item some optional information that can be used by the BarcodeFindView to display extra information. ```js const items = [ new Scandit.BarcodeFindItem(new Scandit.BarcodeFindItemSearchOptions("9783598215438"), new Scandit.BarcodeFindItemContent("Mini Screwdriver Set", "(6-Piece)", null)), new Scandit.BarcodeFindItem(new Scandit.BarcodeFindItemSearchOptions("9783598215414"), null) // Item information is optional, used for display only ] ``` Create the mode with the previously created settings and set the items: ```js const mode = new Scandit.BarcodeFind(settings); mode.setItemList(items); ``` ## Setup the BarcodeFindView MatrixScan Find’s built-in AR user interface includes buttons and overlays that guide the user through the searching process. By adding a [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView), the scanning interface (camera preview and searching UI elements) will be added automatically to your application. The BarcodeFindView appearance can be customized through [BarcodeFindViewSettings](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-find-view-settings.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindViewSettings): - Colors of dots in augmented reality overlay - Enable sound and haptic alerts ```js const viewSettings = new Scandit.BarcodeFindViewSettings(); ``` Construct a new BarcodeFindView. The BarcodeFindView is automatically added to the provided parent view. ```js const barcodeFindView = new Scandit.BarcodeFindView({ context: DataCaptureContext.sharedInstance, barcodeFind: mode, viewSettings }); barcodeFindView.connectToElement(htmlElement); ``` ## Register a listener to be notified with found items The BarcodeFindView displays next to its shutter button a handy “finish” button. Register a [BarcodeFindViewUiListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-find-view.html#interface-scandit.datacapture.barcode.find.ui.IBarcodeFindViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```js barcodeFindView.barcodeFindViewUiListener = { didTapFinishButton(foundItems) { // This method is called when the user presses the // finish button. It returns the list of all items that were found during // the session. }, }; ``` ## Start searching As soon as everything is set up, control the [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) to start the search. ```js barcodeFindView.startSearching(); ``` This is the equivalent of pressing the “Play” button programmatically. It will start the search process, turn on the camera and hide the item carousel. --- ## About MatrixScan Find # About MatrixScan Find import AboutFind from '../../../partials/intro/_about-matrixscan-find.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Pick is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Pick to best fit your needs. ## BarcodePick Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodePick` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodePickViewListener`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-pick-view.html#interface-scandit.datacapture.barcode.pick.IBarcodePickViewListener) on the view itself, keeping in mind that these listeners are called from a background thread. ```js const viewListener = { didStartScanning(view) { // The view started scanning }, didFreezeScanning(view) { // The view was frozen }, didPauseScanning(view) { // The view was paused }, didStopScanning(view) { // The view stopped scanning }, }; barcodePickView.addListener(viewListener); ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Pick to your application. Implementing MatrixScan Pick involves two primary elements: - Barcode Pick: The data capture mode that is used for scan and pick functionality. - A Barcode Pick View: The pre-built UI elements used to highlight items to be picked. The general steps are: - Initializing the Data Capture Context - Configuring the Barcode Pick Mode - Setup the Barcode Pick View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the Data Capture Context with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Pick Mode The main entry point for the Barcode Pick Mode is the `BarcodePick` object. You can configure the supported Symbologies through its [`BarcodePickSettings`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-pick-settings.html), and set up the list of items that you want MatrixScan Pick to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```js const settings = new Scandit.BarcodePickSettings(); settings.enableSymbology(Scandit.Symbology.EAN13UPCA, true); ``` Then you have to create the list of items that will be picked and quantity to be picked for each item. ```js const items = [ new Scandit.BarcodePickProduct(new Scandit.BarcodePickProductIdentifier("9783598215438"), new Scandit.BarcodePickProductQuantityToPick(3)), new Scandit.BarcodePickProduct(new Scandit.BarcodePickProductIdentifier("9783598215414"), new Scandit.BarcodePickProductQuantityToPick(3)), ]; ``` Create the mode with the previously created settings: ```js const mode = new Scandit.BarcodePick(settings); ``` ## Setup the `BarcodePickView` MatrixScan Pick’s built-in AR user interface includes buttons and overlays that guide the user through the scan and pick process. By adding a [`BarcodePickView`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-pick-view.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickView), the scanning interface is added automatically to your application. The `BarcodePickView` appearance can be customized through [`BarcodePickViewSettings`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-pick-view-settings.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickViewSettings) to match your application’s look and feel. The following settings can be customized: * Colors of dots in augmented reality overlay * Enable sound and haptic alerts * Guidelines text * Showing hints * Finish button * Pause button * Zoom button * Loading Dialog ```js const viewSettings = new Scandit.BarcodePickViewSettings(); // ... ``` Construct a new `BarcodePickView`. The `BarcodePickView` is automatically added to the provided parent view. ```js const barcodePickView = new Scandit.BarcodePickView({ context: DataCaptureContext.sharedInstance, barcodePick: mode, settings: viewSettings }); barcodePickView.connectToElement(document.getElementById('html-element-id')); ``` ## Register the Listener The `BarcodePickView` displays a **Finish** button next to its shutter button. Register a [BarcodePickViewUiListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/barcode-pick-view.html#interface-scandit.datacapture.barcode.pick.ui.IBarcodePickViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```js barcodePickView.uiListener = { didTapFinishButton(foundItems) { // This method is called when the user presses the finish button. // It returns the list of all items that were found during the session. }, }; ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `BarcodePickView.start()`. ```js barcodePickView.start(); ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Pick # About MatrixScan Pick MatrixScan Pick is a pre-built UI that uses augmented reality overlays to highlight specific items that need to be picked. Whereas MatrixScan AR is fully customizable, MatrixScan Pick is a pre-built solution that allows you to add a scan and pick experience with augmented reality to an existing native app, with just a few lines of code. MatrixScan Pick is implemented through functionality provided by [`BarcodePick`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/barcode-pick.html). ## UI Overview * MatrixScan Pick is inspired by the familiar paradigm of a camera, including a shutter button that the user operates in order start and pause the scanning view. The Finish button is used at any time to exit the workflow. * It highlights items with obvious and colorful visual dots on screen. * When paused, MatrixScan Pick freezes the display at the last view, even if the device is moved. The Play button transitions back to the live view. * Textual guidance is displayed from the beginning of the session and as the workflow progresses, informing of the user of changes in item status (i.e. Detected, Ignored, To-Pick, or Picked). * Status icons can be defined to provide further information to users for a given barcode. In the live view, the icons are displayed but not tappable. In the frozen view, the status icons can be tapped and expanded to provide additional textual information. * The Quick Start Guide takes you through the process to install the full UI. However, you can then customize it by choosing to remove any elements on the screen except for the AR overlays. This allows you to create custom UIs suitable for your own workflows. ## Supported Symbologies MatrixScan Find supports all [symbologies](../barcode-symbologies.mdx) **except** DotCode, MaxiCode and postal codes (KIX, RM4SCC). If you are not familiar with the symbologies that are relevant for your use case, you can use capture presets that are tailored for different verticals (e.g. retail, logistics, etc.). --- ## Get Started # Get Started The parser parses data strings, e.g. as found in barcodes, into a set of key-value mappings. In this guide, you will know briefly how to use a parser and what types of parser are currently supported by Scandit. These data formats are supported: [Health Industry Bar Code (HIBC)](https://docs.scandit.com/data-capture-sdk/cordova/parser/hibc.html), [GS1 Application Identifier (parser/AI) system](https://docs.scandit.com/data-capture-sdk/cordova/parser/gs1ai.html) and [Swiss QR Codes](https://docs.scandit.com/data-capture-sdk/cordova/parser/swissqr.html), [VIN Vehicle Identification Number](https://docs.scandit.com/data-capture-sdk/cordova/parser/vin.html), [IATA Bar Coded Boarding Pass (BCBP)](https://docs.scandit.com/data-capture-sdk/cordova/parser/iata-bcbp.html), [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/cordova/parser/epc.html). More data formats will be added in future releases. Please contact us if the data format you are using is not yet supported, or you want to use the parser on a currently unsupported platform. ## Format-Specific Documentation - [Supported Data Formats](https://docs.scandit.com/data-capture-sdk/cordova/parser/formats.html) - [HIBC](https://docs.scandit.com/data-capture-sdk/cordova/parser/hibc.html) - [GS1 AI](https://docs.scandit.com/data-capture-sdk/cordova/parser/gs1ai.html) - [GS1 Digital Link](https://docs.scandit.com/data-capture-sdk/cordova/parser/gs1-digital-link.html) - [Swiss QR](https://docs.scandit.com/data-capture-sdk/cordova/parser/swissqr.html) - [VIN](https://docs.scandit.com/data-capture-sdk/cordova/parser/vin.html) - [IATA BCBP](https://docs.scandit.com/data-capture-sdk/cordova/parser/iata-bcbp.html) - [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/cordova/parser/epc.html) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: First of all, include the `ScanditParser` library and its dependencies to your project, if any. ## Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### New Features #### Barcode * Added the SelectionMode API to replace the SparkScan target-mode APIs and `ScanIntention.smartSelection`: Set `selectionMode` (off/on/auto) in the `BarcodeCaptureSettings` and `SparkScanSettings` to control whether an aimed-at barcode is scanned automatically or requires explicit selection. #### Id * Added Irish Garda Age Card as `RegionSpecificSubtype.IrelandAgeCard`. * Added double-sided support for the Oman residence card. * Added single-sided support for extraction of issue date and birth date from the 2025 NYC Municipal ID. #### Smart Label Capture * Extended VIN label capture to also scan Code 128 barcodes (in addition to QR, Code 39, and Data Matrix) via `createVinLabelDefinition()`. * Extended LabelCapture to accept label definitions where both "barcode" and "text" field types use the "semantics" feature simultaneously; previously this was restricted to only one field type at a time. ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Smart Label Capture * Improved Receipt Scanning efficiency by optimizing receipt image processing before extraction. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. * Updated `SymbologyDescription.forIdentifier` to return `null` for unrecognized identifiers (e.g. `"EAN-8"` instead of `"ean8"`); previously such input was silently mapped to `Codabar`. ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in item-based scanning. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Id * Fixed an issue where cropped document images were rotated when Frame Image was also enabled. * Corrected the orientation of cropped Visa document images that were being rotated incorrectly when scanned using a single-frame image source. * Fixed parser handling of non-standard Surrey BC AAMVA barcodes that were incorrectly returning "Invalid Format". #### Smart Label Capture * Fixed a memory leak in LabelCapture. * Fixed a bug where setting `valueRegexes` or `anchorRegexes` to null in frameworks was incorrectly treated the same as setting them to an empty list; they now correctly fall back to the definition type's defaults. #### Core * Fixed a TypeError: `frameSource.setNativeFrameSourceIsBeingCreated is not a function` thrown when calling `DataCaptureContext.setFrameSource()` with an `ImageFrameSource` on Cordova, Capacitor, and React Native SDKs. * Fixed a Cordova Android issue with cordova-android 15.x where HTML overlays in the WebView could appear hidden behind the camera preview. * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a crash when the `DataCaptureContext` singleton was initialized more than once. ### Deprecations #### Barcode * The SparkScan target-mode APIs and `ScanIntention.smartSelection` are deprecated in favour of selectionMode. ## 8.4.1 **Released**: June 23, 2026 ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in SparkScan when using the item-based API. #### Id * Fixed an issue where cropped document images were rotated when they are recovered using the getFrame API. * Resolved a duplicate Objective-C class registration that could trigger spurious casting failures or crashes when an app links both ScanditCaptureCore and ScanditIdCapture. #### Core * Fixed a TypeError: `frameSource.setNativeFrameSourceIsBeingCreated is not a function` thrown when calling `DataCaptureContext.setFrameSource()` with an `ImageFrameSource` on Cordova, Capacitor, and React Native SDKs. ## 8.4.0 **Released**: May 18, 2026 ### New Features #### Barcode * Added `dotRadius` property to `BarcodeBatchBasicOverlay` to allow customizing the size of dots when using the Dot overlay style. * Added custom view support for barcode pick highlighting in JavaScript frameworks. * Added support for PDF417 in the Barcode Generator. #### Id * Added support for reading the vehicle table on the back of New Zealand driving licences, with the latest expiry date returned; supported vehicle classes are 1–6, including L=learner and R=restricted variants. * Added support for new versions of USA, California – Driver's License; USA, North Carolina – Driver's License; USA, Texas – Driver's License; and USA, Oklahoma – Driver's License. #### Smart Label Capture * Added the LabelCapture simple sample for Cordova. #### Core * Redesigned `ZoomSwitchControl` to support multiple configurable zoom levels; the control now displays as a compact button that expands to show all available zoom levels, automatically filtered to those supported by the device hardware. * Added a new `PinchToZoom` gesture. * Added Swift Package Manager support to Cordova plugins for iOS. ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. #### Core * Updated mbedtls from version 3.6.5 to 3.6.6. ### Bug Fixes #### Barcode * Fixed an issue in `BarcodeCount` where the floating shutter button was not visible after setting `shouldShowFloatingShutterButton` to `true`. * Fixed an issue preventing `BarcodeFind` from finding binary barcodes. * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. * Fixed an issue where `BarcodeCountView` would display incorrectly after rotating the device when a sibling view was present in the same parent view. * Fixed an unnecessary second scan callback that occurs after freezing barcode recognition. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed an issue where the Smart Scan Selection aimer would become too small when scan-area margins restricted the visible scan area; the aimer is now sized relative to the view, keeping a consistent on-screen size regardless of margins. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. #### Id * Fixed an issue where the US Permanent Residence Card was not processed through the VizMrz flow. * Fixed an issue where AAMVA verification was being performed even when no AAMVA document types were enabled in the accepted documents. #### Smart Label Capture * Fixed a memory leak in LabelCapture * Fixed an issue where the validation flow viewfinder was not displayed. * Fixed a race condition in the validation flow. * Fixed a bug where the label capture validation flow overlay sometimes did not reflect label capture settings when reused. * Fixed a bug that caused error messages in `DataCaptureView` to be rendered partially out-of-view. * Fixed a rare race condition in Label Capture. * Added `.asDate()` support to `ExpiryDate` and `PackingDate` label fields when the text is provided as manual input or as an Adaptive-Recognition-Engine response. * Fixed a bug where the receipt scanning overlay and validation flow overlay could not be used on the same LabelCapture mode instance. #### Core * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. * Fixed a rare crash when opening the camera. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed custom sound not working in Barcode Find on Android. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. * Fixed a Cordova Android issue with cordova-android 15.x where HTML overlays in the WebView could appear hidden behind the camera preview. * Fixed an issue on Cordova Android where AR overlay views (such as bubbles in MatrixScan-based samples) could become unresponsive to taps after the app was minimized and reopened while the camera preview was frozen. * Fixed a rare crash when starting camera capture while under memory pressure. ## 8.3.1 **Released**: April 14, 2026 ### Bug Fixes #### Smart Label Capture * Fixed the validation flow to accept dates in more formats when manually entered * Fixed a race condition in the validation flow ## 8.3.0 **Released**: March 26, 2026 ### New Features #### Barcode * Added support for composite codes in SparkScan * Added a SparkScan ListBuilding sample for Cordova #### Id * Added support for OCR scanning of the 2026 version of Victoria mobile driver licenses * Added IdCaptureSettings.anonymizeDefaultFields setting that controls whether the SDK applies default anonymization rules for specific document types and regions #### Smart Label Capture * Fixed a rare race condition #### Core * Added Camera-related APIs for macro mode, torch, accessibility hints, as well as ImageBuffer and Timestamp for FrameData. * Added shouldShowZoomNotification and setProperty to DataCaptureView * Added new SparkScan APIs related to feedback, scanning mode change, and periscope mode. * Added BarcodeFilterSettings public constructor and exposed excludedSymbolCounts property for JavaScript frameworks * Added BarcodeCount-related APIs for BarcodeCountNotInListActionSettings, BarcodeCountToolbarSettings, BarcodeCountMappingFlowSettings, status mode and accessibility properties on BarcodeCountView, BarcodeCountStatusProvider with status items and callbacks, cluster support, capture list completion listener, and session update listener * Added moduleCountX and moduleCountY to Barcode API ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Improved speed of MatrixScan Count scanning phase for mid- and high-end devices ### Bug Fixes #### Barcode * Fixed an issue in BarcodeCount where the floating shutter button was not visible after setting shouldShowFloatingShutterButton to true. * Fixed a bug that was causing BarcodeFind to render barcodes filtered out by the Transformer as if they were valid targets. * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. #### Id * Fixed BarcodeDictionary anonymization setting for iOS and Web * Fixed support for UAE Esaad card * Sanitized name fields on ACT driver license to split FullName and populate first and last name properties * Added support for scanning MRZ from the back of Argentinian DN when using `FullDocumentScanner` * Fixed misplaced MRZ anonymization on FullFrame images. #### Smart Label Capture * Fixed an issue in the `LabelCaptureValidationFlowOverlay` when using it with Jetpack Compose that caused focus loss when opening the keyboard * Added `LabelCaptureValidationFlowOverlay.ShouldHandleKeyboardInsetsInternally` for cases when customers don't want to follow official Android edge-to-edge and inset guidelines #### Core * Fixed Cordova iOS compilation error due to missing header files * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.2.1 **Released**: March 5, 2026 ### Bug Fixes #### Id * Sanitized name fields on ACT DL. Splits FullName to populate first and last name properties #### Smart Label Capture * Fixed LabelCaptureValidationFlowOverlay possible issue with Jetpack Compose that caused focus loss when opening the keyboard * Added LabelCaptureValidationFlowOverlay::ShouldHandleKeyboardInsetsInternally in case customers don't want to follow official Android guidelines for edge-to-edge and insets * Fixed a rare race condition ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Barcode * Added new getFeedbackForScannedItem method to SparkScanFeedbackDelegate * Added BarcodeArResponsiveAnnotation API * Added MatrixScanArSimpleSample on Cordova * Added MatrixScan AR mode to Cordova framework * Added some missing BarcodePick APIs to React-Native, Capacitor and Cordova #### Smart Label Capture * [Smart Label Capture](/sdks/cordova/label-capture/intro.md) is now available on .NET for Android. It enables multi-modal data capture, extracting barcode and text data from labels simultaneously and making complex data entry up to 7 times faster. Ideal for labels containing serial numbers, weights, or expiry dates, it improves accuracy, reduces errors, and prevents revenue loss from incorrect information. #### Core * Added Electronic Product Code (EPC) data format ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes * Barcode Generator: Improved DataMatrix encoding efficiency, which depending on input data may result in smaller generated codes ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed BarcodeCount Scan Preview issues including: fixed an issue where preview barcodes were used to populate the scanning list, the correct feedback is played when a barcode not in list is scanned, fixed an issue where scanning was not possible after the app was put in background, and corrected highlight orientation in landscape * Added cameraStateOnStop property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed an issue where the successful hint in BarcodeFind is not displayed * Fixed the missing found item icon in the MatrixScan Find carousel #### Id * Fixed an issue affecting MRZ scanning performance when using the user facing camera in portrait mode on Android * Fixed a memory issue leading to a persistent black screen during ID Capture startup * Treated Puerto Rico driver licenses as AAMVA to enforce barcode capture with FullScanner * Fixed a bug that would cause Canada Northwest Territories driver license scans to be incomplete #### Core * Fixed MatrixScanBubble Tap not being triggered in Cordova * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed an issue where some LabelCapture fields were being returned incorrectly on TS frameworks * Fixed a crash in the DataCaptureView overlay management that could occur during rapid view updates. * Fixed a Cordova iOS compilation error due to missing header files ## 8.1.5 **Released**: June 10, 2026 ### Bug Fixes #### Barcode * Fixed a memory leak in item-based scanning. #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed a TypeError: `frameSource.setNativeFrameSourceIsBeingCreated is not a function` thrown when calling `DataCaptureContext.setFrameSource()` with an `ImageFrameSource` on Cordova, Capacitor, and React Native SDKs. * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a rare native crash (SIGABRT in BitTube::recvObjects) that could occur on Android during camera preview rendering. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. #### Core * Fixed a rare issue that was causing a crash when the app moved to the background. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed crashes caused by RuntimeExceptions thrown by OEM camera code that are not part of the standard Android Camera API contract; these exceptions are now caught and logged instead of crashing. ## 8.1.3 **Released**: March 25, 2026 ### Bug Fixes #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.1.2 **Released**: March 9, 2026 ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session #### Smart Label Capture * Fixed a rare race condition ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Id * Fixed a memory issue leading to a persistent black screen during ID Capture startup #### Core * Fixed a crash in the DataCaptureView overlay management that could occur during rapid view updates * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Smart Scan Selection is now available in Barcode Capture. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * [SparkScan](/sdks/cordova/sparkscan/intro.md) is not limited to only barcodes anymore, but can also scan items - in other words any combinations of barcodes and text present on a target to be scanned. The feature is available in beta at the moment, please contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out. * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. #### Id * Added NationalityISO property that maps results from Nationality field to country ISO code * Added RejectionDiagnosticJSON property to CapturedId to report debug info during Timeout rejections * Added support for new California DL, new South Carolina DL, Arizona Medical Marijuana Card, Kuwait Civil card, and new Texas DL * Our SDK can now scan the following documents both in single-side and double-side mode: - All Mexican DLs - Mexican Voter Cards ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the [“strict" symbology extension](../symbology-properties#symbology-extension-descriptions) ### Behavioral Changes #### Barcode * Enabling the [“ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 (“Missing Resource”) ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Fixed a bug in the default color of BarcodeCapture highlights * Fixed an issue where popover annotations with HIGHLIGHT_TAP_AND_BARCODE_SCAN trigger could not be opened again * Fixed an issue in BarcodeSequence where camera would not be ON in portrait * Fixed an issue where SparkScan mini preview would sometimes stay in regular when entering target mode * Fixed the app becoming unresponsive after being in the background for extended periods * Added the `cameraStateOnStop` property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed an issue where the successful notification in BarcodeFind was not displayed #### Id * Fixed an issue where front expiry date anonymization rectangle is erroneously drawn on front and back * Fixed a bug that prevented VizResult anonymization of the following fields: additionalAddressInformation, bloodType, employer, fathersName, issuingAuthority, maritalStatus, mothersName, placeOfBirth, profession, race, residentialStatus * Fixed a bug concerning return complete instead of cropped images on the back of EU driving licenses #### Core * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only * Fixed an issue where barcode scanning would permanently stop after the app returned from background, particularly when camera permission dialogs were shown during initialization ## 8.0.1 **Released**: January 14, 2026 ### Bug Fixes #### Barcode * Fixed an issue where the successful hint in BarcodeFind was not displayed * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. #### Barcode * Updated the Gradle version for all sample applications to 8.14.3. * `BarcodeBatchBasicOverlay` and `BarcodeBatchBasicOverlayListener` now allow for nullable brushes. #### ID * Added `ElementsToRetain` to `MobileDocumentScanner`: The set of data elements that the application intends to retain from scanned mobile documents. This information is used to set the `IntentToRetain` flag in ISO 18013-5 mdoc requests, which is required for legal compliance with data protection standards. An empty set indicates no elements will be retained, and `IntentToRetain` will be set to `false` for all fields. * ID Capture now supports full-frame anonymization. * The result of `decodeMobileDriverLicenseViz`, which is currently returned as part of the `VizResult` within `CapturedId`, will now be provided through a new field named `mobileDocumentOcr`. * Added `CapturedId::isCitizenPassport`, which indicates whether the passport was issued to a citizen of the issuing country. Returns `false` for travel documents such as refugee, stateless, or alien passports, and for any passports issued by organizations rather than states. * The following Chinese travel permits now extract VIZ + MIZ data during double-sided scanning flows: * CT - Taiwan Residents Mainland Travel Permit * W - Mainland Residents Exit-Entry Permit to and from Hong Kong and Macao * CD - Mainland Residents Entry-Exit Permit to and from Taiwan ### Behavioral Changes #### Barcode * Symbology `RM4SCC` has been renamed to `ROYAL_MAIL_4STATE`. * Changed the default highlight brush in SparkScan and Barcode Capture. #### ID * The configuration for the following documents has been changed as detailed below: * Australian mobile driver licenses (mDL) are now treated as normal documents, with no separate mode. * US Green Cards are now treated as residence permits. * Removed the deprecated API `DateResult::toDate`. Use `DateResult::toLocalDate` or `DateResult::toUtcDate` instead. * `fullName` now an optional field on all `IdCapture` result types and `capturedMrz` now an optional field on `MrzeeeeeResult`. ### Bug Fixes #### ID * Fixed a bug that could get the scanner stuck when scanning a US passport card. ### Deprecations #### Core * `VideoResolution::Auto` is now deprecated. Please use the capture mode's `recommendedCameraSettings` for the best results. ## 7.6.7 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/cordova/release-notes) --- ## Advanced Configurations # Advanced Configurations SparkScan is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are some cases where you might want to customize the behavior of SparkScan. This guide will show you how to add additional capabilities and further customize SparkScan to best fit your needs. ## Advanced Capabilities ### Hardware Button Control Allowing the end user to control the scanner with hardware buttons can be useful if your users typically wear gloves. It can also improve ergonomics in some workflows. SparkScan offers a built-in API to let you do this via [`SparkScanViewSettings.hardwareTriggerEnabled`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled). ### Trigger Error State You may want to introduce logic in your app to show an error message when scanning specific barcodes (e.g. barcodes already added to the list, barcodes from the wrong lot etc.). SparkScan offers a built-in error state you can easily set to trigger an error feedback prompt to the user. You will be able to customize: - The text message - The timeout of the error message: the scanner will be paused for the specified amount of time, but the user can quickly restart the scanning process by tapping the trigger button. :::tip A high timeout (>10s) typically requires the users to interact with the UI to start scanning again. This is a good choice when you want to interrupt the scanning workflow (e.g. because a wrong barcode is scanned and some actions need to be performed). A small timeout (\ { if (isValidBarcode(barcode)) { return new Scandit.SparkScanBarcodeSuccessFeedback(); } else { return new Scandit.SparkScanBarcodeErrorFeedback( 'This code should not have been scanned', 60 * 1000, Scandit.Color.fromHex('#FF0000'), new Scandit.Brush(Scandit.Color.fromHex('#FF0000'), Scandit.Color.fromHex('#FF0000'), 1), ); } }, }; ``` You can have different error states triggered by different logic conditions. For example you can trigger an error state when a wrong barcode is scanned, and another one when a duplicate barcode is scanned. These errors can show different colors and have different timeouts. This error state for a code that should not have been scanned. This error state for a code that has been scanned more than once. ### Reject Barcodes To prevent scanning unwanted barcodes (like those already listed or from incorrect lots), use SparkScan’s built-in error state. Setting the [`SparkScanBarcodeErrorFeedback.resumeCapturingDelay`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/spark-scan-barcode-feedback.html#property-scandit.datacapture.barcode.spark.feedback.Error.ResumeCapturingDelay) parameter to 0 allows the user to continue scanning immediately without pausing on rejected codes. ## UI Customization :::tip Please refer to [SparkScanView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) for the full list of parameters. ::: import Customization from '../../../partials/advanced/_sparkscan-customization.mdx'; ## Workflow Options This section explains all the available options to configure SparkScan to best fit your case, in case you found something that didn't work well in the default configuration (that remains our recommended option). Developers can set a combination of scanning mode, scanning behavior and camera preview behavior - defining the initial state of the scanner. This can be done by setting the default scanning mode ([`SDCSparkScanViewSettings.defaultScanningMode`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.DefaultScanningMode)). This combination allows for flexible configurations to suit different scanning needs. ### Scanning Mode The scanning mode determines the programmatic presence of an aimer in the preview to help with precision scanning. | Mode | Description | | ----------- | --------------------------------------------------- | | **Default** | Generally recommended. This mode will display a small camera preview to aid with aiming. The preview size and zoom level can be adjusted as needed. User can aim easily at the intended barcode. | | **Target** | This mode will always add an aimer to the camera preview to precisely select the barcode to scan. This is recommended only when selecting among many close barcodes is the common task. | :::tip Even in the *Default* mode, SparkScan will automatically show an aimer when multiple barcodes are present in the view and no clear intention from the user to scan a single one is recorded ([`SDCSparkScanSettings.ScanIntention`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/spark-scan-settings.html#property-scandit.datacapture.barcode.spark.SparkScanSettings.ScanIntention)). Enabling the *Target* mode will simply force this "precision selection" state to be on at all time. ::: ### Scanning Behavior The scanning behavior determines how barcodes are scanned - one at a time or continuously. | Behavior | Description | | ------------------- | ---------------------------------------------------------- | | **Single scan** | Scan one barcode at a time. The user needs to trigger the scanner every time to scan a barcode. This allows for a more controlled scanning and lower battery consumption. | | **Continuous scan** | Scan barcodes consecutively. The user needs to trigger the scanner once and barcodes will be scanned without any further interaction before each scan. This allows for a smoother experience when multiple barcodes need to be scanned consecutively. | :::tip Users can enable continuous scanning by holding down the trigger button. This gesture can be disabled ([`SDCSparkScanViewSettings.holdToScanEnabled`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HoldToScanEnabled)). ::: ### Preview Behavior The preview behavior determines how the camera preview behaves when the scanner is not actively scanning. | Behavior | Description | | -------------- | -------------------------- | | **Default** | Preview fades away when the scanner is off. This lets the user check important information displayed by the app and reduces battery consumption. | | **Persistent** | Preview remains visible, but darkened, even when the scanner is off. This is useful for scenarios where you want to select a barcode (among many) or need to look through the preview at all times (to ensure the right scan) - especially if used in conjunction with the target mode. | ### Configuring the default scanning mode Combine a scanning mode, scanning behavior, and preview behavior and assign it to `SparkScanViewSettings.defaultScanningMode`. For example, to start in continuous scanning with the preview always visible: ```js const sparkScanViewSettings = new Scandit.SparkScanViewSettings(); sparkScanViewSettings.defaultScanningMode = new Scandit.SparkScanScanningModeDefault( Scandit.SparkScanScanningBehavior.Continuous, // or .Single Scandit.SparkScanPreviewBehavior.Persistent, // or .Default ); ``` Pass both arguments — the single-argument constructor is deprecated. Use `Scandit.SparkScanScanningModeTarget` instead of `SparkScanScanningModeDefault` to force the aimer (target mode). --- ## Get Started # Get Started In this guide you will learn step-by-step how to add SparkScan to your application. The general steps are: 1. Initialize the Data Capture Context. 2. Configure the Spark Scan Mode. 3. Create the SparkScanView with the desired settings and bind it to the application’s lifecycle. 4. Register the listener to be informed when new barcodes are scanned and update your data whenever this event occurs. ## Prerequisites - The latest stable version of [Node.js and npm](https://nodejs.org/en/download/) (required only if including and building the SDK as part of an app, instead of just including it as an external resource from a CDN in HTML). - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). - If you have not already done so, see [this guide](../add-sdk.md) for information on how to add the Scandit Data Capture SDK to your project :::note Devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/cordova/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the SparkScan Mode The SparkScan Mode is configured through [`SparkScanSettings`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/spark-scan-settings.html#class-scandit.datacapture.barcode.spark.SparkScanSettings) and allows you to register one or more listeners that are informed whenever a new barcode is scanned. For this tutorial, we will set up SparkScan for scanning EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```js const settings = new Scandit.SparkScanSettings(); settings.enableSymbologies([Scandit.Symbology.EAN13UPCA]); ``` Next, create a SparkScan instance with the settings initialized in the previous step: ```js const sparkScan = new Scandit.SparkScan(settings); ``` ## Setup the Spark Scan View The SparkScan built-in user interface includes the camera preview and scanning UI elements. These guide the user through the scanning process. The [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/spark-scan-view-settings.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) appearance can be customized through [`SparkScanViewSettings`](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/spark-scan-view-settings.html#class-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings). ```js const viewSettings = new Scandit.SparkScanViewSettings(); // setup the desired appearance settings by updating the fields in the object above ``` See the [SparkScan Workflow Options](./advanced.md#workflow-options) section for more information. By adding a `SparkScanView`, the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a `SparkScanView` to your view hierarchy. Construct a new SparkScan view. The `SparkScan` view is automatically added to the provided parentView: ```js const sparkScanView = Scandit.SparkScanView.forContext(DataCaptureContext.sharedInstance, sparkScan, viewSettings); ``` Additionally, make sure to call [SparkScanView.stopScanning()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.StopScanning) in your app state handling logic. You have to call this for the correct functioning of the [SparkScanView](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView). ```js componentWillUnmount() { sparkScanView.stopScanning(); } handleAppStateChange = async (nextAppState) => { if (nextAppState.match(/inactive|background/)) { sparkScanView.stopScanning(); } } ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [SparkScanListener](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface and register the listener to the SparkScan mode. ```js // Register a listener object to monitor the spark scan session. const listener = { didScan: (sparkScan, session, getFrameData) => { // Gather the recognized barcode const barcode = session.newlyRecognizedBarcode[0]; // Handle the barcode }, }; sparkScan.addListener(listener); ``` [SparkScanListener.didScan()](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/spark-scan-listener.html#method-scandit.datacapture.barcode.spark.ISparkScanListener.OnBarcodeScanned) is called when a new barcode has been scanned. This result can be retrieved from the first object in the provided barcodes list: [SparkScanSession.newlyRecognizedBarcode](https://docs.scandit.com/data-capture-sdk/cordova/barcode-capture/api/spark-scan-session.html#property-scandit.datacapture.barcode.spark.SparkScanSession.NewlyRecognizedBarcode). Please note that this list only contains one barcode entry. ## Scan Some Barcodes Now that you’re up and running, go find some barcodes to scan. Don’t feel like getting up from your desk? Here’s a [handy pdf of barcodes](https://github.com/Scandit/.github/blob/main/images/PrintTheseBarcodes.pdf) you can print out. --- ## About SparkScan # About SparkScan SparkScan is our pre-built smartphone scanning interface designed for high-performance barcode scanning. It fits on top of any smartphone application, providing an intuitive user interface for simple, fast and ergonomic scanning in scan-intensive workflows such as inventory management in retail, or goods receiving in logistics. SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs. ## UI Overview The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience. Two main elements compose the UI: ![SparkScan UI](/img/sparkscan/features_web.png) - **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc). - **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space. There are additional UI elements available for displaying additional scanning modes, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section. ## Workflow Description When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use. To start scanning, the user can simply tap on it. When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app). In the default configuration: - Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away. - Tapping on the trigger button or the mini preview will restart immediately the scanner. Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state. If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released. List building use case using SparkScan. The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field. But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more. ## Supported Symbologies SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx). ## AI-Powered Features SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide. --- ## Installation import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Installation This page describes how to integrate the Scandit Data Capture SDK into your Flutter project. ## Prerequisites - The latest stable version of the [Flutter SDK](https://pub.dev/publishers/scandit.com/packages) (for example through the latest Android Studio). - A project with: - minimum iOS deployment target of 15.0 or higher - an Android project with target SDK version 23 (Android 6, Marshmallow) and Kotlin 1.7.21 or higher (version 24 or higher for ID Capture). - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). :::tip Android devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ### Internal Dependencies import InternalDependencies from '../../partials/get-started/_internal-deps-no-label-capture.mdx'; ## Get a License Key 1. [Sign up](https://ssl.scandit.com/dashboard/sign-up?p=test) or [Sign in](https://ssl.scandit.com/dashboard/sign-in) to your Scandit account 2. Create a project 3. Create a license key If you have a paid subscription, please reach out to [Scandit Support](mailto:support@scandit.com) if you need a new license key. ## Add the SDK Currently we support adding the Scandit Data Capture SDK Flutter plugins to your project in two ways. The simplest way is to use the [pub.dev](https://pub.dev/) registry, alternatively you can manually download the plugins and add them to your project. ### Create a new project If you do not have a Flutter project yet that you’ll use, you should create a new one using your IDE of choice. ### Add the SDK from pub.dev To add our plugins from the _pub.dev_ registry, you need to open the `pubspec.yaml` file located inside the app folder, and add the required Scandit plugin(s) as listed under [interal dependencies](#internal-dependencies). In the following snippet we’re adding multiple plugins for different functionalities, but you can add only the ones you need. ```yml dependencies: flutter: sdk: flutter scandit_flutter_datacapture_barcode: scandit_flutter_datacapture_text: scandit_flutter_datacapture_parser: scandit_flutter_datacapture_id: ``` ### Add the SDK manually After you download the [archive](https://ssl.scandit.com/dashboard/downloads) containing all the plugins, unzip the archive. It includes the available Flutter plugins, including the `scandit-flutter-datacapture-core` plugin that all other plugins depend on. Move the required plugins to some subdirectory within your app folder (e.g. to `libs/`) and then open the `pubspec.yaml` file located inside the app folder. Add required Scandit plugin(s) under dependencies. In the following snippet we’re adding multiple plugins for different functionalities, but you can add only the ones you need. ```yml dependencies: flutter: sdk: flutter scandit_flutter_datacapture_barcode: path: libs/scandit-flutter-datacapture-barcode scandit_flutter_datacapture_parser: path: libs/scandit-flutter-datacapture-parser scandit_flutter_datacapture_id: path: libs/scandit-flutter-datacapture-id ``` :::tip You don’t need to add the dependency to the `scandit-flutter-datacapture-core` plugin in the `pubspec.yaml`. However, as all the other Scandit Flutter plugins depend internally on it, you still have to copy it to the same location. ::: ### Install Scandit Data Capture SDK Flutter plugin(s) Run from terminal: ```sh flutter pub get ``` ### iOS Setup For iOS development, Flutter uses CocoaPods to manage native dependencies. You'll need to set up Scandit's private CocoaPods repository: **Important:** This project uses Scandit's private CocoaPods repository. First-time setup: ```sh # Add Scandit's private CocoaPods repository (one-time setup) pod repo add scandit-private-specs https://github.com/Scandit/scandit-cocoapods-specs.git # Navigate to iOS directory and install dependencies cd ios && pod install && cd .. ``` :::note The public CocoaPods trunk repository is becoming read-only. Scandit has migrated to a private CocoaPods specs repository to ensure continued support and updates for iOS framework integrations. The repository is publicly accessible at https://github.com/Scandit/scandit-cocoapods-specs. **Troubleshooting**: If you encounter issues: - Verify the repo is added: `pod repo list | grep scandit-private-specs` - Update the repo: `pod repo update scandit-private-specs` ::: ## Additional Information ### Android Configuration On Android, the Scandit SDK uses content providers to initialize the scanning capabilities properly. If your own content providers depend on the Scandit SDK, choose an **initOrder** lower than 10 to make sure the SDK is ready first. If not specified, **initOrder** is zero by default and you have nothing to worry about. Check [the official `` documentation](https://developer.android.com/guide/topics/manifest/provider-element). ### Camera Permissions When using the Scandit Data Capture SDK you will want to set the camera as the frame source for various capture modes. On Android, you have to request camera permissions in your own application before starting scanning. To see how you can achieve this, take a look at our [samples](https://github.com/Scandit/datacapture-flutter-samples). Remember that, if you want to use the camera as the frame source for barcode, text and label capture, you need to set the “Privacy - Camera Usage Description” field in the `Info.plist` file for iOS. import OSSLicense from '../../partials/_third-party-licenses-js.mdx'; --- ## Agent Skills import SkillsPage from '@site/src/components/SkillsPage'; # Agent Skills for Flutter --- ## Configure Barcode Symbologies # Configure Barcode Symbologies import Intro from '../../../partials/configure-symbologies/_intro.mdx' ## Enable the Symbologies You Want to Read import EnableSymbologies from '../../../partials/configure-symbologies/_enable-symbologies.mdx' The following lines of code show you how to enable scanning Code 128 codes for barcode capture: ```dart var settings = BarcodeCaptureSettings() ..enableSymbology(Symbology.code128, true); ``` import CapturePresents from '../../../partials/configure-symbologies/_capture-presents.mdx' ## Configure the Active Symbol Count Barcode symbologies (such as Code 128, Code 39, Code 93, or Interleaved Two of Five) can store variable-length data. For example, Code 39 can be used to store a string from 1 to 40-50 symbols. There is no fixed upper limit, though there are practical limitations to the code’s length for it to still be conveniently readable by barcode scanners. For performance reasons, the Scandit Data Capture SDK limits the [possible symbol range](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.ActiveSymbolCounts) for variable-length symbologies. If you want to read codes that are shorter/longer than the specified default range or you want to tailor your app to only read codes of a certain length, you need to change the active symbol count of the symbology to accommodate the data length you want to use in your application. The below lines of code show how to change the active symbol count for Code 128 to read codes with 6, 7 and 8 symbols. ```dart var settings = BarcodeCaptureSettings(); var symbologySettings = settings.settingsForSymbology(Symbology.code128); symbologySettings.activeSymbolCounts = {6, 7, 8}; ``` import CalculateSymbolCount from '../../../partials/configure-symbologies/_calculate-symbol-count.mdx' ## Read Bright-on-Dark Barcodes Most barcodes are printed using dark ink on a bright background. Some symbologies allow the colors to be inverted and can also be printed using bright ink on a dark background. This is not possible for all symbologies as it could lead to false reads when the symbology is not designed for this use case. See [symbology properties](../symbology-properties.mdx) to learn which symbologies allow color inversion. When you enable a symbology as described above, only dark-on-bright codes are enabled. If you also want to read bright-on-dark codes, color-inverted reading for that symbology must be enabled ( `SymbologySettings.isColorInvertedEnabled`). The following code shows how to enable color-inverted reading for Code 128: ```dart var settings = BarcodeCaptureSettings(); var symbologySettings = settings.settingsForSymbology(Symbology.code128); symbologySettings.isColorInvertedEnabled = true; ``` ## Enforce Checksums Some symbologies have a mandatory checksum that will always be enforced while others only have optional [checksums](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/checksum.html#enum-scandit.datacapture.barcode.Checksum). Enforcing an optional checksum will reduce false positives as an additional check can be performed. When enabling a checksum you have to make sure that the data of your codes contains the calculated checksum otherwise the codes get discarded as the checksum doesn’t match. All available checksums per symbology can be found in [symbology properties](../symbology-properties.mdx). You can enforce a specific checksum by setting it through [SymbologySettings.checksums](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.Checksums): ```dart var settings = BarcodeCaptureSettings(); var symbologySettings = settings.settingsForSymbology(Symbology.code39) ..checksums = {Checksum.mod43}; ``` ## Enable Symbology-Specific Extensions Some symbologies allow further configuration. These configuration options are available as symbology extensions that can be enabled/disabled for each symbology individually. Some extensions affect how the data in the code is formatted, others allow for more relaxed recognition modes that are disabled by default to eliminate false reads. All available extensions per symbology and a description of what they do can be found in the documentation on [symbology properties](../symbology-properties.mdx). To enable/disable a symbology extension, use [SymbologySettings.setExtensionEnabled()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/symbology-settings.html#method-scandit.datacapture.barcode.SymbologySettings.SetExtensionEnabled). The following code shows how to enable the full ASCII extension for Code 39. ```dart var settings = BarcodeCaptureSettings(); var symbologySettings = settings.settingsForSymbology(Symbology.code39) ..setExtensionEnabled("full_ascii", enabled: true); ``` This extension allows Code 39 to encode all 128 ASCII characters instead of only the 43 characters defined in the standard. The extension is disabled by default as it can lead to false reads when enabled. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Barcode Capture to your application. The general steps are: - Include the ScanditBarcodeCapture library and its dependencies to your project, if any. - Initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. - Create a [barcode capture settings](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and enable the [barcode symbologies](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology) you want to read in your application. - Create a new [barcode capture mode](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance and initialize it with the settings created above. - Register a [barcode capture listener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/flutter/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## Initialize the barcode plugin :::warning Without initializing the barcode plugin, runtime crashes will occur. However, you don’t have to initialize the core plugin, as initializing the barcode plugin already does that for you, as presented in the snippet below. ::: Before accessing anything of the Scandit Data Capture SDK functionality. You have to initialize the barcode plugin. ```dart void main() async { WidgetsFlutterBinding.ensureInitialized(); await ScanditFlutterDataCaptureBarcode.initialize(); runApp(MyApp()); } ``` ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Scanning Behavior Barcode scanning is orchestrated by the [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) [data capture mode](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). This class is the main entry point for scanning barcodes. It is configured through [BarcodeCaptureSettings](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) that will get informed whenever new codes have been recognized. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```dart var settings = BarcodeCaptureSettings() ..enableSymbologies({ Symbology.code128, Symbology.code39, Symbology.qr, Symbology.ean8, Symbology.upce, Symbology.ean13Upca }); ``` If you are not disabling barcode capture immediately after having scanned the first code, consider setting the [BarcodeCaptureSettings.codeDuplicateFilter](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture-settings.html#property-scandit.datacapture.barcode.BarcodeCaptureSettings.CodeDuplicateFilter) to around 500 or even \-1 if you do not want codes to be scanned more than once. Next, create a [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance with the settings initialized in the previous step: ```dart var barcodeCapture = BarcodeCapture(settings); DataCaptureContext.sharedInstance.addMode(barcodeCapture); ``` ## Register the Barcode Capture Listener To get informed whenever a new code has been recognized, add a [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) through [BarcodeCapture.addListener()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.AddListener) and implement the listener methods to suit your application’s needs. First implement the [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) interface. For example: ```dart @override void didScan(BarcodeCapture barcodeCapture, BarcodeCaptureSession session) { var recognizedBarcodes = session.newlyRecognizedBarcode; // Do something with the barcodes. } ``` Then add the listener: ```dart barcodeCapture.addListener(this); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```dart var cameraSettings = BarcodeCapture.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. var camera = Camera.defaultCamera?..applySettings(cameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```dart DataCaptureContext.sharedInstance.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/flutter/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.on](https://docs.scandit.com/data-capture-sdk/flutter/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```dart camera.switchToDesiredState(FrameSourceState.on); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```dart var dataCaptureView = DataCaptureView.forContext(DataCaptureContext.sharedInstance); // Add the dataCaptureView to your widget tree ``` To visualize the results of barcode scanning, the following [overlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) can be added: ```dart var overlay = BarcodeCaptureOverlay.withBarcodeCaptureForView(barcodeCapture, dataCaptureView); ``` ## Disabling Barcode Capture To disable barcode capture, for instance as a consequence of a barcode being recognized, set [BarcodeCapture.isEnabled](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-capture.html#property-scandit.datacapture.barcode.BarcodeCapture.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## Barcode Generator # Barcode Generator The Barcode Generator is a simple tool to generate barcodes directly from the Scandit SDK. In this guide, we will show you how to use the Barcode Generator to generate barcodes and QR codes. The Barcode Generator supports the following formats: * Code 39 * Code 128 * EAN 13 * UPCA * ITF * QR * DataMatrix * PDF417 (SDK version >= 8.2) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/flutter/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Generating Barcodes To generate barcodes, you need to create a [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then use the static factory method on [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) for the symbology you are interested in, in this example Code 128, to get a builder instance. You can configure the colors used in the resulting image: ```dart var builder = BarcodeGenerator.code128BarcodeGeneratorBuilder(dataCaptureContext) .withBackgroundColor(Colors.white) .withForegroundColor(Colors.black); var generator = builder.build(); ``` When the builder is configured, call `build()` to get the `BarcodeGenerator` and try to generate the image: ```dart try { var image = await generator.generateFromText(dataString, 200); // Use the image } catch (e) { debugPrint("Error generating barcode: $e"); } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-generator.html) for more information. ## Generating QR Codes To generate barcodes, you need to create a [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`QRCodeBarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder) using the method of [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) specific for QR codes. You can configure the colors used in the resulting image, and the two settings that can be configured for QR codes: [`QRCodeBarcodeGeneratorBuilder.errorCorrectionLevel`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithErrorCorrectionLevel) and [`QRCodeBarcodeGeneratorBuilder.versionNumber`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithVersionNumber). ```dart var builder = BarcodeGenerator.qrCodeBarcodeGeneratorBuilder(dataCaptureContext) .withErrorCorrectionLevel(QrCodeErrorCorrectionLevel.high) .withVersionNumber(4); var generator = builder.build(); ``` When the builder is configured, call `build()` to get the `BarcodeGenerator` and try to generate the image: ```dart try { var image = await generator.generateFromText(dataString, 200); // Use the image } catch (e) { debugPrint("Error generating barcode: $e"); } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-generator.html) for more information. --- ## Get Started # Get Started :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/flutter/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: In this guide you will learn step-by-step how to add Barcode Selection to your application. The general steps are: - Initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. - Create a [barcode selection settings](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and choose the right configuration. - Create a new [barcode selection mode](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance and initialize it with the settings created above. - Register a [barcode selection listener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/flutter/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-selection-basic-overlay.html#class-scandit.datacapture.barcode.selection.ui.BarcodeSelectionBasicOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Selection Behavior _Symbologies_ Barcode selection is orchestrated by the [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) [data capture mode](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). It is configured through [BarcodeSelectionSettings](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) that will get informed whenever new codes have been selected. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```dart var settings = BarcodeSelectionSettings() ..enableSymbologies({ Symbology.code128, Symbology.code39, Symbology.qr, Symbology.ean8, Symbology.upce, Symbology.ean13Upca }); ``` _Selection Types_ The behavior of Barcode Selection can be changed by using a different [selection type](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-type.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionType). This defines the method used by [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) to select codes. Currently there are two types. If you want the user to select barcodes with a tap, then use [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection). This selection type can automatically freeze the camera preview to make the selection easier. You can configure the freezing behavior via [BarcodeSelectionTapSelection.freezeBehavior](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.FreezeBehavior). With [BarcodeSelectionTapSelection.tapBehavior](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.TapBehavior) you can decide if a second tap on a barcode means that the barcode is unselected or if it is selected another time (increasing the counter). :::note Using [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection) requires the MatrixScan add-on. ::: If you want the selection to happen automatically based on where the user points the camera, then use [BarcodeSelectionAimerSelection](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-aimer-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAimerSelection). It is possible to choose between two different [selection strategies](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-strategy.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionStrategy). Use [BarcodeSelectionAutoSelectionStrategy](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAutoSelectionStrategy) if you want the barcodes to be selected automatically when aiming at them as soon as the intention is understood by our internal algorithms. Use [BarcodeSelectionManualSelectionStrategy](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionManualSelectionStrategy) if you want the barcodes to be selected when aiming at them and tapping anywhere on the screen. _Single Barcode Auto Detection_ If you want to automatically select a barcode when it is the only one on screen, turn on [BarcodeSelectionSettings.singleBarcodeAutoDetection](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-settings.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionSettings.SingleBarcodeAutoDetection). _Creating the mode_ Next, create a [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance with the settings initialized in the previous step: ```dart var barcodeSelection = BarcodeSelection(settings); await DataCaptureContext.sharedInstance.addMode(barcodeSelection); ``` ## Register the Barcode Selection Listener To get informed whenever a new code has been recognized, add a [BarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) through [BarcodeSelection.addListener()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection.html#method-scandit.datacapture.barcode.selection.BarcodeSelection.AddListener) and implement the listener methods to suit your application’s needs. First implement the [BarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) interface. For example: ```dart @override void didUpdateSelection(BarcodeSelection barcodeSelection, BarcodeSelectionSession session) { var newlySelectedBarcodes = session.newlySelectedBarcodes; // Do something with the barcodes. } ``` Then add the listener: ```dart barcodeSelection.addListener(this); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```dart var cameraSettings = BarcodeSelection.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. var camera = Camera.defaultCamera?..applySettings(cameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```dart DataCaptureContext.sharedInstance.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/flutter/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.on](https://docs.scandit.com/data-capture-sdk/flutter/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```dart camera.switchToDesiredState(FrameSourceState.on); ``` ## Disabling Barcode Selection To disable barcode selection, for instance when the selection is complete, set [BarcodeSelection.isEnabled](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelection.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## About Barcode Selection # About Barcode Selection :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/flutter/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: Barcode Selection enables you to increase scanning accuracy and prevent users from scanning the wrong code in scenarios where there are multiple barcodes present, such as a crowded shelf, an order catalog with barcodes printed closely together, or a label with multiple barcodes. Barcode Selection provides two key capabilities: - **Aim to Select** allows users to select one code at a time. This is especially useful for one-handed operation. - **Tap to Select** is a quick way for users to select several codes from the same view. Selection is done by tapping on highlighted barcodes in the live camera preview or on a frozen screen. :::warning Barcode Selection does not support handling of duplicate codes. If a code appears twice in the visible preview both instances will be marked as selected even if only one of them was selected. ::: --- ## Advanced Configurations # Advanced Configurations There are several advanced configurations that can be used to customize the behavior of the ID Capture SDK and enable additional features. ## Configure Data Anonymization By default, data extracted from documents is anonymized according to local regulations. See [Anonymized Documents](/sdks/flutter/id-capture/supported-documents.md#anonymized-documents) for more information. That means certain data from certain fields won’t be returned, even if it’s present on a document. You control the anonymization level with the following setting: ```dart // Default value: settings.anonymizationMode = IdAnonymizationMode.fieldsOnly; // Sensitive data is additionally covered with black boxes on returned images: settings.anonymizationMode = IdAnonymizationMode.fieldsAndImages; // Only images are anonymized: settings.anonymizationMode = IdAnonymizationMode.imagesOnly; // No anonymization: settings.anonymizationMode = IdAnonymizationMode.none; ``` ## Document Capture Zones By default, a new instance of [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) creates a single-sided scanner type with no accepted or rejected documents. To change this, use the `scannerType` method to set the scanner type to either [SingleSideScanner](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-scanner.html#single-side-scanner) or [FullDocumentScanner](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-scanner.html#full-document-scanner). The `FullDocumentScanner` extracts all document information by default. If using the `SingleSideScanner`, you can specify the document zones to extract: ```dart // To extract data from barcodes on IDs: settings.scanner = IdCaptureScanner(physicalDocumentScanner: SingleSideScanner(true, false, false)); // To extract data from the visual inspection zone (VIZ) on IDs: settings.scanner = IdCaptureScanner(physicalDocumentScanner: SingleSideScanner(false, false, true)); // To extract data from the machine-readable zone (MRZ) on IDs: settings.scanner = IdCaptureScanner(physicalDocumentScanner: SingleSideScanner(false, true, false)); ``` ## Configure Accepted and Rejected Documents To configure the documents that should be accepted and/or rejected, use the `acceptedDocuments` and `rejectedDocuments` methods in `IdCaptureSettings`. These methods are used in conjunction with the [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) and [IdCaptureRegion](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-region.html#enum-scandit.datacapture.id.IdCaptureRegion) enums to enable highly flexible document filtering as may be desired in your application. For example, to accept only US Driver Licenses: ```dart settings.acceptedDocuments.addAll([DriverLicense(IdCaptureRegion.us)]); ``` Or to accept all Passports *except* those from the US: ```dart settings.acceptedDocuments.addAll([Passport(IdCaptureRegion.any)]); settings.rejectedDocuments.addAll([Passport(IdCaptureRegion.us)]); ``` ## ID Images Your use can may require that you capture and extract images of the ID document. Use the [IdImageType](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-image-type.html#enum-scandit.datacapture.id.IdImageType) enum to specify the images you want to extract from the `CapturedId` object For the full frame of the document, you can use [`setShouldPassImageTypeToResult`](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-settings.html#method-scandit.datacapture.id.IdCaptureSettings.SetShouldPassImageTypeToResult) when creating the `IdCaptureSettings` object. This will pass the image type to the result, which you can then access in the `CapturedId` object. ## Callbacks and Scanning Workflows The ID Capture Listener provides two callbacks: `onIdCaptured` and `onIdRejected`. The `onIdCaptured` callback is called when an acceptable document is successfully captured, while the `onIdRejected` callback is called when a document is captured but rejected. For a successful capture, the `onIdCaptured` callback provides a `CapturedId` object that contains the extracted information from the document. This object is specific to the type of document scanned. For example, a `CapturedId` object for a US Driver License will contain different fields than a `CapturedId` object for a Passport. For a rejected document, a [RejectionReason](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) is provided in the `onIdRejected` callback to help you understand why the document was rejected and to take appropriate action. These are: * NOT_ACCEPTED_DOCUMENT_TYPE: The document is not in the list of accepted documents. In this scenario, you could direct the user to scan a different document. * INVALID_FORMAT: The document is in the list of accepted documents, but the format is invalid. In this scenario, you could direct the user to scan the document again. * DOCUMENT_VOIDED: The document is in the list of accepted documents, but the document is voided. In this scenario, you could direct the user to scan a different document. * TIMEOUT: The document was not scanned within the specified time. In this scenario, you could direct the user to scan the document again. ## Detect Fake IDs *ID Validate* is a fake ID detection software. It currently supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). Fake ID detection can be performed automatically using the following settings: * [IdCaptureSettings.rejectForgedAamvaBarcodes](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectForgedAamvaBarcodes): Automatically rejects documents whose AAMVA barcode fails authenticity validation. * [IdCaptureSettings.rejectInconsistentData](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectInconsistentData): Automatically rejects documents whose human‑readable data does not match the data encoded in the barcode or MRZ. To enable ID validation for your subscription, please reach out to [Scandit Support](mailto:support@scandit.com). --- ## Get Started # Get Started This page will guide you through the process of adding ID Capture to your Flutter application. ID Capture is a mode of the Scandit Data Capture SDK that allows you to capture and extract information from personal identification documents, such as driver's licenses, passports, and ID cards. The general steps are: - Initializing the Data Capture Context - Accessing a Camera - Configuring the Capture Settings - Implementing a Listener to Receive Scan Results - Setting up the Capture View and Overlay - Starting the Capture Process :::warning Using ID Capture at the same time as other modes (e.g. Barcode Capture) is not supported. ::: ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](/sdks/flutter/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import IdModuleOverview from '../../../partials/get-started/_id-module-overview-no-eu-dl.mdx'; ### Initialize the ID Plugin :::warning Without initializing the ID plugin, runtime crashes will occur. However, you don’t have to initialize the core plugin, as initializing the ID plugin already does that. ::: Before accessing anything of the Scandit Data Capture SDK functionality. You have to initialize the id plugin. ```dart void main() async { WidgetsFlutterBinding.ensureInitialized(); await ScanditFlutterDataCaptureId.initialize(); runApp(MyApp()); } ``` ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Add the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/flutter/core/api/camera.html#class-scandit.datacapture.core.Camera): ```dart Camera? camera = Camera.defaultCamera; if (camera != null) { // Use the settings recommended by id capture. camera.applySettings(IdCapture.createRecommendedCameraSettings()); DataCaptureContext.sharedInstance.setFrameSource(camera); } ``` ## Create ID Capture Settings Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scanner type and the accepted and rejected documents. Check [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-document.html) for all the available options. :::tip By default, [anonymized data](./advanced.md#configure-data-anonymization) is not returned in accordance with local regulations for specific documents. This setting can be disabled for testing purposes, but be sure to comply with local laws and requirements in production. ::: ```dart var settings = IdCaptureSettings(); // To scan only one-sided documents: settings.scanner = IdCaptureScanner(physicalDocumentScanner: SingleSideScanner(true, false, false)); // To scan both sides of the document: // settings.scanner = IdCaptureScanner(physicalDocumentScanner: FullDocumentScanner()); settings.acceptedDocuments.addAll([Passport(IdCaptureRegion.any), DriverLicense(IdCaptureRegion.any)]); settings.rejectedDocuments.addAll([IdCard(IdCaptureRegion.any)]); ``` ## Implement the Listener To receive scan results, implement [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener). Capture results are delivered as a [CapturedId](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/captured-id.html#class-scandit.datacapture.id.CapturedId). This class contains data common for all kinds of personal identification documents. For more specific information, use its non-null result properties (e.g. [CapturedId.barcode](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/captured-id.html#property-scandit.datacapture.id.CapturedId.Barcode)). ```dart @override void didCaptureId(IdCapture idCapture, IdCaptureSession session) { CapturedId? capturedId = session.newlyCapturedId; // Do something in case the capturedId is not null. } ``` Create a new ID Capture mode with the chosen settings. Then register the listener: ```dart idCapture = IdCapture(settings); idCapture.addListener(this) DataCaptureContext.sharedInstance.addMode(idCapture); ``` ## Set up Capture View and Overlay When using the built-in camera as [frameSource](https://docs.scandit.com/data-capture-sdk/flutter/core/api/frame-source.html#interface-scandit.datacapture.core.IFrameSource), you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```dart var dataCaptureView = DataCaptureView.forContext(DataCaptureContext.sharedInstance); // Add the dataCaptureView to your widget tree ``` Then create an instance of [IdCaptureOverlay](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) attached to the view: ```dart overlay = IdCaptureOverlay.withIdCaptureForView(idCapture, dataCaptureView); ``` The overlay chooses the displayed UI automatically, based on the selected [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings). If you prefer to show a different UI or to temporarily hide it, set the appropriate [IdCaptureOverlay.idLayout](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/ui/id-capture-overlay.html#property-scandit.datacapture.id.ui.IdCaptureOverlay.IdLayout). ## Start the Capture Process Finally, turn on the camera to start scanning: ```dart camera.switchToDesiredState(FrameSourceState.on); ``` --- ## About ID Capture import AboutIdCapture from '../../../partials/intro/_about-id-capture.mdx'; --- ## Supported Documents ## ID Scanning Supported Documents Scandit ID Capture provides various [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/flutter/id-capture/api/id-capture-scanner.html#id-capture-scanner) types, each designed for specific scanning workflows. These workflows can involve scanning either specific parts of a document or the entire document, including both the front and back sides. This section details the types of documents supported by each scanner type. import IdDocumentsFull from '../../../partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from '../../../partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents import IdValidateDocuments from '../../../partials/advanced/_id-documents-validate.mdx'; --- ## Advanced Configurations import ValidationFlowHowItWorks from '../../../partials/advanced/_validation-flow-how-it-works.mdx'; import ValidationFlowCustomButtons from '../../../partials/advanced/_validation-flow-custom-buttons.mdx'; import ValidationFlowTypingHints from '../../../partials/advanced/_validation-flow-typing-hints.mdx'; import ValidationFlowCloudVLM from '../../../partials/advanced/_validation-flow-cloud-vlm.mdx'; import ReceiptScanning from '../../../partials/advanced/_receipt-scanning.mdx'; import ValidationFlowRequiredOptional from '../../../partials/advanced/_validation-flow-required-optional.mdx'; import ValidationFlowCustomToasts from '../../../partials/advanced/_validation-flow-custom-toasts.mdx'; import ValidationFlowCustomField from '../../../partials/advanced/_validation-flow-custom-field.mdx'; # Advanced Configurations ## Customization of the Overlays To customize the appearance of an overlay you can implement a [LabelCaptureBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/ui/label-capture-basic-overlay-listener.html#interface-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener) and/or [LabelCaptureAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/ui/label-capture-advanced-overlay-listener.html) interface, depending on the overlay(s) you are using. The method [brushForLabel()](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForLabel) is called every time a label is captured, and [brushForFieldOfLabel()](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForField) is called for each of its fields to determine the brush for the label or field. ```dart // Create a custom listener class that implements LabelCaptureBasicOverlayListener. class MyBasicOverlayListener extends LabelCaptureBasicOverlayListener { @override Future brushForLabel(LabelCaptureBasicOverlay overlay, CapturedLabel label) async { // Use a transparent brush for the label itself. return null; } @override Future brushForFieldOfLabel( LabelCaptureBasicOverlay overlay, LabelField field, CapturedLabel label) async { if (field.name == 'Barcode') { // Highlight barcode fields with a cyan color. return Brush( Color.fromRGBO(0, 255, 255, 0.5), Color.fromRGBO(0, 255, 255, 0.5), 0, ); } if (field.name == 'Expiry Date') { // Highlight expiry date fields with an orange color. return Brush( Color.fromRGBO(255, 165, 0, 0.5), Color.fromRGBO(255, 165, 0, 0.5), 0, ); } // Use transparent brush for other fields. return null; } @override void didTapLabel(LabelCaptureBasicOverlay overlay, CapturedLabel label) { // Handle user tap gestures on the label. } } // Create the overlay and set the listener. final overlay = LabelCaptureBasicOverlay(labelCapture); overlay.listener = MyBasicOverlayListener(); ``` :::tip You can also use `LabelCaptureBasicOverlay.setLabelBrush()` and `LabelCaptureBasicOverlay.setCapturedFieldBrush()` to configure the overlay if you don't need to customize the appearance based on the name or content of the fields. ::: ### Advanced Overlay For more advanced use cases, such as adding custom views or implementing Augmented Reality (AR) features, you can use the `LabelCaptureAdvancedOverlay`. The example below creates an advanced overlay, configuring it to display a styled warning message below expiry date fields when they’re close to expiring, while ignoring other fields. ```dart final advancedOverlay = LabelCaptureAdvancedOverlay(labelCapture); dataCaptureView.addOverlay(advancedOverlay); advancedOverlay.listener = MyAdvancedOverlayListener(); ``` Implement `LabelCaptureAdvancedOverlayListener` as a concrete class. The `widgetForCapturedLabel` and `widgetForCapturedLabelField` callbacks must return a `LabelCaptureAdvancedOverlayWidget` subclass (or `null` to show nothing): ```dart class MyAdvancedOverlayListener extends LabelCaptureAdvancedOverlayListener { @override Future widgetForCapturedLabel( LabelCaptureAdvancedOverlay overlay, CapturedLabel capturedLabel) async { return null; // We only care about specific fields } @override Future anchorForCapturedLabel( LabelCaptureAdvancedOverlay overlay, CapturedLabel capturedLabel) async { return Anchor.center; } @override Future offsetForCapturedLabel( LabelCaptureAdvancedOverlay overlay, CapturedLabel capturedLabel) async { return PointWithUnit(DoubleWithUnit(0, MeasureUnit.pixel), DoubleWithUnit(0, MeasureUnit.pixel)); } @override Future widgetForCapturedLabelField( LabelCaptureAdvancedOverlay overlay, LabelField labelField) async { if (labelField.name.toLowerCase().contains("expiry") && labelField.type == LabelFieldType.text) { final daysUntilExpiry = daysUntilExpiryFunction(labelField.text); // Your method const dayLimit = 3; if (daysUntilExpiry anchorForCapturedLabelField( LabelCaptureAdvancedOverlay overlay, LabelField labelField) async { return Anchor.bottomCenter; } @override Future offsetForCapturedLabelField( LabelCaptureAdvancedOverlay overlay, LabelField labelField) async { return PointWithUnit(DoubleWithUnit(0, MeasureUnit.dip), DoubleWithUnit(22, MeasureUnit.dip)); } } ``` ## Validation Flow ```dart final validationFlowOverlay = LabelCaptureValidationFlowOverlay(labelCapture); dataCaptureView.addOverlay(validationFlowOverlay); // Set the listener validationFlowOverlay.listener = MyValidationFlowListener(); ``` ### Define a Listener When the user has verified that all fields are correctly captured and presses the finish button, the Validation Flow triggers a callback with the final results. To receive these results, implement the [LabelCaptureValidationFlowOverlayListener](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/ui/label-capture-validation-flow-listener.html) interface: ```dart class MyValidationFlowListener extends LabelCaptureValidationFlowListener { @override void didCaptureLabelWithFields(List fields) { String? barcodeData; String? expiryDate; for (final field in fields) { if (field.name == "") { barcodeData = field.barcode?.data; } else if (field.name == "") { expiryDate = field.text; } } // Handle the captured values } } ``` ```dart final validationFlowOverlaySettings = LabelCaptureValidationFlowSettings(); validationFlowOverlaySettings.setPlaceholderTextForLabelDefinition("Expiry Date", "MM/DD/YYYY"); validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```dart final validationFlowOverlaySettings = LabelCaptureValidationFlowSettings(); validationFlowOverlaySettings.restartButtonText = "Borrar todo"; validationFlowOverlaySettings.pauseButtonText = "Pausar"; validationFlowOverlaySettings.finishButtonText = "Finalizar"; validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```dart final validationFlowOverlaySettings = LabelCaptureValidationFlowSettings(); validationFlowOverlaySettings.standbyHintText = "No label detected, camera paused"; validationFlowOverlaySettings.validationHintText = "data fields collected"; // X/Y (X fields out of total Y) is shown in front validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```dart final validationFlowOverlaySettings = LabelCaptureValidationFlowSettings(); validationFlowOverlaySettings.validationErrorText = "Incorrect format."; validationFlowOverlaySettings.scanningText = "Scan in progress"; validationFlowOverlaySettings.adaptiveScanningText = "Processing"; validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```dart LabelCaptureSettings _buildLabelCaptureSettings() { final customBarcode = CustomBarcodeBuilder() .setSymbologies([Symbology.ean13Upca, Symbology.gs1DatabarExpanded, Symbology.code128]) .isOptional(false) .build(Constants.fieldBarcode); final expiryDateText = ExpiryDateTextBuilder() .setLabelDateFormat( LabelDateFormat( LabelDateComponentFormat.mdy, false, // acceptPartialDates ), ) .isOptional(false) .build(Constants.fieldExpiryDate); final labelDefinition = LabelDefinitionBuilder() .addCustomBarcode(customBarcode) .addExpiryDateText(expiryDateText) .build(Constants.labelRetailItem); labelDefinition.adaptiveRecognitionMode = AdaptiveRecognitionMode.auto; var settings = LabelCaptureSettings([labelDefinition]); return settings; } ``` See [AdaptiveRecognitionMode](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/label-definition.html#property-scandit.datacapture.label.LabelDefinition.AdaptiveRecognitionMode) for available options. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Smart Label Capture to your application. The general steps are: - Initialize the Data Capture Context - Configure the LabelCapture mode - Define a listener to handle captured labels - Visualize the scan process - Start the camera - Provide feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/flutter/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import LabelCaptureModuleOverview from '../../../partials/get-started/_smart-label-capture-module-overview.mdx'; ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Label Capture Mode The main entry point for the Label Capture Mode is the [LabelCapture](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/label-capture.html#class-scandit.datacapture.label.LabelCapture) object. It is configured through [LabelCaptureSettings](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/label-capture-settings.html#class-scandit.datacapture.label.LabelCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) that get informed whenever a new frame has been processed. ```dart // Create a barcode field using the builder pattern. final barcodeField = CustomBarcodeBuilder() .setSymbologies([Symbology.ean13Upca, Symbology.code128]) .build('Barcode'); // Create an expiry date text field using the builder pattern. final expiryDateField = ExpiryDateTextBuilder() .isOptional(true) .build('Expiry Date'); // Create a label definition using the builder pattern. final labelDefinition = LabelDefinition.builder() .addCustomBarcode(barcodeField) .addExpiryDateText(expiryDateField) .build('Product Label'); // Create the label capture settings using the builder pattern. final settings = LabelCaptureSettings.builder() .addLabel(labelDefinition) .build(); // Create the label capture mode with the settings. final labelCapture = LabelCapture(settings); // Add the mode to the data capture context created earlier. DataCaptureContext.sharedInstance.addMode(labelCapture); ``` ## Define a Listener to Handle Captured Labels To get informed whenever a new label has been recognized, add a [LabelCaptureListener](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) through [LabelCapture.addListener()](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/label-capture.html#method-scandit.datacapture.label.LabelCapture.AddListener) and implement the listener methods to suit your application’s needs. First conform to the `LabelCaptureListener` interface. Here is an example of how to implement a listener that processes the captured labels based on the label capture settings defined above. In this example, we create a `LabelCaptureRepository` class that implements the `LabelCaptureListener` interface. This class is responsible for handling the captured labels and processing them accordingly. Depending on your app architecture and whether you use dependency injection or not, you may use a fragment or a repository to implement the listener. ```dart import 'dart:async'; import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:scandit_flutter_datacapture_core/scandit_flutter_datacapture_core.dart'; import 'package:scandit_flutter_datacapture_label/scandit_flutter_datacapture_label.dart'; class CapturedLabelEvent { final String? barcodeData; final String? expiryDate; CapturedLabelEvent(this.barcodeData, this.expiryDate); } class LabelCaptureRepository { final ValueNotifier capturedLabels = ValueNotifier(null); late final LabelCapture labelCapture; late final LabelCaptureListener _listener; LabelCaptureRepository(DataCaptureContext context, LabelCaptureSettings settings) { labelCapture = LabelCapture(settings); _listener = _LabelCaptureListener(this); labelCapture.addListener(_listener); } void dispose() { labelCapture.removeListener(_listener); capturedLabels.dispose(); } } class _LabelCaptureListener extends LabelCaptureListener { final LabelCaptureRepository repository; _LabelCaptureListener(this.repository); @override void onSessionUpdated(LabelCapture capture, LabelCaptureSession session, FrameData? frameData) { final labels = session.capturedLabels; if (labels.isNotEmpty) { final label = labels.first; // Extract the barcode field final barcodeField = label.fields.firstWhereOrNull( (field) => field.name == '', ); final barcodeData = barcodeField?.barcode?.data; // Extract the expiry date field (optional) final expiryDateField = label.fields.firstWhereOrNull( (field) => field.name == '', ); final expiryDate = expiryDateField?.text; // Disable label capture to avoid duplicate scans capture.isEnabled = false; // Notify UI via ValueNotifier repository.capturedLabels.value = CapturedLabelEvent(barcodeData, expiryDate); // Emit default feedback (sound + vibration) Feedback.defaultFeedback.emit(); } } } ``` ## Visualize the Scan Process The capture process can be visualized by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy. The view controls what UI elements such as the viewfinder, as well as the overlays that are shown to visualize captured labels. To visualize the results of Label Capture you can use two overlays: - [LabelCaptureBasicOverlay](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/ui/label-capture-basic-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureBasicOverlay) - [LabelCaptureAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/ui/label-capture-advanced-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureAdvancedOverlay) :::tip The overlays can be used independently of each other, but you can also use both at the same time as each can serve to extend the functionality of the other. ::: Here is an example of how to add a `LabelCaptureBasicOverlay` to the `DataCaptureView`: ```dart import 'package:flutter/material.dart'; import 'package:scandit_flutter_datacapture_core/scandit_flutter_datacapture_core.dart'; import 'package:scandit_flutter_datacapture_label/scandit_flutter_datacapture_label.dart'; class LabelCaptureScreen extends StatefulWidget { final DataCaptureContext context; final LabelCapture labelCapture; const LabelCaptureScreen({ Key? key, required this.context, required this.labelCapture, }) : super(key: key); @override State createState() => _LabelCaptureScreenState(); } class _LabelCaptureScreenState extends State { late final DataCaptureView _dataCaptureView; @override void initState() { super.initState(); // Create the DataCaptureView and attach it to the context _dataCaptureView = DataCaptureView.forContext(widget.context); // Create the overlay and add it to the DataCaptureView final overlay = LabelCaptureBasicOverlay(widget.labelCapture); _dataCaptureView.addOverlay(overlay); // Optionally set a rectangular viewfinder overlay.viewfinder = RectangularViewfinder.withStyle( RectangularViewfinderStyle.square, ); } @override Widget build(BuildContext context) { // Attach the view to your widget tree return Scaffold( appBar: AppBar(title: Text('Label Capture')), body: _dataCaptureView, ); } } ``` :::tip See the [Advanced Configurations](advanced.md) section for more information about how to customize the appearance of the overlays. ::: ## Start the Camera Next, you need to create a new instance of the [Camera](https://docs.scandit.com/data-capture-sdk/flutter/core/api/camera.html#class-scandit.datacapture.core.Camera) class to indicate the camera to stream previews and to capture images. When initializing the camera, you can pass the recommended camera settings for Label Capture. ```dart Future setupCamera(DataCaptureContext context) async { // Get the default camera final camera = Camera.defaultCamera; if (camera == null) { throw StateError('Failed to initialize camera!'); } // Apply recommended settings for LabelCapture final settings = LabelCapture.createRecommendedCameraSettings(); await camera.applySettings(settings); // Set camera as the frame source for the context await context.setFrameSource(camera); } ``` Once the Camera, DataCaptureContext, DataCaptureView and LabelCapture are initialized, you can switch on the camera to start capturing labels. Typically, this is done on resuming the view and when the user granted permission to use the camera, or once the user pressed continue scanning after handling a previous scan. ```dart await camera.switchToDesiredState(FrameSourceState.on); ``` ## Provide Feedback Label Capture doesn't emit any sound or vibration automatically when a new label is recognized. This is because it may be that the label is not complete and you choose to ignore it and wait for the next recognition. However, we provide a [Feedback](https://docs.scandit.com/data-capture-sdk/flutter/core/api/feedback.html#class-scandit.datacapture.core.Feedback) class that can be uses to emit feedback when a label is recognized and successfully processed. You can use the default feedback, or configure your own sound or vibration. ```dart final Feedback feedback = Feedback.defaultFeedback; ``` :::note Audio feedback is only played if the device is not muted. ::: --- ## About Smart Label Capture import AboutLabelCapture from '../../../partials/intro/_about-smart-label-capture.mdx'; import ValidationFlow from '../../../partials/intro/_about_validation_flow.mdx'; See [here](./advanced.md#validation-flow) for more details. --- ## Label Definitions # Label Definitions A **Label Definition** is a configuration that defines the label, and its relevant fields, that Smart Label Capture should recognize and extract during scans. Smart Label Capture provides a [Label Definition](https://docs.scandit.com/data-capture-sdk/flutter/label-capture/api/label-definition.html#label-definition) API, enabling you to configure and extract structured data from predefined and custom labels. This feature provides a flexible way to recognize and decode fields within a specific label layout such as price tags, VIN labels, or packaging stickers without needing to write custom code for each label type. There are two approaches to using label definitions: - [**Pre-built Labels**](#pre-built-labels) - [**Custom Labels**](#custom-labels) ## Pre-built Labels Smart Label Capture includes ready-made label definitions for common use cases. These pre-built options let you recognize and extract information from standard label types without creating custom configurations: ### Example: Price label Use `LabelDefinition.priceCaptureDefinitionWithName()` to create a pre-built label definition for price labels, such as those found in retail environments: ![Price Label Example](/img/slc/price-label.png) ```dart // Create a pre-built price capture label definition. final priceLabel = LabelDefinition.priceCaptureDefinitionWithName('price-label'); // Create the label capture settings using the builder pattern. final settings = LabelCaptureSettings.builder() .addLabel(priceLabel) .build(); ``` ## Custom Labels If Smart Label Capture’s pre-built options don’t fit your needs, define a custom label instead. Custom labels can combine your own fields with any of the available pre-built ones. :::tip The following characters are recognized: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ()-./:,$¶"`. ::: ### Custom Fields There are two types of custom fields you can define: The following builder methods are available to configure custom fields: | Method | Required | Description | |--------|----------|-------------| | `setValueRegexes()` / `setValueRegex()` | Yes | The regex patterns that identify the target string in the scanned content. | | `setAnchorRegexes()` / `setAnchorRegex()` | No | Used to specify keywords or phrases that help identify the context of the field. This is particularly useful when the label contains multiple fields that could match the same pattern (e.g., when both packaging and expiry dates are present). | | `setSymbologies()` / `setSymbology()` | Yes (barcode fields) | The barcode symbologies to match for barcode fields. This is important for ensuring that the field only captures data from specific barcode types, enhancing accuracy and relevance. | | `isOptional()` | No | Whether the field is optional or mandatory. This is helpful when certain fields may not be present on every scan. | #### Example: Fish Shipping Box This example shows how to create a custom label definition for a fish shipping box, which includes fields for barcode and batch number. ![Fish Shipping Box Example](/img/slc/fish-shipping-box.png) ```dart // Create a barcode field with Code 128 symbology. final barcodeField = CustomBarcodeBuilder() .setSymbology(Symbology.code128) .build('barcode-field'); // Create a custom text field for the batch number. // Use setAnchorRegexes to specify keywords that help identify the field context. // Use setValueRegexes to specify the expected format of the field data. final batchNumberField = CustomTextBuilder() .setAnchorRegexes(anchorRegexes: ['Batch']) .setValueRegexes([r'FZ\d{5,10}']) .isOptional(true) .build('batch-number-field'); // Create a label definition using the builder pattern. final shippingLabel = LabelDefinition.builder() .addCustomBarcode(barcodeField) .addCustomText(batchNumberField) .build('shipping-label'); // Create the label capture settings. final settings = LabelCaptureSettings.builder() .addLabel(shippingLabel) .build(); ``` ### Pre-built Fields You can also build your label using pre-built fields. These common fields speed up integration because their `valueRegexes`, `anchorRegexes`, and `symbologies` are already predefined. Customization of pre-built fields is done via the `valueRegexes`, `anchorRegexes`, and `isOptional` methods, which allow you to specify the expected format of the field data. :::tip All pre-built fields come with default `valueRegexes` and `anchorRegexes` that are suitable for most use cases. **Calling either builder method is optional and will override the defaults**. The `resetAnchorRegexes()` method can be used to remove the default `anchorRegexes`, allowing you to rely solely on the `valueRegexes` for detection. ::: import FeatureList from '@site/src/components/FeatureList'; #### Barcode Fields #### Price and Weight Fields #### Date and Custom Text Fields #### Example: Hard disk drive label This example demonstrates how to configure a label definition for a hard disk drive (HDD) label, which typically includes common fields like serial number and part number. ![Hard Disk Drive Label Example](/img/slc/hdd-label.png) ```dart // Create a serial number barcode field. // Pre-built fields like SerialNumberBarcode have predefined valueRegexes and anchorRegexes. final serialNumberField = SerialNumberBarcodeBuilder() .setSymbology(Symbology.code128) .build('serial-number'); // Create a part number barcode field. final partNumberField = PartNumberBarcodeBuilder() .setSymbology(Symbology.code128) .build('part-number'); // Create a label definition using the builder pattern. final hddLabel = LabelDefinition.builder() .addSerialNumberBarcode(serialNumberField) .addPartNumberBarcode(partNumberField) .build('hdd-label'); // Create the label capture settings. final settings = LabelCaptureSettings.builder() .addLabel(hddLabel) .build(); ``` --- ## Adding AR Overlays # Adding AR Overlays There are two ways to add advanced AR overlays to a Data Capture View: - Take advantage of the [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) class, which provides a ready-to-use implementation for view-based AR overlays. - Provide your own custom implementation, using the function [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) to retrieve the barcode’s current screen position for each frame. :::note - The first way is the easiest, as it takes care of adding, removing and animating the overlay’s views whenever needed. It’s also flexible enough to cover the majority of use cases. - You can always handle touch events on the views you create like you normally would. ::: ## Using BarcodeBatchAdvancedOverlay As mentioned above, the advanced overlay combined with its [listener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) offers an easy way of adding augmentations to your [DataCaptureView](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). In this guide we will add a view above each barcode showing its content. First of all, create a new instance of [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) and add it to the [DataCaptureView](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). ```dart var overlay = BarcodeBatchAdvancedOverlay(barcodeBatch); dataCaptureView.addOverlay(overlay); ``` At this point, you have two options. - Add a [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) to the overlay. - Use the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) to specify the view, anchor and offset for each barcode. :::note The second way will take priority over the first one, which means that if a view for a barcode has been set using [BarcodeBatchAdvancedOverlay.setWidgetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), the function [BarcodeBatchAdvancedOverlayListener.widgetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) won’t be invoked for that specific barcode. ::: Using [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) - You need to implement [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener). This interface’s methods are invoked every time a barcode is newly tracked. - [BarcodeBatchAdvancedOverlayListener.widgetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) asks for a view to animate on top of the barcode. Returning _null_ will show no view. - [BarcodeBatchAdvancedOverlayListener.anchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode) asks how to anchor the view to the barcode through [Anchor](https://docs.scandit.com/data-capture-sdk/flutter/core/api/anchor.html#enum-scandit.datacapture.core.Ancho). Be aware that it anchors the view’s center to the anchor point. To achieve anchoring the top of the view or the bottom etc. you will have to set an offset as explained in the next point. - [BarcodeBatchAdvancedOverlayListener.offsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode) asks for an offset that is applied on the already anchored view. This offset is expressed through a [PointWithUnit](https://docs.scandit.com/data-capture-sdk/flutter/core/api/common.html#struct-scandit.datacapture.core.PointWithUnit). ```dart @override BarcodeBatchAdvancedOverlayWidget? widgetForTrackedBarcode(BarcodeBatchAdvancedOverlay overlay, TrackedBarcode trackedBarcode) { // Create and return the widget you want to show for this tracked barcode. You can also return null, to have no widget for this barcode. return ARWidget(trackedBarcode.barcode.data); } @override Anchor anchorForTrackedBarcode(BarcodeBatchAdvancedOverlay overlay, TrackedBarcode trackedBarcode) { // As we want the view to be above the barcode, we anchor the view's center to the top-center of the barcode quadrilateral. // Use the function 'offsetForTrackedBarcode' below to adjust the position of the view by providing an offset. return Anchor.topCenter; } @override PointWithUnit offsetForTrackedBarcode(BarcodeBatchAdvancedOverlay overlay, TrackedBarcode trackedBarcode) { // This is the offset that will be applied to the view. // You can use MeasureUnit.fraction to give a measure relative to the view itself, the sdk will take care of transforming this into pixel size. // We now center horizontally and move up the view to make sure it's centered and above the barcode quadrilateral by half of the view's height. return PointWithUnit(DoubleWithUnit(0, MeasureUnit.fraction), DoubleWithUnit(-1, MeasureUnit.fraction)); } ``` Using the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) The function [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) gives you access to a [session](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession), which contains all added, updated and removed tracked barcodes. From here you can create the view you want to display, and then call [BarcodeBatchAdvancedOverlay.setWidgetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), [BarcodeBatchAdvancedOverlay.setAnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode) and [BarcodeBatchAdvancedOverlay.setOffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode) ```dart @override void didUpdateSession(BarcodeBatch barcodeBatch, BarcodeBatchSession session) { for (final trackedBarcode in session.addedTrackedBarcodes) { var arWidget = ARWidget(trackedBarcode.barcode.data); overlay.setWidgetForTrackedBarcode(arWidget, trackedBarcode); overlay.setAnchorForTrackedBarcode(Anchor.topCenter, trackedBarcode); overlay.setOffsetForTrackedBarcode( PointWithUnit(DoubleWithUnit(0, MeasureUnit.fraction), DoubleWithUnit(-1, MeasureUnit.fraction)), trackedBarcode); } } ``` ## Provide your own custom implementation If you do not want to use the overlay, it is also possible to add augmented reality features based on the tracking identifier and the [quadrilateral](https://docs.scandit.com/data-capture-sdk/flutter/core/api/common.html#struct-scandit.datacapture.core.Quadrilateral) coordinates that every tracked barcode has. Below are some pointers. - Set a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) on the barcode tracking - In the [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) function fetch the [added](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.AddedTrackedBarcodes) and [removed](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.RemovedTrackedBarcodes) tracked barcodes. - Create and show the views for the added barcodes. - Remove the views for the lost barcodes. - Add a method that is called 60fps when [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) is enabled. In this method, for each [TrackedBarcode](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/tracked-barcode.html#class-scandit.datacapture.barcode.batch.TrackedBarcode) on-screen, update the position based on [TrackedBarcode.location](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location). Please note that there is no need to animate the change of location, the change of position will happen frequently enough that the view will look as it is animated. :::note The frame coordinates from [TrackedBarcode.location](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location) need to be mapped to view coordinates, using [DataCaptureView.viewQuadrilateralForFrameQuadrilateral()](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#method-scandit.datacapture.core.ui.DataCaptureView.MapFrameQuadrilateralToView). ::: ```dart @override void didUpdateSession(BarcodeBatch barcodeBatch, BarcodeBatchSession session) { for (final lostTrackIdentifier in session.removedTrackedBarcodes) { // You now know the identifier of the tracked barcode that has been lost. // Usually here you would remove the views associated. } for (final trackedBarcode in session.addedTrackedBarcodes) { // Fixed identifier for the tracked barcode. var trackingIdentifier = trackedBarcode.identifier; // Current location of the tracked barcode. var location = trackedBarcode.location; view.viewQuadrilateralForFrameQuadrilateral(location).then((quadrilateral) => { // You now know the location of the tracked barcode. }); } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan to your application. The general steps are: - Initializing the Data Capture Context - Configuring the MatrixScan mode - Using the built-in camera - Visualizing the scan process - Providing feedback - Disabling barcode tracking ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [data capture context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Batch Mode The main entry point for the Barcode Batch Mode is the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object. It is configured through [BarcodeBatchSettings](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) that will get informed whenever a new frame has been processed. Most of the times, you will not need to implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener), instead you will add a [BarcodeBatchBasicOverlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) and implement a [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener). For this tutorial, we will setup Barcode Batch for tracking QR codes. ```dart var settings = BarcodeBatchSettings() ..enableSymbology(Symbology.qr, true); ``` Next, create a [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance with the data capture context and the settings initialized in the previous steps: ```dart var barcodeBatch = BarcodeBatch(settings); DataCaptureContext.sharedInstance.addMode(barcodeBatch); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```dart var cameraSettings = BarcodeBatch.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. var camera = Camera.defaultCamera?..applySettings(cameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```dart DataCaptureContext.sharedInstance.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/flutter/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.on](https://docs.scandit.com/data-capture-sdk/flutter/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```dart camera.switchToDesiredState(FrameSourceState.on); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```dart var dataCaptureView = DataCaptureView.forContext(DataCaptureContext.sharedInstance); // Add the dataCaptureView to your widget tree ``` To visualize the results of Barcode Batch, first you need to add the following [overlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay): ```dart var overlay = BarcodeBatchBasicOverlay(barcodeBatch); dataCaptureView.addOverlay(overlay); ``` Once the overlay has been added, you should implement the [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) interface. The method [BarcodeBatchBasicOverlayListener.brushForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode) is invoked every time a new tracked barcode appears and it can be used to set a [brush](https://docs.scandit.com/data-capture-sdk/flutter/core/api/ui/brush.html#class-scandit.datacapture.core.ui.Brush) that will be used to highlight that specific barcode in the [overlay](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay). ```dart @override Brush brushForTrackedBarcode(BarcodeBatchBasicOverlay overlay, TrackedBarcode trackedBarcode) {// Return a custom Brush based on the tracked barcode. // Return a custom Brush based on the tracked barcode. } ``` If you would like to make the highlights tappable, you need to implement the [BarcodeBatchBasicOverlayListener.didTapTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped) method. ```dart @override void didTapTrackedBarcode(BarcodeBatchBasicOverlay overlay, TrackedBarcode trackedBarcode) { // A tracked barcode was tapped. } ``` ## Get Barcode Batch Feedback Barcode Batch, unlike Barcode Capture, doesn’t emit feedback (sound or vibration) when a new barcode is recognized. However, you may implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) to provide a similar experience. Below, we use the default [Feedback](https://docs.scandit.com/data-capture-sdk/flutter/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration if you want. Next, use this [feedback](https://docs.scandit.com/data-capture-sdk/flutter/core/api/feedback.html#class-scandit.datacapture.core.Feedback) in a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener): ```dart class FeedbackListener implements BarcodeBatchListener { @override void didUpdateSession(BarcodeBatch barcodeBatch, BarcodeBatchSession session) { if (session.addedTrackedBarcodes.isNotEmpty) { feedback.emit(); } } } ``` [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) is invoked for every processed frame. The [session](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession) parameter contains information about the currently tracked barcodes, in particular, the newly recognized ones. We check if there are any and if so, we emit the feedback. As the last step, register the listener responsible for emitting the feedback with the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance. ```dart barcodeBatch.addListener(feedbackListener); ``` ## Disabling Barcode Batch To disable barcode tracking set [BarcodeBatch.isEnabled](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-batch.html#property-scandit.datacapture.barcode.batch.BarcodeBatch.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off or put it in standby calling [SwitchToDesiredState](https://docs.scandit.com/data-capture-sdk/flutter/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [StandBy](https://docs.scandit.com/data-capture-sdk/flutter/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.Standby). --- ## About MatrixScan Batch # About MatrixScan Batch import AboutMatrixScan from '../../../partials/intro/_about-matrixscan.mdx' --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan AR to your application. Implementing MatrixScan AR involves two primary elements: - Barcode AR: The data capture mode that is used for scan and check functionality. - A Barcode AR View: The pre-built UI elements used to highlight items to be checked. The general steps are: - Initializing the Data Capture Context - Configuring the Barcode AR Mode - Setup the Barcode AR View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Initialize the Data Capture Context The first step to add find capabilities to your application is to initialize the [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode AR Mode The main entry point for the Barcode AR Mode is the `BarcodeAr` object. You can configure the supported Symbologies through its [`BarcodeArSettings`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-ar-settings.html), and set up the list of items that you want MatrixScan AR to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```dart var settings = BarcodeArSettings(); settings.enableSymbology(Symbology.ean13Upca, true); ``` The create the mode with the previously created settings: ```dart var mode = BarcodeAr(settings); ``` ## Setup the BarcodeArView MatrixScan AR’s built-in AR user interface includes buttons and overlays that guide the user through the scan and check process. By adding a [`BarcodeArView`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView), the scanning interface is added automatically to your application. The `BarcodeArView` is where you provide the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider) to supply the highlight and annotation information for the barcodes to be checked. If *null*, a default highlight is used and no annotations are provided. The `BarcodeArView` appearance can be customized through [`BarcodeArViewSettings`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-ar-view-settings.html#class-scandit.datacapture.barcode.check.ui.BarcodeArViewSettings), and the corresponding settings for your desired highlights and/or annotations, to match your application’s look and feel. The following settings can be customized: * Audio and haptic feedback * Torch button visibility and its position * Switch camera button visibility and its position * Zoom control visibility and its position * The size, colors, and styles of the highlight and annotation overlays ```dart var viewSettings = BarcodeArViewSettings( // ... ); ``` Next, create a `BarcodeArView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodeArView` is automatically added to the provided parent view. ```dart var barcodeArView = BarcodeArView.forModeWithViewSettings(DataCaptureContext.sharedInstance, barcodeAr, viewSettings); ``` Connect the `BarcodeArView` to the Widget lifecycle. The widget is dependent on calling `widgetPaused` and `widgetResumed` to set up the camera and its overlays properly. ```dart @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { // Resume scanning by calling the BarcodeArView widgetResumed function. // Under the hood, it re-enables the BarcodeAr mode and makes sure the view is properly // setup. barcodeArView.widgetResumed(); } else { // Pause scanning by calling the BarcodeArView widgetPaused function. // Under the hood, it will disable the mode and free resources that are not needed in a // paused state. barcodeArView.widgetPaused(); } } ``` ## Register the Listener Register a [BarcodeArViewUiListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-ar-view.html#interface-scandit.datacapture.barcode.check.ui.IBarcodeArViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the session. ```dart barcodeArView.uiListener = this @override void didTapFinishButton(Set foundItems) { } ``` ## Start searching As soon as everything is set up, control the [BarcodeArView](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView) to start the search. ```dart barcodeArView.start(); ``` --- ## About MatrixScan AR # About MatrixScan AR import AboutMatrixScanCheck from '../../../partials/intro/_about-matrixscan-ar.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Count is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Count to best fit your needs. ## Scanning Against A List There is a function to set a list of expected barcodes if you are scanning against a manifest or item list. If this is used, a progress bar is added to the UI, so you can keep track of the process while scanning. When scanning against a list, the UI will also show red icons to mark scanned barcodes that aren’t present on the list. ```dart List targetBarcodes = []; targetBarcodes.add(TargetBarcode.create("data", 1)); var captureList = BarcodeCountCaptureList.create(this, targetBarcodes); barcodeCount.setBarcodeCountCaptureList(captureList); ``` ## Clustering import Clustering from '../../../partials/count/_clustering.mdx' ## Tote Mapping import Totes from '../../../partials/count/_tote-mapping.mdx' ## Strap Mode It can be difficult to reach the shutter button if the smart device is attached to the user’s wrist by a strap or similar. In this instance, you can enable a floating shutter button that can be positioned by the end user in a more ergonomically suitable position. ```dart barcodeCountView.shouldShowFloatingShutterButton = true; ``` ## Filtering If you have several types of barcodes on your label/package, you may want to scan only one of them. In this case, you can filter the others out. This can be done by symbology, symbol count, or setting a regex. For example, you might want to scan only Code 128 barcodes and no PDF417 ones. ```dart var settings = BarcodeCountSettings(); settings.enableSymbology(Symbology.code128, true); Set excludedSymbologies = {}; excludedSymbologies.add(Symbology.pdf417); var filterSettings = settings.filterSettings; filterSettings.excludedSymbologies = excludedSymbologies; ``` Or, you want to exclude all the barcodes starting with 4 numbers: ```dart var settings = BarcodeCountSettings(); var filterSettings = settings.filterSettings; filterSettings.excludedCodesRegex = "^1234.*"; ``` By default the filters applied to the relevant barcodes are transparent, but you can use [`BarcodeFilterHighlightSettings`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-filter-highlight-settings.html#barcode-filter-highlight-settings) to change the color and level of transparency. ![Different Filters in MatrixScan Count](/img/matrixscan-count/filtering_styles.png) ## Clear Screen Button There are situations in which the user may find it helpful to clean up their screen (i.e. clear all the AR overlays) but keep the list of barcodes scanned. If this is the case, you can enable the “Clear screen” button. ```dart barcodeCountView.shouldShowClearHighlightsButton = true; ``` ## Customize Overlay Colors MatrixScan Count comes with recommended and user-tested AR overlays. However, if you wish to customize the overlay colors, once the overlay has been added, you can conform to the [BarcodeCountViewListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view-listener.html#interface-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener) interface. The methods [BarcodeCountViewListener.brushForRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForRecognizedBarcode) and [BarcodeCountViewListener.brushForUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForUnrecognizedBarcode) are invoked every time a new recognized or unrecognized barcode appears. These can be used to set a brush that will be used to highlight that specific barcode in the overlay. Keep in mind that these methods are relevant only when using the style [BarcodeCountViewStyle.dot](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view.html#value-scandit.datacapture.barcode.count.ui.BarcodeCountViewStyle.Dot). ```dart @override Brush? brushForRecognizedBarcode(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Return a custom brush } @override Brush? brushForUnrecognizedBarcode(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Return a custom brush } ``` ## Notifications If you want to be notified when a user taps on an overlay, you need to implement the[BarcodeCountViewListener.didTapRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnRecognizedBarcodeTapped) and [BarcodeCountViewListener.didTapUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped) methods. ```dart @override void didTapRecognizedBarcode(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Do something with the tapped barcode } @override void didTapUnrecognizedBarcode(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Do something with the tapped barcode } ``` ## Disable UI Elements The UI is an integral part of MatrixScan Count and we do not recommend that you use it without it. However, if you wish to disable UI elements you can do it as follows. Disable buttons: ```dart barcodeCountView.shouldShowListButton = false; barcodeCountView.shouldShowExitButton = false; barcodeCountView.shouldShowShutterButton = false; ``` Disable feedback and hints: ```dart barcodeCountView.shouldShowUserGuidanceView = false; barcodeCountView.shouldShowHints = false; ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Count to your application. The general steps are: 1. Initialize the Data Capture Context 2. Configure the Barcode Count Mode 3. Obtain camera instance and set frame source used 4. Register the listener to be informed when scanned phase is over 5. Set capture view and AR overlays 6. Set up the camera so that it switches on when you are in scanning view 7. Store and retrieve scanned barcodes 8. Reset Barcode Count mode 9. List and Exit callbacks ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure The Barcode Count Mode The main entry point for the Barcode Count Mode is the [BarcodeCount](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) object. It is configured through [BarcodeCountSettings](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count-settings.html#class-scandit.datacapture.barcode.count.BarcodeCountSettings) and allows you to register one or more listeners that are informed whenever a scan phase has finished. For this tutorial, we will set up Barcode Count for tracking EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```dart var settings = BarcodeCountSettings(); settings.enableSymbology(Symbology.ean13Upca, true); ``` If you are sure that your environment will only have unique barcodes (i.e. no duplicated values), you can also enable [BarcodeCountSettings.expectsOnlyUniqueBarcodes](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count-settings.html#property-scandit.datacapture.barcode.count.BarcodeCountSettings.ExpectsOnlyUniqueBarcodes). This option improves scanning performance as long as you are sure that no duplicates will be present. Next, create a [BarcodeCount](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) instance with the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) and the settings initialized in the previous step: ```dart var barcodeCount = BarcodeCount(settings); DataCaptureContext.sharedInstance.addMode(barcodeCount); ``` ## Obtain Camera Instance And Set Frame Source Used Our recommended camera settings should be used to achieve the best performance and user experience. The following couple of lines show how to get the recommended settings for MatrixScan Count and create the camera from it: Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```dart DataCaptureContext.sharedInstance.setFrameSource(camera); ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [BarcodeCountListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) interface and register the listener. ```dart barcodeCount.addListener(this); ``` [BarcodeCountListener.didScan()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan) is called when the scan phase has finished and results can be retrieved from [BarcodeCountSession](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession). ## Set Capture View And AR Overlays MatrixScan Count’s built-in AR user interface includes buttons and overlays that guide the user through the capturing process. By adding a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) to your view hierarchy: ```dart var barcodeCountView = BarcodeCountView.forContextWithMode(DataCaptureContext.sharedInstance, barcodeCount); ``` ## Set Up The Camera So That It Switches On When You Are In Scanning View The camera is not automatically turned on when you are in a scanning view. You need to set up the camera so that it switches on when needed and it switches off when not needed anymore. Similarly [BarcodeCount](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) should also be enabled and disabled. For instance, you should switch off the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is not visible anymore (including when the app goes in the background), similarly you want to switch on the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is visible (including when the app goes to the foreground). One way to achieve this is the following: ```dart @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { camera.switchToDesiredState(FrameSourceState.on); } else if (state == AppLifecycleState.paused) { camera.switchToDesiredState(FrameSourceState.off); } } ``` ## Store And Retrieve Scanned Barcodes The values captured as part of the scanning process are part of the [session](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession), and the session is not accessible outside [BarcodeCountListener.didScan()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan). Therefore, we recommend that you store the values to present a list, for example when the user taps the list icon. To do this, make a copy of [BarcodeCountSession.recognizedBarcodes](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count-session.html#property-scandit.datacapture.barcode.count.BarcodeCountSession.RecognizedBarcodes): ```dart @override Future didScan(BarcodeCount barcodeCount, BarcodeCountSession session, Future Function() getFrameData) async { allRecognizedBarcodes = session.recognizedBarcodes; } ``` ## Reset Barcode Count Mode When the scanning process is over, you need to reset the mode to make it ready for the next process. This clears the list of barcodes scanned and all the AR overlays. To reset Barcode Count’s scanning process, you need to call the [BarcodeCount.reset()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-count.html#method-scandit.datacapture.barcode.count.BarcodeCount.Reset) method. ```dart barcodeCount.reset(); ``` ## List And Exit Callbacks The UI includes two icons (buttons) named “List” and “Exit”. The SDK provides the callbacks so you can add the desired action when those icons are tapped by the user. ```dart @override void didTapListButton(BarcodeCountView view) { // Show the current progress but the order is not completed } @override void didTapExitButton(BarcodeCountView view) { // The order is completed } ``` --- ## About MatrixScan Count # About MatrixScan Count import AboutMatrixScanCount from '../../../partials/intro/_about-matrixscan-count.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Find is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Find to best fit your needs. ## Set up a listener on the BarcodeFind mode You may want more fine-grained knowledge over the different events happening during the life of the BarcodeFind mode, such as when the search starts, pauses and stops. To do this, you can directly register a [BarcodeFindListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-find-listener.html#interface-scandit.datacapture.barcode.find.IBarcodeFindListener) on the mode itself. Be aware that these listeners will be called from a background thread. ```dart mode.addListener(this) class BarcodeFindListenerImpl implements BarcodeFindListener { @override void didPauseSearch(Set foundItems) { // The mode was paused } @override void didStartSearch() { // The mode was started } @override void didStopSearch(Set foundItems) { // The mode was stopped after the finish button was clicked } } ``` ## UI configuration The [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) will by default show a set of UI elements, which can be optionally hidden: - A play/pause button - A finish button - A searched items carousel - Guidance hints There is also a progress bar but this is hidden by default. Each of these elements can be shown or hidden at will. ```dart barcodeFindView.shouldShowCarousel = false; barcodeFindView.shouldShowProgressBar = true; // … ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Find to your application. Implementing MatrixScan Find involves two primary elements: - Barcode Find: The data capture mode that is used for search and find functionality. - A Barcode Find View: The pre-built UI elements used to highlight found items. The general steps are: 1. Initialize the Data Capture Context. 2. Configure the Barcode Find Mode. 3. Setup the BarcodeFindView. 4. Register a listener to be notified with found items 5. Start searching ## Initialize the Data Capture Context The first step to add find capabilities to your application is to initialize the [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Find Mode The main entry point for the Barcode Find Mode is the [BarcodeFind](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind) object. You can configure the supported Symbologies through its [BarcodeFindSettings](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-find-settings.html#class-scandit.datacapture.barcode.find.BarcodeFindSettings), and set up the list of items that you want MatrixScan Find to highlight (e.g. a list of products). For this tutorial, we will set up Barcode Find for tracking EAN13 codes. Change this to the correct symbologies for your use case (e.g. Code 128, Code 39…). First create the settings: ```dart var settings = BarcodeFindSettings(); settings.enableSymbology(Symbology.ean13Upca, true); ``` Then you have to create the list of items that will be actively searched for. In this tutorial, let’s look up two items based on their EAN13 codes. We will attach to the first item some optional information that can be used by the BarcodeFindView to display extra information. ```dart var items = { BarcodeFindItem(BarcodeFindItemSearchOptions("9783598215438"), BarcodeFindItemContent("Mini Screwdriver Set", "(6-Piece)", null)), BarcodeFindItem( BarcodeFindItemSearchOptions("9783598215414"), null) // Item information is optional, used for display only }; ``` Create the mode with the previously created settings and set the items: ```dart var mode = BarcodeFind(settings); mode.setItemList(items); ``` ## Setup the BarcodeFindView MatrixScan Find’s built-in AR user interface includes buttons and overlays that guide the user through the searching process. By adding a [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView), the scanning interface (camera preview and searching UI elements) will be added automatically to your application. The BarcodeFindView appearance can be customized through [BarcodeFindViewSettings](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-find-view-settings.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindViewSettings): - Colors of dots in augmented reality overlay - Enable sound and haptic alerts ```dart var viewSettings = BarcodeFindViewSettings( Colors.green, // item in list color Colors.red, // item not in list color true, // sound enabled true // haptic enabled ); ``` Construct a new BarcodeFindView. ```dart var barcodeFindView = BarcodeFindView.forModeWithViewSettings(DataCaptureContext.sharedInstance, barcodeFind, viewSettings); ``` Connect the BarcodeFindView to the Widget lifecycle. The widget is dependent on calling widgetPaused and widgetResumed to set up the camera and its overlays properly. ```dart @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { // Resume finding by calling the BarcodeFindView widgetResumed function. // Under the hood, it re-enables the BarcodeFind mode and makes sure the view is properly // setup. barcodeFindView.widgetResumed(); } else { // Pause finding by calling the BarcodeFindView widgetPaused function. // Under the hood, it will disable the mode and free resources that are not needed in a // paused state. barcodeFindView.widgetPaused(); } } ``` ## Register a listener to be notified with found items The BarcodeFindView displays next to its shutter button a handy “finish” button. Register a [BarcodeFindViewUiListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-find-view.html#interface-scandit.datacapture.barcode.find.ui.IBarcodeFindViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```dart barcodeFindView.uiListener = this @override void didTapFinishButton(Set foundItems) { // This method is called when the user presses the // finish button. It returns the list of all items that were found during // the session. } ``` ## Start searching As soon as everything is set up, control the [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) to start the search. ```dart barcodeFindView.startSearching(); ``` This is the equivalent of pressing the “Play” button programmatically. It will start the search process, turn on the camera and hide the item carousel. --- ## About MatrixScan Find # About MatrixScan Find import AboutFind from '../../../partials/intro/_about-matrixscan-find.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Pick is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Pick to best fit your needs. ## BarcodePick Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodePick` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodePickListener`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-pick-listener.html#interface-scandit.datacapture.barcode.pick.IBarcodePickListener) on the mode itself, keeping in mind that these listeners are called from a background thread. ```dart barcodePickView.addListener(myListener); class BarcodePickViewListenerImpl implements BarcodePickViewListener { @override void didStartScanning(BarcodePickView view) { // The view started scanning } @override void didFreezeScanning(BarcodePickView view) { // The view was frozen } @override void didPauseScanning(BarcodePickView view) { // The view was paused } @override void didStopScanning(BarcodePickView view) { // The view stopped scanning } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Pick to your application. Implementing MatrixScan Pick involves two primary elements: - Barcode Pick: The data capture mode that is used for scan and pick functionality. - A Barcode Pick View: The pre-built UI elements used to highlight items to be picked. The general steps are: - Initializing the Data Capture Context - Configuring the Barcode Pick Mode - Setup the Barcode Pick View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the Barcode Pick Mode The main entry point for the Barcode Pick Mode is the `BarcodePick` object. You can configure the supported Symbologies through its [`BarcodePickSettings`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-pick-settings.html), and set up the list of items that you want MatrixScan Pick to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```dart var settings = BarcodePickSettings(); settings.enableSymbology(Symbology.ean13Upca, true); ``` Then you have to create the list of items that will be picked and quantity to be picked for each item. ```dart var items = { BarcodePickProduct("9783598215438", 3), BarcodePickProduct("9783598215414", 3), }; ``` Create a product provider and the mode: ```dart var productProvider = BarcodePickAsyncMapperProductProvider(items, productProviderCallback); var mode = BarcodePick(DataCaptureContext.sharedInstance, settings, productProvider); ``` ## Setup the `BarcodePickView` MatrixScan Pick’s built-in AR user interface includes buttons and overlays that guide the user through the scan and pick process. By adding a [`BarcodePickView`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-pick-view.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickView), the scanning interface is added automatically to your application. The `BarcodePickView` appearance can be customized through [`BarcodePickViewSettings`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-pick-view-settings.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickViewSettings) to match your application’s look and feel. The following settings can be customized: * Colors of dots in augmented reality overlay * Enable sound and haptic alerts * Guidelines text * Showing hints * Finish button * Pause button * Zoom button * Loading Dialog ```dart var viewSettings = BarcodePickViewSettings( // ... ); ``` Construct a new `BarcodePickView`. ```dart var barcodePickView = BarcodePickView.forModeWithViewSettings(DataCaptureContext.sharedInstance, mode, viewSettings); ``` Connect the `BarcodePickView` to the Widget lifecycle. The widget is dependent on calling `widgetPaused` and `widgetResumed` to set up the camera and its overlays properly. ```dart @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { // Resume finding by calling the BarcodePickView widgetResumed function. // Under the hood, it re-enables the BarcodePick mode and makes sure the view is properly // setup. barcodePickView.widgetResumed(); } else { // Pause finding by calling the BarcodePickView widgetPaused function. // Under the hood, it will disable the mode and free resources that are not needed in a // paused state. barcodePickView.widgetPaused(); } } ``` ## Register the Listener The `BarcodePickView` displays a **Finish** button next to its shutter button. Register a [BarcodePickViewUiListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/barcode-pick-view.html#interface-scandit.datacapture.barcode.pick.ui.IBarcodePickViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the session. ```dart barcodePickView.uiListener = this; @override void didTapFinishButton(BarcodePickView view) { // This method is called when the user presses the finish button. } ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `BarcodePickView.start()`. ```dart barcodePickView.start(); ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Pick # About MatrixScan Pick MatrixScan Pick is a pre-built UI that uses augmented reality overlays to highlight specific items that need to be picked. Whereas MatrixScan AR is fully customizable, MatrixScan Pick is a pre-built solution that allows you to add a scan and pick experience with augmented reality to an existing native app, with just a few lines of code. MatrixScan Pick is implemented through functionality provided by [`BarcodePick`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/barcode-pick.html). ## UI Overview * MatrixScan Pick is inspired by the familiar paradigm of a camera, including a shutter button that the user operates in order start and pause the scanning view. The Finish button is used at any time to exit the workflow. * It highlights items with obvious and colorful visual dots on screen. * When paused, MatrixScan Pick freezes the display at the last view, even if the device is moved. The Play button transitions back to the live view. * Textual guidance is displayed from the beginning of the session and as the workflow progresses, informing of the user of changes in item status (i.e. Detected, Ignored, To-Pick, or Picked). * Status icons can be defined to provide further information to users for a given barcode. In the live view, the icons are displayed but not tappable. In the frozen view, the status icons can be tapped and expanded to provide additional textual information. * The Quick Start Guide takes you through the process to install the full UI. However, you can then customize it by choosing to remove any elements on the screen except for the AR overlays. This allows you to create custom UIs suitable for your own workflows. ## Supported Symbologies MatrixScan Find supports all [symbologies](../barcode-symbologies.mdx) **except** DotCode, MaxiCode and postal codes (KIX, RM4SCC). If you are not familiar with the symbologies that are relevant for your use case, you can use capture presets that are tailored for different verticals (e.g. retail, logistics, etc.). --- ## Get Started # Get Started The parser parses data strings, e.g. as found in barcodes, into a set of key-value mappings. In this guide, you will know briefly how to use a parser and what types of parser are currently supported by Scandit. These data formats are supported: [Health Industry Bar Code (HIBC)](https://docs.scandit.com/data-capture-sdk/flutter/parser/hibc.html), [GS1 Application Identifier (https://docs.scandit.com/data-capture-sdk/flutter/parser/AI) system](https://docs.scandit.com/data-capture-sdk/flutter/parser/gs1ai.html) and [Swiss QR Codes](https://docs.scandit.com/data-capture-sdk/flutter/parser/swissqr.html), [VIN Vehicle Identification Number](https://docs.scandit.com/data-capture-sdk/flutter/parser/vin.html), [IATA Bar Coded Boarding Pass (BCBP)](https://docs.scandit.com/data-capture-sdk/flutter/parser/iata-bcbp.html), [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/flutter/parser/epc.html). More data formats will be added in future releases. Please contact us if the data format you are using is not yet supported, or you want to use the parser on a currently unsupported platform. ## Format-Specific Documentation - [Supported Data Formats](https://docs.scandit.com/data-capture-sdk/flutter/parser/formats.html) - [HIBC](https://docs.scandit.com/data-capture-sdk/flutter/parser/hibc.html) - [GS1 AI](https://docs.scandit.com/data-capture-sdk/flutter/parser/gs1ai.html) - [GS1 Digital Link](https://docs.scandit.com/data-capture-sdk/flutter/parser/gs1-digital-link.html) - [Swiss QR](https://docs.scandit.com/data-capture-sdk/flutter/parser/swissqr.html) - [VIN](https://docs.scandit.com/data-capture-sdk/flutter/parser/vin.html) - [IATA BCBP](https://docs.scandit.com/data-capture-sdk/flutter/parser/iata-bcbp.html) - [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/flutter/parser/epc.html) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: First of all, include the ScanditParser library and its dependencies to your project, if any. ## Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### New Features #### Barcode * Added `BarcodeArPopoverAnnotation.Anchor` and `BarcodeArPopoverAnnotationAnchor` enum to the Flutter binding. Added the ability to filter barcodes in `BarcodeArView` through the `BarcodeArFilter` interface. * Added the SelectionMode API to replace the SparkScan target-mode APIs and `ScanIntention.smartSelection`: Set `selectionMode` (off/on/auto) in the `BarcodeCaptureSettings` and `SparkScanSettings` to control whether an aimed-at barcode is scanned automatically or requires explicit selection. #### Id * Added Irish Garda Age Card as `RegionSpecificSubtype.IrelandAgeCard`. * Added double-sided support for the Oman residence card. * Added single-sided support for extraction of issue date and birth date from the 2025 NYC Municipal ID. #### Smart Label Capture * Extended VIN label capture to also scan Code 128 barcodes (in addition to QR, Code 39, and Data Matrix) via `createVinLabelDefinition()`. * Extended LabelCapture to accept label definitions where both "barcode" and "text" field types use the "semantics" feature simultaneously; previously this was restricted to only one field type at a time. ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Smart Label Capture * Improved Receipt Scanning efficiency by optimizing receipt image processing before extraction. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. * Updated `SymbologyDescription.forIdentifier` to return `null` for unrecognized identifiers (e.g. `"EAN-8"` instead of `"ean8"`); previously such input was silently mapped to `Codabar`. ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in item-based scanning. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Id * Fixed an issue where cropped document images were rotated when Frame Image was also enabled. * Corrected the orientation of cropped Visa document images that were being rotated incorrectly when scanned using a single-frame image source. * Fixed parser handling of non-standard Surrey BC AAMVA barcodes that were incorrectly returning "Invalid Format". #### Smart Label Capture * Fixed a memory leak in LabelCapture. * Fixed a bug where setting `valueRegexes` or `anchorRegexes` to null in frameworks was incorrectly treated the same as setting them to an empty list; they now correctly fall back to the definition type's defaults. #### Core * Fixed the Web SDK camera preview expanding to full-screen in iOS WebViews by setting `playsinline` and `webkit-playsinline` attributes on the video element; the host `WKWebView` must also enable `allowsInlineMediaPlayback`. * Fixed Flutter iOS builds with Swift Package Manager that failed to resolve when consuming the published plugins from pub.dev, due to a missing `scandit-datacapture-frameworks-core` folder under `ios/Flutter/ephemeral/`. * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a crash when the `DataCaptureContext` singleton was initialized more than once. ### Deprecations #### Barcode * The SparkScan target-mode APIs and `ScanIntention.smartSelection` are deprecated in favour of selectionMode. ## 8.4.1 **Released**: June 23, 2026 ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in SparkScan when using the item-based API. #### Id * Fixed an issue where cropped document images were rotated when they are recovered using the getFrame API. * Resolved a duplicate Objective-C class registration that could trigger spurious casting failures or crashes when an app links both ScanditCaptureCore and ScanditIdCapture. ## 8.4.0 **Released**: May 18, 2026 ### New Features #### Barcode * Added `dotRadius` property to `BarcodeBatchBasicOverlay` to allow customizing the size of dots when using the Dot overlay style. * Added support for PDF417 in the Barcode Generator. #### Id * Added support for reading the vehicle table on the back of New Zealand driving licences, with the latest expiry date returned; supported vehicle classes are 1–6, including L=learner and R=restricted variants. * Added support for new versions of USA, California – Driver's License; USA, North Carolina – Driver's License; USA, Texas – Driver's License; and USA, Oklahoma – Driver's License. #### Core * Redesigned `ZoomSwitchControl` to support multiple configurable zoom levels; the control now displays as a compact button that expands to show all available zoom levels, automatically filtered to those supported by the device hardware. * Added a new `PinchToZoom` gesture. ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. #### Core * Updated mbedtls from version 3.6.5 to 3.6.6. ### Bug Fixes #### Barcode * Fixed an issue in `BarcodeCount` where the floating shutter button was not visible after setting `shouldShowFloatingShutterButton` to `true`. * Fixed an issue preventing `BarcodeFind` from finding binary barcodes. * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. * Fixed an issue where `BarcodeCountView` would display incorrectly after rotating the device when a sibling view was present in the same parent view. * Fixed an unnecessary second scan callback that occurs after freezing barcode recognition. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed an issue where the Smart Scan Selection aimer would become too small when scan-area margins restricted the visible scan area; the aimer is now sized relative to the view, keeping a consistent on-screen size regardless of margins. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. #### Id * Fixed an issue where the US Permanent Residence Card was not processed through the VizMrz flow. * Fixed an issue where AAMVA verification was being performed even when no AAMVA document types were enabled in the accepted documents. #### Smart Label Capture * Fixed a memory leak in LabelCapture * Fixed an issue where the validation flow viewfinder was not displayed. * Fixed a race condition in the validation flow. * Fixed a bug where the label capture validation flow overlay sometimes did not reflect label capture settings when reused. * Fixed a bug that caused error messages in `DataCaptureView` to be rendered partially out-of-view. * Fixed a rare race condition in Label Capture. * Added `.asDate()` support to `ExpiryDate` and `PackingDate` label fields when the text is provided as manual input or as an Adaptive-Recognition-Engine response. * Fixed a bug where the receipt scanning overlay and validation flow overlay could not be used on the same LabelCapture mode instance. #### Core * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. * Fixed a rare crash when opening the camera. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed custom sound not working in Barcode Find on Android. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. * Fixed Flutter iOS builds with Swift Package Manager enabled that failed to resolve when consuming the published plugins from pub.dev, due to a missing scandit-datacapture-frameworks-core folder under ios/Flutter/ephemeral/. * Fixed a rare crash when starting camera capture while under memory pressure. ## 8.3.1 **Released**: April 14, 2026 ### Bug Fixes #### Smart Label Capture * Fixed the validation flow to accept dates in more formats when manually entered * Fixed a race condition in the validation flow ## 8.3.0 **Released**: March 26, 2026 ### New Features #### Barcode * Added support for composite codes in SparkScan #### Id * Added support for OCR scanning of the 2026 version of Victoria mobile driver licenses * Added IdCaptureSettings.anonymizeDefaultFields setting that controls whether the SDK applies default anonymization rules for specific document types and regions #### Smart Label Capture * Fixed a rare race condition #### Core * Added Swift Package Manager support to Flutter plugins for iOS development * Added Camera-related APIs for macro mode, torch, accessibility hints, as well as ImageBuffer and Timestamp for FrameData. * Added shouldShowZoomNotification and setProperty to DataCaptureView * Added new SparkScan APIs related to feedback, scanning mode change, and periscope mode. * Added BarcodeFilterSettings public constructor and exposed excludedSymbolCounts property for JavaScript frameworks * Added BarcodeCount-related APIs for BarcodeCountNotInListActionSettings, BarcodeCountToolbarSettings, BarcodeCountMappingFlowSettings, status mode and accessibility properties on BarcodeCountView, BarcodeCountStatusProvider with status items and callbacks, cluster support, capture list completion listener, and session update listener * Added moduleCountX and moduleCountY to Barcode API ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Improved speed of MatrixScan Count scanning phase for mid- and high-end devices ### Bug Fixes #### Barcode * Fixed an issue in BarcodeCount where the floating shutter button was not visible after setting shouldShowFloatingShutterButton to true. * Fixed a bug that was causing BarcodeFind to render barcodes filtered out by the Transformer as if they were valid targets. * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. #### Id * Fixed BarcodeDictionary anonymization setting for iOS and Web * Fixed support for UAE Esaad card * Sanitized name fields on ACT driver license to split FullName and populate first and last name properties * Added support for scanning MRZ from the back of Argentinian DN when using `FullDocumentScanner` * Fixed misplaced MRZ anonymization on FullFrame images. #### Smart Label Capture * Fixed an issue in the `LabelCaptureValidationFlowOverlay` when using it with Jetpack Compose that caused focus loss when opening the keyboard * Added `LabelCaptureValidationFlowOverlay.ShouldHandleKeyboardInsetsInternally` for cases when customers don't want to follow official Android edge-to-edge and inset guidelines #### Core * Fixed GetLastFrameData call in LabelCaptureListener not returning any frame * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.2.1 **Released**: March 5, 2026 ### Bug Fixes #### Barcode * Fixed additional information not displaying in MatrixScan Find carousel items. #### Id * Sanitized name fields on ACT DL. Splits FullName to populate first and last name properties #### Smart Label Capture * Fixed LabelCaptureValidationFlowOverlay possible issue with Jetpack Compose that caused focus loss when opening the keyboard * Added LabelCaptureValidationFlowOverlay::ShouldHandleKeyboardInsetsInternally in case customers don't want to follow official Android guidelines for edge-to-edge and insets * Fixed a rare race condition #### Core * Fixed GetLastFrameData call in LabelCaptureListener not returning any frame ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Barcode * Added new getFeedbackForScannedItem method to SparkScanFeedbackDelegate * Fixed BarcodeFilterSettings not correctly applied to the BarcodeCountSettings * Added BarcodeArResponsiveAnnotation API #### Smart Label Capture * The Validation Flow, our ready‑to‑use workflow in Smart Label Capture for capturing and validating label data with minimal code, now features a completely redesigned user interface. The update improves ergonomics through a simplified API and highly requested customization options, making Smart Label Capture more intuitive and significantly reducing integration and customization effort across a wider range of use cases * Smart Label Capture now supports Receipt Scanning Capture. The feature is available in beta (contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out). #### Core * Added Electronic Product Code (EPC) data format ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes * Barcode Generator: Improved DataMatrix encoding efficiency, which depending on input data may result in smaller generated codes ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed BarcodeCount Scan Preview issues including: fixed an issue where preview barcodes were used to populate the scanning list, the correct feedback is played when a barcode not in list is scanned, fixed an issue where scanning was not possible after the app was put in background, and corrected highlight orientation in landscape * Fixed an issue where MatrixScan AR circle highlights stopped pulsing when the app was restored from the background * Added cameraStateOnStop property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed an issue where the successful hint in BarcodeFind is not displayed * Fixed the missing found item icon in the MatrixScan Find carousel #### Id * Fixed an issue affecting MRZ scanning performance when using the user facing camera in portrait mode on Android * Fixed a memory issue leading to a persistent black screen during ID Capture startup * Treated Puerto Rico driver licenses as AAMVA to enforce barcode capture with FullScanner * Fixed a bug that would cause Canada Northwest Territories driver license scans to be incomplete #### Core * Fixed scanning against a list in MatrixScan Count * Fixed MatrixScanBubble Tap not being triggered in Cordova * Fixed an issue where the camera would not restart when opened from another app * Fixed concurrent modification of the listeners in BarcodeCapture, which was happening when customers would modify the listeners within the callback * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed an issue where some LabelCapture fields were being returned incorrectly on TS frameworks * Fixed a crash in the DataCaptureView overlay management that could occur during rapid view updates. ### Deprecations #### Smart Label Capture * Deprecated some LabelCaptureValidationFlowSetting APIs: requiredFieldErrorText, missingFieldsHintText, manualInputButtonText, as those don't make sense anymore with the redesign of Validation Flow in 8.2 ## 8.1.5 **Released**: June 10, 2026 ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in item-based scanning. #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a rare native crash (SIGABRT in BitTube::recvObjects) that could occur on Android during camera preview rendering. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. #### Core * Fixed a rare issue that was causing a crash when the app moved to the background. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed crashes caused by RuntimeExceptions thrown by OEM camera code that are not part of the standard Android Camera API contract; these exceptions are now caught and logged instead of crashing. ## 8.1.3 **Released**: March 25, 2026 ### Bug Fixes #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.1.2 **Released**: March 9, 2026 ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session #### Smart Label Capture * Fixed a rare race condition ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Id * Fixed a memory issue leading to a persistent black screen during ID Capture startup #### Core * Fixed a crash in the DataCaptureView overlay management that could occur during rapid view updates * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed scanning against a list in MatrixScan Count * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Smart Scan Selection is now available in Barcode Capture. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * [SparkScan](/sdks/flutter/sparkscan/intro.md) is not limited to only barcodes anymore, but can also scan items - in other words any combinations of barcodes and text present on a target to be scanned. The feature is available in beta at the moment, please contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out. * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. * Added, in `BarcodeAr`, new classes to create custom highlights (via `BarcodeArCustomHighlight`) and custom annotations (via `BarcodeArCustomAnnotation`). #### Id * Added NationalityISO property that maps results from Nationality field to country ISO code * Added RejectionDiagnosticJSON property to CapturedId to report debug info during Timeout rejections * Added support for new California DL, new South Carolina DL, Arizona Medical Marijuana Card, Kuwait Civil card, and new Texas DL * Our SDK can now scan the following documents both in single-side and double-side mode: - All Mexican DLs - Mexican Voter Cards ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the [“strict" symbology extension](../symbology-properties#symbology-extension-descriptions) #### Smart Label Capture * Incremental improvements in accuracy across all use-cases for the OCR model powering Smart Label Capture. ### Behavioral Changes #### Barcode * Enabling the [“ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 (“Missing Resource”) #### Smart Label Capture * Validation Flow: Manually input values for barcodes will go through a stricter validation. Some values may no longer be accepted if they do not match the symbology specs for the symbology’s definition ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Fixed a bug in the default color of BarcodeCapture highlights * Fixed an issue where popover annotations with HIGHLIGHT_TAP_AND_BARCODE_SCAN trigger could not be opened again * Fixed an issue in BarcodeSequence where camera would not be ON in portrait * Fixed an issue where SparkScan mini preview would sometimes stay in regular when entering target mode * Fixed the app becoming unresponsive after being in the background for extended periods * Added the `cameraStateOnStop` property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed an issue where the successful notification in BarcodeFind was not displayed #### Id * Fixed an issue where front expiry date anonymization rectangle is erroneously drawn on front and back * Fixed a bug that prevented VizResult anonymization of the following fields: additionalAddressInformation, bloodType, employer, fathersName, issuingAuthority, maritalStatus, mothersName, placeOfBirth, profession, race, residentialStatus * Fixed a bug concerning return complete instead of cropped images on the back of EU driving licenses #### Smart Label Capture * Fixed an issue where LabelCapture fields would return default data in some frameworks #### Core * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only * Fixed an issue where barcode scanning would permanently stop after the app returned from background, particularly when camera permission dialogs were shown during initialization ## 8.0.1 **Released**: January 14, 2026 ### Bug Fixes #### Barcode * Fixed an issue where the successful hint in BarcodeFind was not displayed * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Fixed MatrixScan Count when using the “Scanning Against a List” feature which previously just ignored the given list #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. #### Core * Upgraded all sample applications to build correctly with Flutter 3.35.3. #### Barcode * Updated the Gradle version for all sample applications to 8.14.3. * `BarcodeBatchBasicOverlay` and `BarcodeBatchBasicOverlayListener` now allow for nullable brushes. * MatrixScan AR now allows for the use of custom highlights and annotations. #### Smart Label Capture * We’re introducing an enhancement that makes Smart Label Capture more robust and scalable by complementing its on-device model with a larger, more capable model. When the on-device model can’t capture certain labels, the SDK automatically escalates to this enhancement to handle complex or unforeseen cases with high accuracy and reliability. This capability is currently available in `beta`. If you’re interested in trying it, please contact Scandit Support. For configuration details, see `labelDefinition.adaptiveRecognitionEngine`. #### ID * Added `ElementsToRetain` to `MobileDocumentScanner`: The set of data elements that the application intends to retain from scanned mobile documents. This information is used to set the `IntentToRetain` flag in ISO 18013-5 mdoc requests, which is required for legal compliance with data protection standards. An empty set indicates no elements will be retained, and `IntentToRetain` will be set to `false` for all fields. * ID Capture now supports full-frame anonymization. * The result of `decodeMobileDriverLicenseViz`, which is currently returned as part of the `VizResult` within `CapturedId`, will now be provided through a new field named `mobileDocumentOcr`. * Added `CapturedId::isCitizenPassport`, which indicates whether the passport was issued to a citizen of the issuing country. Returns `false` for travel documents such as refugee, stateless, or alien passports, and for any passports issued by organizations rather than states. * The following Chinese travel permits now extract VIZ + MIZ data during double-sided scanning flows: * CT - Taiwan Residents Mainland Travel Permit * W - Mainland Residents Exit-Entry Permit to and from Hong Kong and Macao * CD - Mainland Residents Entry-Exit Permit to and from Taiwan ### Behavioral Changes #### Barcode * Symbology `RM4SCC` has been renamed to `ROYAL_MAIL_4STATE`. * Changed the default highlight brush in SparkScan and Barcode Capture. * Removed the `ExtendedSparkScanViewUiListener` as the same functionality is offered by `SparkScanViewUiListener`. #### ID * The configuration for the following documents has been changed as detailed below: * Australian mobile driver licenses (mDL) are now treated as normal documents, with no separate mode. * US Green Cards are now treated as residence permits. * Removed the deprecated API `DateResult::toDate`. Use `DateResult::toLocalDate` or `DateResult::toUtcDate` instead. * `fullName` now an optional field on all `IdCapture` result types and `capturedMrz` now an optional field on `MrzResult`. ### Bug Fixes #### ID * Fixed a bug that could get the scanner stuck when scanning a US passport card. ### Deprecations #### Core * `VideoResolution::Auto` is now deprecated. Please use the capture mode's `recommendedCameraSettings` for the best results. ## 7.6.7 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/flutter/release-notes) --- ## Advanced Configurations # Advanced Configurations SparkScan is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are some cases where you might want to customize the behavior of SparkScan. This guide will show you how to add additional capabilities and further customize SparkScan to best fit your needs. ## Advanced Capabilities ### Hardware Button Control Allowing the end user to control the scanner with hardware buttons can be useful if your users typically wear gloves. It can also improve ergonomics in some workflows. SparkScan offers a built-in API to let you do this via [SparkScanViewSettings.hardwareTriggerEnabled](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled). ### Trigger Error State You may want to introduce logic in your app to show an error message when scanning specific barcodes (e.g. barcodes already added to the list, barcodes from the wrong lot etc.). SparkScan offers a built-in error state you can easily set to trigger an error feedback prompt to the user. You can customize: - The text message. - The timeout of the error message: the scanner will be paused for the specified amount of time, but the user can quickly restart the scanning process by tapping the trigger button. :::tip A high timeout (>10s) typically requires the users to interact with the UI to start scanning again. This is a good choice when you want to interrupt the scanning workflow (e.g. because a wrong barcode is scanned and some actions need to be performed). A small timeout (\ This error state for a code that should not have been scanned. This error state for a code that has been scanned more than once. ### Reject Barcodes To prevent scanning unwanted barcodes (like those already listed or from incorrect lots), use SparkScan's built-in error state. Setting the `scandit.datacapture.barcode.spark.feedback.Error.ResumeCapturingDelay` parameter to `0` allows the user to continue scanning immediately without pausing on rejected codes. ## UI Customization :::tip Please refer to [SparkScanView](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) for the full list of parameters. ::: import Customization from '../../../partials/advanced/_sparkscan-customization.mdx'; ## Workflow Options This section explains all the available options to configure SparkScan to best fit your case, in case you found something that didn't work well in the default configuration (that remains our recommended option). Developers can set a combination of scanning mode, scanning behavior and camera preview behavior - defining the initial state of the scanner. This can be done by setting the default scanning mode (SDCSparkScanViewSettings.defaultScanningMode). This combination allows for flexible configurations to suit different scanning needs. ### Scanning Mode The scanning mode determines the programmatic presence of an aimer in the preview to help with precision scanning. | Mode | Description | | ----------- | --------------------------------------------------- | | **Default** | Generally recommended. This mode will display a small camera preview to aid with aiming. The preview size and zoom level can be adjusted as needed. User can aim easily at the intended barcode. | | **Target** | This mode will always add an aimer to the camera preview to precisely select the barcode to scan. This is recommended only when selecting among many close barcodes is the common task. | :::tip Even in the *Default* mode, SparkScan will automatically show an aimer when multiple barcodes are present in the view and no clear intention from the user to scan a single one is recorded ([`SDCSparkScanSettings.ScanIntention`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/spark-scan-settings.html#property-scandit.datacapture.barcode.spark.SparkScanSettings.ScanIntention)). Enabling the *Target* mode will simply force this "precision selection" state to be on at all time. ::: ### Scanning Behavior The scanning behavior determines how barcodes are scanned - one at a time or continuously. | Behavior | Description | | ------------------- | ---------------------------------------------------------- | | **Single scan** | Scan one barcode at a time. The user needs to trigger the scanner every time to scan a barcode. This allows for a more controlled scanning and lower battery consumption. | | **Continuous scan** | Scan barcodes consecutively. The user needs to trigger the scanner once and barcodes will be scanned without any further interaction before each scan. This allows for a smoother experience when multiple barcodes need to be scanned consecutively. | :::tip Users can enable continuous scanning by holding down the trigger button. This gesture can be disabled (`SDCSparkScanViewSettings.holdToScanEnabled`). ::: ### Preview Behavior The preview behavior determines how the camera preview behaves when the scanner is not actively scanning. | Behavior | Description | | -------------- | -------------------------- | | **Default** | Preview fades away when the scanner is off. This lets the user check important information displayed by the app and reduces battery consumption. | | **Persistent** | Preview remains visible, but darkened, even when the scanner is off. This is useful for scenarios where you want to select a barcode (among many) or need to look through the preview at all times (to ensure the right scan) - especially if used in conjunction with the target mode. | ### Configuring the default scanning mode Combine a scanning mode, scanning behavior, and preview behavior and assign it to [`SparkScanViewSettings.defaultScanningMode`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/spark-scan-view-settings.html). For example, to start in continuous scanning with the preview always visible: ```dart final viewSettings = SparkScanViewSettings(); viewSettings.defaultScanningMode = SparkScanScanningModeDefault.fromPreviewBehavior( SparkScanScanningBehavior.continuous, // or .single SparkScanPreviewBehavior.persistent, // or .defaultBehaviour ); ``` Use `SparkScanScanningModeTarget.fromPreviewBehavior(...)` instead of `SparkScanScanningModeDefault` to force the aimer (target mode). --- ## Get Started # Get Started This page describes the step-by-step instructions that helps you to add SparkScan to your application: - Initialize the Data Capture Context - Configure the Spark Scan Mode - Create the SparkScanView with the desired settings and bind it to the application’s lifecycle - Register the listener to be informed when new barcodes are scanned and update your data whenever this event occurs ## Prerequisites - The latest stable version of the [Flutter SDK](https://pub.dev/publishers/scandit.com/packages). - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). - If you have not already done so, see [this guide](../add-sdk.md) for information on how to add the Scandit Data Capture SDK to your project :::note Devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/flutter/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```dart await DataCaptureContext.initialize("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure the SparkScan Mode The SparkScan Mode is configured through SparkScanSettings and allows you to register one or more listeners that are informed whenever a new barcode is scanned. For this tutorial, we set up SparkScan for scanning EAN13 codes. You can change this to the correct symbologies for your use case (for instance, Code 128, Code 39…). ```dart var settings = SparkScanSettings(); settings.enableSymbologies({ Symbology.ean13Upca }); ``` Next, create a SparkScan instance with the settings initialized in the previous step: ```dart var viewSettings = SparkScanViewSettings(); // setup the desired appearance settings by updating the fields in the object above ``` ## Create the SparkScan View The SparkScan built-in user interface includes the camera preview and scanning UI elements. These guide the user through the scanning process. The [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) appearance can be customized through [SparkScanViewSettings](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/spark-scan-view-settings.html). See the [SparkScan Workflow Options](./advanced.md#workflow-options) section for more information. By adding a [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView), the scanning interface (camera preview and scanning UI elements) gets added automatically to your application. You can add a [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) to your view hierarchy: ```dart var sparkScanView = SparkScanView.forContext(YOUR_WIDGET_TREE_BODY, DataCaptureContext.sharedInstance, sparkScan, null); ``` Additionally, make sure to call [`SparkScanView.onPause()`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.OnPause) in your app state handling logic. You have to call this for the correct functioning of the [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView). ```dart @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state != AppLifecycleState.resumed) { sparkScanView.onPause() } } ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [SparkScanListener](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface and register the listener to the SparkScan mode. ```dart // Register self as a listener to monitor the spark scan session. sparkScan.addListener(this); ``` [SparkScanListener.didScan()](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/spark-scan-listener.html#method-scandit.datacapture.barcode.spark.ISparkScanListener.OnBarcodeScanned) is called when a new barcode has been scanned. This result can be retrieved from the first object in the provided barcodes list: [SparkScanSession.newlyRecognizedBarcode](https://docs.scandit.com/data-capture-sdk/flutter/barcode-capture/api/spark-scan-session.html#property-scandit.datacapture.barcode.spark.SparkScanSession.NewlyRecognizedBarcode). :::note Note that this list only contains one barcode entry. ::: ```dart @override Future didScan(SparkScan sparkScan, SparkScanSession session, Future getFrameData()) async { if (session.newlyRecognizedBarcode == null) return; // Gather the recognized barcode var barcode = session.newlyRecognizedBarcode!; // Do something with the recognized barcode } ``` ## Scan Some Barcodes Now that you’re up and running, go find some barcodes to scan. Don’t feel like getting up from your desk? Here’s a [handy pdf of barcodes](https://github.com/Scandit/.github/blob/main/images/PrintTheseBarcodes.pdf) you can print out. --- ## About SparkScan # About SparkScan SparkScan is our pre-built smartphone scanning interface designed for high-performance barcode scanning. It fits on top of any smartphone application, providing an intuitive user interface for simple, fast and ergonomic scanning in scan-intensive workflows, such as inventory management in retail, or goods receiving in logistics. SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs. ## UI Overview The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience. Two main elements compose the UI: ![SparkScan UI](/img/sparkscan/features_web.png) - **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc). - **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space. There are additional UI elements available for displaying additional scanning modes, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section. ## Workflow Description When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use. To start scanning, the user can simply tap on it. When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app). In the default configuration: - Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away. - Tapping on the trigger button or the mini preview will restart immediately the scanner. Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state. If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released. List building use case using SparkScan. The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field. But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more. ## Supported Symbologies SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx). ## AI-Powered Features SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide. --- ## Installation # Installation This page describes how to integrate the Scandit Data Capture SDK into your iOS project. The SDK can be added via: - [CocoaPods](#install-via-package-manager) - [Carthage](#install-via-package-manager) - [Swift Package Manager](#install-via-package-manager) - [Import in Source Code](#import-in-source-code) ## Prerequisites Before you begin, make sure you have the following prerequisites in place: - Latest version of Xcode - iOS project with a deployment target of iOS 15.0+ :::note ID Capture requires a minimum deployment target of iOS 15.0. ::: - Scandit license key, sign up for a [free trial](https://www.scandit.com/trial/) if you don't already have a license key ### Internal Dependencies import InternalDependencies from '../../partials/get-started/_internal-deps.mdx'; ## Install via Package Manager [CocoaPods](https://cocoapods.org/) is a dependency manager for Swift and Objective-C Cocoa projects. To integrate the Scandit Data Capture SDK into your Xcode project using CocoaPods, specify the required pods for your use case, detailed above in [Internal Dependencies](#internal-dependencies), in your `Podfile`: ```ruby pod 'ScanditCaptureCore', # Add the necessary pods based on the features needed for your use case ``` [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate the Scandit Data Capture SDK into your Xcode project using Carthage, specify it in your `Cartfile`: ```ruby binary "https://ssl.scandit.com/sdk/download/carthage/ScanditCaptureCore.json" ``` You also need to add the corresponding binaries based on the features you need as detailed above in [Internal Dependencies](#internal-dependencies). For example, if you want to add the [`ScanditBarcodeCapture`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api.html) API, you need to add the following Carthage binary: ```ruby binary "https://ssl.scandit.com/sdk/download/carthage/ScanditBarcodeCapture.json" ``` To integrate the Scandit Data Capture SDK into your Xcode project using Swift Package Manager, add the frameworks you want to add in the _Package Dependencies_ section of your project. ![Add Package Dependencies](./img/spm.png) Add our SPM package repository: ```shell https://github.com/Scandit/datacapture-spm ``` Or if you prefer checking out git repositories via SSH: ```shell git@github.com:Scandit/datacapture-spm.git ``` You also need to add the corresponding frameworks based on the features you need as detailed in [Internal Dependencies](#internal-dependencies). ## Add the Frameworks Manually Adding the frameworks manually is a single step process when using the XCFramework archives. All you need to do is drag the frameworks into the _Frameworks, Libraries, and Embedded Content_ section of your target. Make sure to select _Embed and Sign_ for the _Embed_ option. Please note that you will always need at least `ScanditCaptureCore.xcframework` which contains the shared functionality used by the other data capture modules. ![Add Frameworks Manually](./img/embedded-binaries.png) :::note When building the project, by default Xcode will look for the frameworks in the root folder of the project. If you choose to copy the frameworks in a different location, don’t forget to update the `FRAMEWORK_SEARCH_PATHS` build setting accordingly. ::: ## Import in Source Code To import the Scandit Data Capture SDK into your source code, add the following import statement: ```swift import ScanditCaptureCore import ScanditBarcodeCapture import ScanditLabelCapture import ScanditIdCapture import ScanditParser ``` ```objectivec @import ScanditCaptureCore; @import ScanditBarcodeCapture; @import ScanditLabelCapture; @import ScanditIdCapture; @import ScanditParser; ``` ## Additional Information import OSSLicense from '../../partials/_third-party-licenses.mdx'; --- ## Agent Skills import SkillsPage from '@site/src/components/SkillsPage'; # Agent Skills for iOS --- ## Configure Barcode Symbologies # Configure Barcode Symbologies import Intro from '../../../partials/configure-symbologies/_intro.mdx' ## Enable the Symbologies You Want to Read import EnableSymbologies from '../../../partials/configure-symbologies/_enable-symbologies.mdx' The following code shows you how to enable scanning Code 128 codes for barcode capture: ```swift let settings = BarcodeCaptureSettings() settings.set(symbology: .code128, enabled: true) ``` import CapturePresents from '../../../partials/configure-symbologies/_capture-presents.mdx' ## Configure the Active Symbol Count Barcode symbologies such as Code 128, Code 39, Code 93 or Interleaved Two of Five can store variable-length data. As an example, Code 39 can be used to store a string anywhere from 1 to 40-50 symbols. There is no fixed upper limit, though there are practical limitations to the code’s length for it to still be conveniently readable by barcode scanners. For performance reasons, the Scandit Data Capture SDK limits the [possible symbol range](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.ActiveSymbolCounts) for variable-length symbologies. If you want to read codes that are shorter/longer than the specified default range or you want to tailor your app to only read codes of a certain length, you need to change the active symbol count of the symbology to accommodate the data length you want to use in your application. The below code shows how to change the active symbol count for Code 128 to read codes with 6, 7 and 8 symbols. ```swift let settings = BarcodeCaptureSettings() let symbologySettings = settings.settings(for: .code128) symbologySettings.activeSymbolCounts = Set(6...8) ``` import CalculateSymbolCount from '../../../partials/configure-symbologies/_calculate-symbol-count.mdx' ## Read Bright-on-Dark Barcodes Most barcodes are printed using dark ink on a bright background. Some symbologies allow the colors to be inverted and can also be printed using bright ink on a dark background. This is not possible for all symbologies as it could lead to false reads when the symbology is not designed for this use case. See [symbology properties](../symbology-properties.mdx) to learn which symbologies allow color inversion. When you enable a symbology as described above, only dark-on-bright codes are enabled (see [`SDCSymbologySettings.enabled`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.IsEnabled)). When you also want to read bright-on-dark codes, color-inverted reading for that symbology must also be enabled (see [`SDCSymbologySettings.colorInvertedEnabled:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.IsColorInvertedEnabled)). The following code shows how to enable color-inverted reading for Code 128: ```swift let settings = BarcodeCaptureSettings() let symbologySettings = settings.settings(for: .code128) symbologySettings.isColorInvertedEnabled = true ``` ## Enforce Checksums Some symbologies have a mandatory checksum that always gets enforced while others only have optional [checksums](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/checksum.html#enum-scandit.datacapture.barcode.Checksum).Enforcing an optional checksum reduces false positives as an additional check can be performed. When enabling a checksum you have to make sure that the data of your codes contains the calculated checksum otherwise the codes get discarded as the checksum doesn’t match. All available checksums per symbology can be found in [symbology properties](../symbology-properties.mdx). You can enforce a specific checksum by setting it through [`SDCSymbologySettings.checksums`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.Checksums): ```swift let settings = BarcodeCaptureSettings() let symbologySettings = settings.settings(for: .code39) symbologySettings.checksums = [.mod43] ``` ## Enable Symbology-Specific Extensions Some symbologies allow further configuration. These configuration options are available as symbology extensions that can be enabled/disabled for each symbology individually. Some extensions affect how the data in the code is formatted, others allow for more relaxed recognition modes that are disabled by default to eliminate false reads. All available extensions per symbology and a description of what they do can be found in the documentation on [symbology properties](../symbology-properties.mdx). To enable/disable a symbology extension, use [`SDCSymbologySettings.setExtension:enabled:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/symbology-settings.html#method-scandit.datacapture.barcode.SymbologySettings.SetExtensionEnabled). The following code shows how to enable the full ASCII extension for Code 39. ```swift let settings = BarcodeCaptureSettings() let symbologySettings = settings.settings(for: .code39) symbologySettings.set(extension: "full_ascii", enabled: true) ``` This extension allows Code 39 to encode all 128 ASCII characters instead of only the 43 characters defined in the standard. The extension is disabled by default as it can lead to false reads when enabled. --- ## Get Started With SwiftUI # Get Started With SwiftUI In this guide you will learn step-by-step how to add Barcode Capture to your application using SwiftUI. The general steps are: 1. **Create a UIViewController**: Implement the barcode scanning logic following the main [Get Started guide](./get-started.md) 2. **Create a SwiftUI wrapper**: Use `UIViewControllerRepresentable` to integrate the `UIViewController` 3. **Use in your SwiftUI app**: Add the SwiftUI view to your app's view hierarchy The core barcode scanning implementation (data capture context, settings, camera setup, etc.) remains the same as described in the main guide. ## Create a UIViewController for Barcode Scanning To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a `UIViewController` that handles the barcode scanning functionality. This follows the same implementation as described in the main [Get Started guide](./get-started.md). Create a `BarcodeCaptureViewController` class that implements all the steps from the UIKit guide: ```swift import ScanditBarcodeCapture import UIKit class BarcodeCaptureViewController: UIViewController { private var context: DataCaptureContext! private var camera: Camera? private var barcodeCapture: BarcodeCapture! private var captureView: DataCaptureView! private var overlay: BarcodeCaptureOverlay! override func viewDidLoad() { super.viewDidLoad() setupRecognition() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodeCapture.isEnabled = true camera?.switch(toDesiredState: .on) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) barcodeCapture.isEnabled = false camera?.switch(toDesiredState: .off) } func setupRecognition() { // Follow the implementation from the main Get Started guide: // 1. Create data capture context // 2. Configure barcode scanning settings // 3. Register the barcode capture listener // 4. Use the built-in camera // 5. Create capture view and overlay } } extension BarcodeCaptureViewController: BarcodeCaptureListener { func barcodeCapture(_ barcodeCapture: BarcodeCapture, didScanIn session: BarcodeCaptureSession, frameData: FrameData) { // Handle barcode scanning results // See the main Get Started guide } } ``` ## Create a SwiftUI View using UIViewControllerRepresentable Now create a SwiftUI wrapper that integrates the `UIViewController` into your SwiftUI app: ```swift import SwiftUI import UIKit struct BarcodeCaptureRepresentable: UIViewControllerRepresentable { typealias UIViewControllerType = BarcodeCaptureViewController func makeUIViewController(context: Context) -> BarcodeCaptureViewController { return BarcodeCaptureViewController() } func updateUIViewController(_ uiViewController: BarcodeCaptureViewController, context: Context) { // Update the view controller if needed } } ``` ## Use the SwiftUI View in Your App Finally, use the `BarcodeCaptureRepresentable` in your SwiftUI app: ```swift import SwiftUI @main struct MyApp: App { var body: some Scene { WindowGroup { BarcodeCaptureRepresentable() } } } ``` Or within another SwiftUI view: ```swift struct ContentView: View { var body: some View { NavigationView { BarcodeCaptureRepresentable() .navigationTitle("Barcode Scanner") } } } ``` ## Alternative: Using UIViewRepresentable As an alternative to wrapping a `UIViewController`, you can implement the barcode scanning functionality directly using `UIViewRepresentable`. This approach uses a `Coordinator` to hold the SDK objects, ensuring they are created once and persist across SwiftUI updates: ```swift import ScanditBarcodeCapture import SwiftUI struct BarcodeCaptureView: UIViewRepresentable { let onBarcodeScanned: (Barcode) -> Void func makeCoordinator() -> Coordinator { Coordinator() } func makeUIView(context: Context) -> UIView { let coordinator = context.coordinator coordinator.onBarcodeScanned = onBarcodeScanned if let camera = Camera.default { // Apply recommended camera settings let cameraSettings = BarcodeCapture.recommendedCameraSettings camera.apply(cameraSettings) // Turn on the camera coordinator.dataCaptureContext.setFrameSource(camera) camera.switch(toDesiredState: .on) coordinator.camera = camera } // Enable barcode capture coordinator.barcodeCapture.isEnabled = true // Create the capture view let captureView = DataCaptureView(context: coordinator.dataCaptureContext, frame: .zero) captureView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // Create the overlay coordinator.overlay = BarcodeCaptureOverlay(barcodeCapture: coordinator.barcodeCapture, view: captureView) return captureView } func updateUIView(_ uiView: UIView, context: Context) { context.coordinator.onBarcodeScanned = onBarcodeScanned } static func dismantleUIView(_ uiView: UIView, coordinator: Coordinator) { coordinator.barcodeCapture.isEnabled = false coordinator.camera?.switch(toDesiredState: .off) } class Coordinator: NSObject, BarcodeCaptureListener { let dataCaptureContext: DataCaptureContext let barcodeCapture: BarcodeCapture var overlay: BarcodeCaptureOverlay? var camera: Camera? var onBarcodeScanned: ((Barcode) -> Void)? override init() { // Create the data capture context DataCaptureContext.initialize(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") dataCaptureContext = DataCaptureContext.shared // Configure barcode capture settings let settings = BarcodeCaptureSettings() // ... // Create barcode capture mode barcodeCapture = BarcodeCapture(context: dataCaptureContext, settings: settings) super.init() barcodeCapture.addListener(self) } nonisolated func barcodeCapture(_ barcodeCapture: BarcodeCapture, didScanIn session: BarcodeCaptureSession, frameData: FrameData) { guard let barcode = session.newlyRecognizedBarcode else { return } DispatchQueue.main.async { self.onBarcodeScanned?(barcode) } } } } ``` You can then use this view directly in your SwiftUI app: ```swift struct ContentView: View { var body: some View { NavigationView { BarcodeCaptureView { barcode in // Handle the scanned barcode } .navigationTitle("Barcode Scanner") } } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Barcode Capture to your application. The general steps are: - Creating a new Data Capture Context instance - Create your barcode capture settings and enable the barcode symbologies you want to read - Create a new barcode capture mode instance and initialize it - Register a barcode capture listener to receive scan events - Process successful scans according to your application’s needs and decide whether more codes will be scanned or the scanning process should be stopped - Obtain a camera instance and set it as the frame source on the data capture context - Display the camera preview by creating a data capture view - If displaying a preview, optionally create a new overlay and add it to data capture view for better visual feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Configure Barcode Scanning Settings Barcode scanning is orchestrated by the [`SDCBarcodeCapture`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) [data capture mode](https://docs.scandit.com/data-capture-sdk/ios/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). This class is the main entry point for scanning barcodes. It is configured through [`SDCBarcodeCaptureSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) that will get informed whenever new codes have been recognized. Here we will setup barcode scanning for a small list of barcode types, called [symbologies](../barcode-symbologies.mdx). The list of symbologies to enable is application specific. We recommend that you only enable the symbologies your application requires. If you are not familiar with the symbologies that are relevant for your use case, you can use [capture presets](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/capture-preset.html#enum-scandit.datacapture.barcode.CapturePreset) that are tailored for different verticals (e.g. retail, logistics). ```swift let settings = BarcodeCaptureSettings() settings.set(symbology: .code128, enabled: true) settings.set(symbology: .code39, enabled: true) settings.set(symbology: .qr, enabled: true) settings.set(symbology: .ean8, enabled: true) settings.set(symbology: .upce, enabled: true) settings.set(symbology: .ean13UPCA, enabled: true) ``` :::note If you are not disabling barcode capture immediately after having scanned the first code, consider setting the [`SDCBarcodeCaptureSettings.codeDuplicateFilter`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-capture-settings.html#property-scandit.datacapture.barcode.BarcodeCaptureSettings.CodeDuplicateFilter) to around `500` or even `-1` if you do not want codes to be scanned more than once. ::: Next, create a `SDCBarcodeCapture` instance with the settings initialized in the previous step: ```swift barcodeCapture = BarcodeCapture(context: context, settings: settings) ``` ## Register the Barcode Capture Listener To get informed whenever a new code has been recognized, add a [`SDCBarcodeCaptureListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) through [`SDCBarcodeCapture.addListener:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.AddListener) and implement the listener methods to suit your application’s needs. First conform to the `SDCBarcodeCaptureListener` protocol. For example: ```swift extension ViewController: BarcodeCaptureListener { func barcodeCapture(_ barcodeCapture: BarcodeCapture, didScanIn session: BarcodeCaptureSession, frameData: FrameData) { let recognizedBarcode = session.newlyRecognizedBarcode // Do something with the barcode. } } ``` Then add the listener: ```swift barcodeCapture.addListener(self) ``` ### Rejecting Barcodes To prevent scanning unwanted codes, you can reject them by adding the desired logic to the `didScanIn` method. The example below will only scan barcodes beginning with the digits `09` and ignore all others, using a transparent brush to distinguish a rejected barcode from a recognized one: ```swift ... guard barcodeData.hasPrefix("09:") else { self.overlay.brush = Brush.transparent return } ... ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device. :::note In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [`NSCameraUsageDescription`](https://developer.apple.com/documentation/bundleresources/information_property_list/nscamerausagedescription) key in your app’s `Info.plist` file. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```swift let cameraSettings = BarcodeCapture.recommendedCameraSettings // Depending on the use case further camera settings adjustments can be made here. let camera = Camera.default camera?.apply(cameraSettings) ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [`SDCDataCaptureContext.setFrameSource:completionHandler:`](https://docs.scandit.com/data-capture-sdk/ios/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync). The camera is off by default and must be turned on. This is done by calling [`SDCFrameSource.switchToDesiredState:completionHandler:`](https://docs.scandit.com/data-capture-sdk/ios/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [`SDCFrameSourceStateOn`](https://docs.scandit.com/data-capture-sdk/ios/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```swift context.setFrameSource(camera) camera?.switch(toDesiredState: .on) ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a `SDCDataCaptureView` to your view hierarchy: ```swift let captureView = DataCaptureView(context: context, frame: view.bounds) captureView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(captureView) // To visualize the results of barcode scanning, the following overlay can be added: let overlay = BarcodeCaptureOverlay(barcodeCapture: barcodeCapture, view: captureView) ``` ## Disabling Barcode Capture To disable barcode capture, for instance as a consequence of a barcode being recognized, set [`SDCBarcodeCapture.enabled`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-capture.html#property-scandit.datacapture.barcode.BarcodeCapture.IsEnabled) to `NO`. The effect is immediate: no more frames will be processed after the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## Barcode Generator # Barcode Generator The Barcode Generator is a simple tool to generate barcodes directly from the Scandit SDK. In this guide, we will show you how to use the Barcode Generator to generate barcodes and QR codes. The Barcode Generator supports the following formats: * Code 39 * Code 128 * EAN 13 * UPCA * ITF * QR * DataMatrix * PDF417 (SDK version >= 8.2) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Generating Barcodes To generate barcodes, you need to create a [`SDCDataCaptureContext`](https://docs.scandit.com/data-capture-sdk/ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`SDCBarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.BarcodeGeneratorBuilder), and use the method of [`SDCBarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) for the symbology you are interested in, in this example Code 128. ```swift let context = DataCaptureContext(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") let builder = BarcodeGenerator.code128BarcodeGeneratorBuilder(with: context) ``` You can configure the colors used in the resulting image: ```swift builder.foregroundColor = .black builder.backgroundColor = .white ``` When the builder is configured get the `SDCBarcodeGenerator` and try to generate the image: ```swift do { let generator = try builder.build() let image = try generator.generate(with: dataString, imageWidth: 200.0) // Use the image } catch { // Handle the error print(error) } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-generator.html) for more information. ## Generating QR Codes To generate barcodes, you need to create a [`SDCDataCaptureContext`](https://docs.scandit.com/data-capture-sdk/ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`SDCQRCodeBarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder) using the method of [`SDCBarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) specific for QR codes. ```swift let context = DataCaptureContext(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") let builder = BarcodeGenerator.qrCodeBarcodeGeneratorBuilder(with: context) ``` You can configure the colors used in the resulting image: ```swift builder.foregroundColor = .black builder.backgroundColor = .white ``` There are two settings that can be configured for QR codes: [`SDCQRCodeBarcodeGeneratorBuilder.errorCorrectionLevel`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithErrorCorrectionLevel) and [`SDCQRCodeBarcodeGeneratorBuilder.versionNumber`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithVersionNumber). ```swift builder.errorCorrectionLevel = .medium builder.versionNumber = 4 ``` When the builder is configured get the `SDCBarcodeGenerator` and try to generate the image: ```swift do { let generator = try builder.build() let image = try generator.generate(with: dataString, imageWidth: 200.0) // Use the image } catch { // Handle the error print(error) } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-generator.html) for more information. --- ## Get Started With SwiftUI # Get Started With SwiftUI In this guide you will learn step-by-step how to add Barcode Selection to your application using SwiftUI. The general steps are: 1. **Create a UIViewController**: Implement the barcode selection logic following the main [Get Started guide](./get-started.md) 2. **Create a SwiftUI wrapper**: Use `UIViewControllerRepresentable` to integrate the `UIViewController` 3. **Use in your SwiftUI app**: Add the SwiftUI view to your app's view hierarchy The core barcode selection implementation (data capture context, settings, camera setup, etc.) remains the same as described in the main guide. ## Create a UIViewController for Barcode Selection To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a `UIViewController` that handles the barcode selection functionality. This follows the same implementation as described in the main [Get Started guide](./get-started.md). Create a `BarcodeSelectionViewController` class that implements all the steps from the UIKit guide: ```swift import ScanditBarcodeCapture import UIKit class BarcodeSelectionViewController: UIViewController { private var context: DataCaptureContext! private var camera: Camera? private var barcodeSelection: BarcodeSelection! private var captureView: DataCaptureView! private var overlay: BarcodeSelectionBasicOverlay! override func viewDidLoad() { super.viewDidLoad() setupRecognition() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodeSelection.isEnabled = true camera?.switch(toDesiredState: .on) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) barcodeSelection.isEnabled = false camera?.switch(toDesiredState: .off) } func setupRecognition() { // Follow the implementation from the main Get Started guide: // 1. Create data capture context // 2. Configure the Barcode Selection Mode // 3. Register the listener to receive scan events // 4. Obtain the camera instance and set as frame source // 5. Create capture view and overlay } } extension BarcodeSelectionViewController: BarcodeSelectionListener { func barcodeSelection(_ barcodeSelection: BarcodeSelection, didUpdateSelection session: BarcodeSelectionSession, frameData: FrameData?) { // Handle barcode selection results // See the main Get Started guide } } ``` ## Create a SwiftUI View using UIViewControllerRepresentable Now create a SwiftUI wrapper that integrates the UIViewController into your SwiftUI app: ```swift import SwiftUI import UIKit struct BarcodeSelectionRepresentable: UIViewControllerRepresentable { typealias UIViewControllerType = BarcodeSelectionViewController func makeUIViewController(context: Context) -> BarcodeSelectionViewController { return BarcodeSelectionViewController() } func updateUIViewController(_ uiViewController: BarcodeSelectionViewController, context: Context) { // Update the view controller if needed } } ``` ## Use the SwiftUI View in Your App Finally, use the `BarcodeSelectionRepresentable` in your SwiftUI app: ```swift import SwiftUI @main struct MyApp: App { var body: some Scene { WindowGroup { BarcodeSelectionRepresentable() } } } ``` Or within another SwiftUI view: ```swift struct ContentView: View { var body: some View { NavigationView { BarcodeSelectionRepresentable() .navigationTitle("Barcode Selection") } } } ``` ## Alternative: Using UIViewRepresentable As an alternative to wrapping a `UIViewController`, you can implement the barcode selection functionality directly using `UIViewRepresentable`. This approach uses a `Coordinator` to hold the SDK objects, ensuring they are created once and persist across SwiftUI updates: ```swift import ScanditBarcodeCapture import SwiftUI struct BarcodeSelectionView: UIViewRepresentable { let onBarcodeSelectionUpdated: ([Barcode]) -> Void func makeCoordinator() -> Coordinator { Coordinator() } func makeUIView(context: Context) -> UIView { let coordinator = context.coordinator coordinator.onSelectionUpdated = onBarcodeSelectionUpdated if let camera = Camera.default { // Apply recommended camera settings let cameraSettings = BarcodeSelection.recommendedCameraSettings camera.apply(cameraSettings) // Turn on the camera coordinator.dataCaptureContext.setFrameSource(camera) camera.switch(toDesiredState: .on) coordinator.camera = camera } // Enable barcode selection coordinator.barcodeSelection.isEnabled = true // Create the capture view let captureView = DataCaptureView(context: coordinator.dataCaptureContext, frame: .zero) captureView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // Create the overlay coordinator.overlay = BarcodeSelectionBasicOverlay(barcodeSelection: coordinator.barcodeSelection, view: captureView, style: .frame) return captureView } func updateUIView(_ uiView: UIView, context: Context) { context.coordinator.onSelectionUpdated = onBarcodeSelectionUpdated } static func dismantleUIView(_ uiView: UIView, coordinator: Coordinator) { coordinator.barcodeSelection.isEnabled = false coordinator.camera?.switch(toDesiredState: .off) } class Coordinator: NSObject, BarcodeSelectionListener { let dataCaptureContext: DataCaptureContext let barcodeSelection: BarcodeSelection var overlay: BarcodeSelectionBasicOverlay? var camera: Camera? var onSelectionUpdated: (([Barcode]) -> Void)? override init() { // Create the data capture context DataCaptureContext.initialize(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") dataCaptureContext = DataCaptureContext.shared // Configure barcode selection settings let settings = BarcodeSelectionSettings() // ... // Create barcode selection mode barcodeSelection = BarcodeSelection(context: dataCaptureContext, settings: settings) super.init() barcodeSelection.addListener(self) } nonisolated func barcodeSelection(_ barcodeSelection: BarcodeSelection, didUpdateSelection session: BarcodeSelectionSession, frameData: FrameData?) { let selectedBarcodes = session.selectedBarcodes DispatchQueue.main.async { self.onSelectionUpdated?(selectedBarcodes) } } } } ``` You can then use this view directly in your SwiftUI app: ```swift struct ContentView: View { var body: some View { NavigationView { BarcodeSelectionView { barcodes in // Handle the selected barcodes } .navigationTitle("Barcode Selection") } } } ``` --- ## Get Started # Get Started :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/ios/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: In this guide you will learn step-by-step how to add Barcode Selection to your application. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Selection settings - Creating a new Barcode Selection mode instance - Registering the listener to receive scan events: - Processing the successful scans according to your application’s needs, e.g. by looking up information in a database - Deciding whether more codes will be scanned, or the scanning process should be stopped - Obtaining the camera instance and set as frame source ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Configure the Barcode Selection Mode Barcode selection is orchestrated by the [`SDCBarcodeSelection`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) data capture mode. It is configured via [`SDCBarcodeSelectionSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and allows you to register one or more listeners for when new codes have been selected. Here we setup barcode scanning for the desired barcode [symbologies](../barcode-symbologies.mdx). The list of symbologies to enable is highly application specific, and we recommend that you **only enable the list of symbologies your application requires**: ```swift let settings = BarcodeSelectionSettings() settings.set(symbology: .code128, enabled: true) settings.set(symbology: .ean8, enabled: true) settings.set(symbology: .upce, enabled: true) settings.set(symbology: .ean13UPCA, enabled: true) ``` And then create a `SDCBarcodeSelection` instance with the Data Capture Context and the settings initialized in the previous step: ```swift let barcodeSelection = BarcodeSelection(context: context, settings: settings) ``` ### Selection Types The behavior of Barcode Selection can be changed by using a different [selection type](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-type.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionType). This defines the method used by `SDCBarcodeSelection` to select codes. There are two types: - [`SDCBarcodeSelectionTapSelection`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection): Allows the user to select barcodes by tapping on them. Requires the MatrixScan add-on. - [`SDCBarcodeSelectionAimerSelection`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-aimer-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAimerSelection): Allows the user to select barcodes by aiming at them. #### `SDCBarcodeSelectionTapSelection` You can select to automatically freeze the camera preview to make the selection easier via [`SDCBarcodeSelectionTapSelection.freezeBehavior`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.FreezeBehavior). Using [`SDCBarcodeSelectionTapSelection.tapBehavior`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.TapBehavior) you can further decide if a second tap on a barcode means that the barcode is unselected or if it is selected another time (increasing the counter). #### `SDCBarcodeSelectionAimerSelection` With this selection mode it is possible to choose between two different [selection strategies](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-strategy.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionStrategy): - [`SDCBarcodeSelectionAutoSelectionStrategy`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAutoSelectionStrategy): Barcodes are selected automatically when aiming at them. - [`SDCBarcodeSelectionManualSelectionStrategy`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionManualSelectionStrategy): Barcodes are selected when aiming at them and tapping anywhere on the screen. ### Single Barcode Selection If you want to automatically select a barcode when it is the only one on screen, turn on [`SDCBarcodeSelectionSettings.singleBarcodeAutoDetection`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-settings.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionSettings.SingleBarcodeAutoDetection): ```swift settings.singleBarcodeAutoDetection = true ``` ## Registering the Listener To get informed whenever a new code has been recognized, add a [`SDCBarcodeSelectionListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener), implementing the listener methods to suit your application’s needs. First conform to the `SDCBarcodeSelectionListener` protocol. For example: ```swift extension ScanViewController: BarcodeSelectionListener { func barcodeSelection(_ barcodeSelection: BarcodeSelection, didUpdateSelection session: BarcodeSelectionSession, frameData: FrameData?) { let newlySelectedBarcodes = session.newlySelectedBarcodes // Do something with the newly selected barcodes. } } ``` Then register the listener to the `SDCBarcodeSelection` instance: ```swift barcodeSelection.addListener(self) ``` ## Obtaining the Camera Instance and Set as Frame Source The data capture context supports using different frame sources to perform recognition, here we assume that you will use the built-in camera of the device. :::note In iOS, the user must explicitly grant permission for each app to access the camera. Your app needs to provide static messages to display when the system asks for camera permission. To do that include the [`NSCameraUsageDescription`](https://developer.apple.com/documentation/bundleresources/information_property_list/nscamerausagedescription) key in your app’s `Info.plist` file. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode: ```swift let cameraSettings = BarcodeSelection.recommendedCameraSettings // Depending on the use case further camera settings adjustments can be made here. let camera = Camera.default camera?.apply(cameraSettings) ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [`SDCDataCaptureContext.setFrameSource:completionHandler:`](https://docs.scandit.com/data-capture-sdk/ios/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```swift context.setFrameSource(camera) ``` The camera is off by default and must be turned on. This is done by calling: ```swift camera?.switch(toDesiredState: .on) ``` ## Disabling Barcode Selection To disable barcode selection, for instance when the selection is complete, set [`SDCBarcodeSelection.enabled`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelection.IsEnabled) to `NO`. The effect is immediate, no more frames will be processed after the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off: ```swift camera?.switch(toDesiredState: .off) ``` --- ## About Barcode Selection # About Barcode Selection :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/ios/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: Barcode Selection enables you to increase scanning accuracy and prevent users from scanning the wrong code in scenario where there are multiple barcodes present. This includes the following: - A crowded shelf where users want to scan the correct barcode to report stockouts or perform a cycle count. - An order catalog with barcodes printed closely together. - A label that has several types of barcodes; however users are only interested in scanning barcodes that have the same type, but cannot select them programmatically. Barcode Selection provides two key capabilities: - **Aim to Select** allows users to select one code at a time. This is especially useful for one-handed operation. - **Tap to Select** is a quick way for users to select several codes from the same view. Selection is done by tapping on highlighted barcodes in the live camera preview or on a frozen screen. Tapping on codes while keeping the smartphone steady can be tricky, and freezing the screen allows for ergonomic use. :::warning Barcode Selection does not support handling of duplicate codes. If a code appears twice in the visible preview both instances will be marked as selected even if only one of them was selected. ::: --- ## Advanced Configurations # Advanced Configurations There are several advanced configurations that can be used to customize the behavior of the ID Capture SDK and enable additional features. ## Decode EU Driver Licenses By default, ID Capture doesn’t extract data from the table on the back of European Driver Licenses. If you are interested in this data, you may enable the extraction by calling: ```swift settings.decodeBackOfEuropeanDrivingLicense = true ``` ```objectivec settings.decodeBackOfEuropeanDrivingLicense = YES; ``` :::warning To use this feature, you will need to include the `ScanditIdEuropeDrivingLicense` module in your project. See the [module overview](/sdks/ios/id-capture/get-started.md#module-overview) for details. ::: ## Configure Data Anonymization By default, data extracted from documents is anonymized according to local regulations. See [Anonymized Documents](/sdks/ios/id-capture/supported-documents.md#anonymized-documents) for more information. That means certain data from certain fields won’t be returned, even if it’s present on a document. You control the anonymization level with the following setting: ```swift // Default value: settings.anonymizationMode = .fieldsOnly // Sensitive data is additionally covered with black boxes on returned images: settings.anonymizationMode = .fieldsAndImages // Only images are anonymized: settings.anonymizationMode = .imagesOnly // No anonymization: settings.anonymizationMode = .none ``` ```objectivec // Default value: settings.anonymizationMode = SDCIdAnonymizationModeFieldsOnly; // Sensitive data is additionally covered with black boxes on returned images: settings.anonymizationMode = SDCIdAnonymizationModeFieldsAndImages; // Only images are anonymized: settings.anonymizationMode = SDCIdAnonymizationModeImagesOnly; // No anonymization: settings.anonymizationMode = SDCIdAnonymizationModeNone; ``` ## ID Images Your use can may require that you capture and extract images of the ID document. Use the [IdImageType](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/id-image-type.html#enum-scandit.datacapture.id.IdImageType) enum to specify the images you want to extract from the `CapturedId` object. :::tip Face and Cropped Document can be extracted only by either `SingleSideScanner` with `visualInspectionZone` enabled or by `FullDocumentScanner`. In the case of `FullDocumentScanner`, if the front & the back side of a document are scanned, Cropped Document and Full Frame are returned for both sides. ::: For the full frame of the document, you can use [`setShouldPassImageTypeToResult`](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/id-capture-settings.html#method-scandit.datacapture.id.IdCaptureSettings.SetShouldPassImageTypeToResult) when creating the `IdCaptureSettings` object. This will pass the image type to the result, which you can then access in the `CapturedId` object. ```swift // Holder's picture as printed on a document: settings.resultShouldContainImage(true, for: .face) // Cropped image of a document: settings.resultShouldContainImage(true, for: .croppedDocument) // Full camera frame that contains the document: settings.resultShouldContainImage(true, for: .frame) ``` ```objectivec // Holder's picture as printed on a document: [settings resultShouldContainImage:YES forImageType:SDCIdImageTypeFace]; // Cropped image of a document: [settings resultShouldContainImage:YES forImageType:SDCIdImageTypeCroppedDocument]; // Full camera frame that contains the document: [settings resultShouldContainImage:YES forImageType:SDCIdImageTypeFrame]; ``` ## Callbacks and Scanning Workflows The ID Capture Listener provides two callbacks: `onIdCaptured` and `onIdRejected`. The `onIdCaptured` callback is called when an acceptable document is successfully captured, while the `onIdRejected` callback is called when a document is captured but rejected. For a successful capture, the `onIdCaptured` callback provides a `SDCCapturedId` object that contains the extracted information from the document. This object is specific to the type of document scanned. For example, a `SDCCapturedId` object for a US Driver License will contain different fields than a `SDCCapturedId` object for a Passport. For a rejected document, a [SDCRejectionReason](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) is provided in the `onIdRejected` callback to help you understand why the document was rejected and to take appropriate action. These are: * NOT_ACCEPTED_DOCUMENT_TYPE: The document is not in the list of accepted documents. In this scenario, you could direct the user to scan a different document. * INVALID_FORMAT: The document is in the list of accepted documents, but the format is invalid. In this scenario, you could direct the user to scan the document again. * DOCUMENT_VOIDED: The document is in the list of accepted documents, but the document is voided. In this scenario, you could direct the user to scan a different document. * TIMEOUT: The document was not scanned within the specified time. In this scenario, you could direct the user to scan the document again. ## Detect Fake IDs *ID Validate* is a fake ID detection software. It currently supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). Fake ID detection can be performed automatically using the following settings: * [IdCaptureSettings.rejectForgedAamvaBarcodes](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectForgedAamvaBarcodes): Automatically rejects documents whose AAMVA barcode fails authenticity validation. * [IdCaptureSettings.rejectInconsistentData](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectInconsistentData): Automatically rejects documents whose human‑readable data does not match the data encoded in the barcode or MRZ. To enable ID validation for your subscription, please reach out to [Scandit Support](mailto:support@scandit.com). --- ## Get Started # Get Started This page will guide you through the process of adding ID Capture to your iOS application. ID Capture is a mode of the Scandit Data Capture SDK that allows you to capture and extract information from personal identification documents, such as driver's licenses, passports, and ID cards. The general steps are: - Creating a new Data Capture Context instance - Accessing a Camera - Configuring the Capture Settings - Implementing a Listener to Receive Scan Results - Setting up the Capture View and Overlay - Starting the Capture Process :::warning Using ID Capture at the same time as other modes (e.g. Barcode Capture) is not supported. ::: ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. See the [installation guide](/sdks/ios/add-sdk.md) for details. :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import IdModuleOverview from '../../../partials/get-started/_id-module-overview-ios.mdx'; ### Mobile ID Scanning ID Capture supports Bluetooth to scan mobile identity documents. The App Store requires the `NSBluetoothAlwaysUsageDescription` key to be present in your app's `Info.plist` when this module is included, even if you are not actively using this feature. To resolve this issue, add the following entry to your `Info.plist` file: ```xml NSBluetoothAlwaysUsageDescription Required to scan mobile identity documents via Bluetooth. ``` ## Create a Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Access a Camera Next, you need to create a new instance of the [`SDCCamera`](https://docs.scandit.com/data-capture-sdk/ios/core/api/camera.html#class-scandit.datacapture.core.Camera) class to indicate the camera that will be used to stream previews and to capture images. The camera settings are also configured, in this case, we use the `recommendedCameraSettings` that come withe ID Capture SDK. ```swift camera = Camera.default context.setFrameSource(camera, completionHandler: nil) // Use the recommended camera settings for the IdCapture mode. let recommendedCameraSettings = IdCapture.recommendedCameraSettings camera?.apply(recommendedCameraSettings) ``` ```objectivec SDCCamera *camera = [SDCCamera defaultCamera]; [dataCaptureContext setFrameSource:camera completionHandler:nil]; auto recommendedCameraSettings = [SDCIdCapture recommendedCameraSettings]; [camera applySettings:recommendedCameraSettings completionHandler:nil]; ``` ## Configure the Capture Settings Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scanner type to use and the documents that should be accepted and/or rejected. Check [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) for all the available options. :::tip By default, [anonymized data](./advanced.md#configure-data-anonymization) is not returned in accordance with local regulations for specific documents. This setting can be disabled for testing purposes, but be sure to comply with local laws and requirements in production. ::: ```swift var acceptedDocuments = [IdCaptureDocument]() var rejectedDocuments = [IdCaptureDocument]() // Passports from any region: acceptedDocuments.append(Passport(region: .any)) // Only documents issued by a specific country: acceptedDocuments.append(IdCard(region: .germany)) // Standardized documents issued in Europe: acceptedDocuments.append(IdCard(region: .euAndSchengen)) acceptedDocuments.append(DriverLicense(region: .euAndSchengen)) // Regional documents: acceptedDocuments.append(RegionSpecific(subtype: .apecBusinessTravelCard)) acceptedDocuments.append(RegionSpecific(subtype: .chinaExitEntryPermit)) // Reject passports from certain regions: rejectedDocuments.append(Passport(region: .cuba)) // Configure: let settings = IdCaptureSettings() settings.acceptedDocuments = acceptedDocuments settings.rejectedDocuments = rejectedDocuments // Capture only one-side documents and a given zone // Capture only barcodes settings.scannerType = SingleSideScanner(enablingBarcode: true, machineReadableZone: false, visualInspectionZone: false) // Capture only Machine Readable Zone (MRZ) settings.scannerType = SingleSideScanner(enablingBarcode: false, machineReadableZone: true, visualInspectionZone: false) // Capture only Visual Inspection Zone (VIZ) settings.scannerType = SingleSideScanner(enablingBarcode: false, machineReadableZone: false, visualInspectionZone: true) // Full document scanner settings.scannerType = FullDocumentScanner() ``` ```objectivec NSMutableArray *acceptedDocuments = [NSMutableArray new]; NSMutableArray *rejectedDocuments = [NSMutableArray new]; // Passports from any region: [acceptedDocuments addObject:[SDCPassport documentWithRegion:SDCIdCaptureRegionAny]]; // Only documents issued by a specific country: [acceptedDocuments addObject:[SDCIdCard documentWithRegion:SDCIdCaptureRegionGermany]]; // Standardized documents issued in Europe: [acceptedDocuments addObject:[SDCIdCard documentWithRegion:SDCIdCaptureRegionEUAndSchengen]]; [acceptedDocuments addObject:[SDCDriverLicense documentWithRegion:SDCIdCaptureRegionEUAndSchengen]]; // Regional documents: [acceptedDocuments addObject:[SDCRegionSpecific documentWithSubtype:SDCIdCaptureRegionSpecificSubtypeApecBusinessTravelCard]]; [acceptedDocuments addObject:[SDCRegionSpecific documentWithSubtype:SDCIdCaptureRegionSpecificSubtypeChinaExitEntryPermit]]; // Reject passports from certain regions: [rejectedDocuments addObject:[SDCPassport documentWithRegion:SDCIdCaptureRegionCuba]]; // Configure: SDCIdCaptureSettings *settings = [SDCIdCaptureSettings new]; settings.acceptedDocuments = acceptedDocuments; settings.rejectedDocuments = rejectedDocuments; // Capture only one-side documents and a given zone // Capture only barcodes settings.scannerType = [SDCSingleSideScanner scannerEnablingBarcode:YES machineReadableZone:NO visualInspectionZone:NO]; // Capture only Machine Readable Zone (MRZ) settings.scannerType = [SDCSingleSideScanner scannerEnablingBarcode:NO machineReadableZone:YES visualInspectionZone:NO]; // Capture only Visual Inspection Zone (VIZ) settings.scannerType = [SDCSingleSideScanner scannerEnablingBarcode:NO machineReadableZone:NO visualInspectionZone:YES]; // Full document scanner settings.scannerType = [SDCFullDocumentScanner scanner]; ``` Create a new ID Capture mode with the chosen settings: ```swift idCapture = IdCapture(context: context, settings: idCaptureSettings) ``` ```objectivec SDCIdCapture *idCapture = [SDCIdCapture idCaptureWithContext:dataCaptureContext settings:idCaptureSettings]; ``` ## Implement a Listener To receive scan results, implement and [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener). The listener provides two callbacks: `didCapture` and `didReject` ```swift extension IdCaptureViewController: IdCaptureListener { func idCapture(_ idCapture: IdCapture, didCapture capturedId: CapturedId) { // Success! Handle extracted data here. } func idCapture(_ idCapture: IdCapture, didReject capturedId: CapturedId?, reason: RejectionReason) { // Something went wrong. Inspect the reason to determine the follow-up action. } } idCapture.addListener(self) ``` ```objectivec - (void)idCapture:(SDCIdCapture *)idCapture didCapture:(SDCCapturedId *)capturedId { // Success! Handle extracted data here. } - (void)idCapture:(SDCIdCapture *)idCapture didReject:(nullable SDCCapturedId *)capturedId reason:(SDCRejectionReason)rejectionReason { // Something went wrong. Inspect the reason to determine the follow-up action. } [idCapture addListener:self]; ``` ### Handling Success Capture results are delivered as a [CapturedId](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/captured-id.html#class-scandit.datacapture.id.CapturedId). This class contains data common for all kinds of personal identification documents. For more specific information, use its non-null result properties (e.g. [CapturedId.barcode](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/captured-id.html#property-scandit.datacapture.id.CapturedId.Barcode)). On a successful scan you may read the extracted data from `CapturedId`: ```swift func idCapture(_ idCapture: IdCapture, didCapture capturedId: CapturedId) { let fullName = capturedId.fullName let dateOfBirth = capturedId.dateOfBirth let dateOfExpiry = capturedId.dateOfExpiry let documentNumber = capturedId.documentNumber // Process data: processData(fullName, dateOfBirth, dateOfExpiry, documentNumber) } ``` ```objectivec - (void)idCapture:(SDCIdCapture *)idCapture didCapture:(SDCCapturedId *)capturedId { NSString *fullName = capturedId.fullName; NSDate *dateOfBirth = capturedId.dateOfBirth; NSDate *dateOfExpiry = capturedId.dateOfExpiry; NSString *documentNumber = capturedId.documentNumber; // Process data: [self processData:fullName dateOfBirth:dateOfBirth dateOfExpiry:dateOfExpiry documentNumber:documentNumber]; } ``` :::tip All data fields are optional, so it's important to verify whether the required information is present if some of the accepted documents may not contain certain data. ::: ### Handling Rejection The ID scanning process may fail for various reasons. Start by inspecting [`RejectionReason`](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) to understand the cause. You may wish to implement the follow-up action based on the reason of failure: ```swift func idCapture(_ idCapture: IdCapture, didReject capturedId: CapturedId?, reason: RejectionReason) { if reason == .timeout { // Ask the user to retry, or offer alternative input method. } else if reason == .notAcceptedDocumentType { // Ask the user to provide alternative document. } else { // Handle other rejection reasons, if necessary. } } ``` ```objectivec - (void)idCapture:(SDCIdCapture *)idCapture didReject:(nullable SDCCapturedId *)capturedId reason:(SDCRejectionReason)rejectionReason { if (rejectionReason == SDCRejectionReasonTimeout) { // Ask the user to retry, or offer alternative input method. } else if (rejectionReason == SDCRejectionReasonNotAcceptedDocumentType) { // Ask the user to provide alternative document. } else { // Handle other rejection reasons, if necessary. } } ``` ## Set up Capture View and Overlay When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [`SDCDataCaptureView`](https://docs.scandit.com/data-capture-sdk/ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```swift let dataCaptureView = DataCaptureView(context: dataCaptureContext, frame: .zero) view.addSubview(dataCaptureView) dataCaptureView.translatesAutoresizingMaskIntoConstraints = false view.addConstraints([ dataCaptureView.leadingAnchor.constraint(equalTo: view.leadingAnchor), dataCaptureView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), dataCaptureView.trailingAnchor.constraint(equalTo: view.trailingAnchor), dataCaptureView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) ]) ``` ```objectivec SDCDataCaptureView *dataCaptureView = [SDCDataCaptureView dataCaptureViewForContext:dataCaptureContext frame:CGRectZero]; dataCaptureView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:dataCaptureView]; [self.view addConstraint:[dataCaptureView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor]]; [self.view addConstraint:[dataCaptureView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor]]; [self.view addConstraint:[dataCaptureView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor]]; [self.view addConstraint:[dataCaptureView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor]]; ``` Then, add a [`SDCIdCaptureOverlay`](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) to the view: ```swift let overlay = IdCaptureOverlay(idCapture: idCapture, view: captureView) ``` ```objectivec SDCIdCaptureOverlay *overlay = [SDCIdCaptureOverlay overlayWithIdCapture:idCapture view:dataCaptureView]; ``` The overlay chooses the displayed UI automatically, based on the selected `SDCIdCaptureSettings`. ## Start the Capture Process Finally, turn on the camera to start scanning: ```swift camera?.switch(toDesiredState: .on) ``` ```objectivec [camera switchToDesiredState:SDCFrameSourceStateOn]; ``` --- ## About ID Capture import AboutIdCapture from '../../../partials/intro/_about-id-capture.mdx'; --- ## Supported Documents ## ID Scanning Supported Documents Scandit ID Capture provides various [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/ios/id-capture/api/id-capture-scanner.html#id-capture-scanner) types, each designed for specific scanning workflows. These workflows can involve scanning either specific parts of a document or the entire document, including both the front and back sides. This section details the types of documents supported by each scanner type. import IdDocumentsFull from '../../../partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from '../../../partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents import IdValidateDocuments from '../../../partials/advanced/_id-documents-validate.mdx'; --- ## Advanced Configurations import ValidationFlowHowItWorks from '../../../partials/advanced/_validation-flow-how-it-works.mdx'; import ValidationFlowCustomButtons from '../../../partials/advanced/_validation-flow-custom-buttons.mdx'; import ValidationFlowTypingHints from '../../../partials/advanced/_validation-flow-typing-hints.mdx'; import ValidationFlowCloudVLM from '../../../partials/advanced/_validation-flow-cloud-vlm.mdx'; import ReceiptScanning from '../../../partials/advanced/_receipt-scanning.mdx'; import ValidationFlowRequiredOptional from '../../../partials/advanced/_validation-flow-required-optional.mdx'; import ValidationFlowCustomToasts from '../../../partials/advanced/_validation-flow-custom-toasts.mdx'; import ValidationFlowCustomField from '../../../partials/advanced/_validation-flow-custom-field.mdx'; # Advanced Configurations ## Customize the Overlay Appearance To customize the appearance of the overlay, you can implement a [LabelCaptureBasicOverlayDelegate](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/ui/label-capture-basic-overlay-listener.html#label-capture-basic-overlay-delegate). The method [brushForLabel](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForLabel) is called every time a label is captured, and [brushForField](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForField) is called for each of its fields to determine the brush for the label or field. ```swift import ScanditLabelCapture extension YourScanViewController: LabelCaptureBasicOverlayDelegate { func labelCaptureBasicOverlay(_ overlay: LabelCaptureBasicOverlay, brushFor field: LabelField, of label: CapturedLabel) -> Brush? { return brush(for: field) } func labelCaptureBasicOverlay(_ overlay: LabelCaptureBasicOverlay, brushFor label: CapturedLabel) -> Brush? { /* * Customize the appearance of the overlay for the full label. * In this example, we always disable label overlays by returning nil. */ return nil } func labelCaptureBasicOverlay(_ overlay: LabelCaptureBasicOverlay, didTap label: CapturedLabel) { /* * Handle user tap gestures on the label. */ } private func brush(for field: LabelField) -> Brush { let fillColor: UIColor let strokeColor: UIColor switch field.name { case "": fillColor = .systemCyan.withAlphaComponent(0.5) strokeColor = .systemCyan case "": fillColor = .systemOrange.withAlphaComponent(0.5) strokeColor = .systemOrange default: fillColor = .clear strokeColor = .clear } return Brush(fill: fillColor, stroke: strokeColor, strokeWidth: 1) } } ``` ## Advanced Overlay For more advanced use cases, such as adding custom views or implementing Augmented Reality (AR) features, you can use the `LabelCaptureAdvancedOverlay`. The example below creates an advanced overlay, configuring it to display a styled warning message below expiry date fields when they're close to expiring, while ignoring other fields. ```swift import ScanditLabelCapture // Create an advanced overlay that allows for custom views to be added over detected label fields // This is the key component for implementing Augmented Reality features let advancedOverlay = LabelCaptureAdvancedOverlay(labelCapture: labelCapture, view: dataCaptureView) // Configure the advanced overlay with a delegate that handles AR content creation and positioning advancedOverlay.delegate = self extension YourScanViewController: LabelCaptureAdvancedOverlayDelegate { // This method is called when a label is detected - we return nil since we're only adding AR elements to specific fields, not the entire label func labelCaptureAdvancedOverlay(_ overlay: LabelCaptureAdvancedOverlay, viewFor capturedLabel: CapturedLabel) -> UIView? { return nil } // This defines where on the detected label the AR view would be anchored func labelCaptureAdvancedOverlay(_ overlay: LabelCaptureAdvancedOverlay, anchorFor capturedLabel: CapturedLabel) -> Anchor { return .center } // This defines the offset from the anchor point for the label's AR view func labelCaptureAdvancedOverlay(_ overlay: LabelCaptureAdvancedOverlay, offsetFor capturedLabel: CapturedLabel) -> PointWithUnit { return PointWithUnit(x: .zero, y: .zero) } // This method is called when a field is detected in a label func labelCaptureAdvancedOverlay(_ overlay: LabelCaptureAdvancedOverlay, viewFor labelField: LabelField) -> UIView? { // We only want to create AR elements for expiry date fields that are text-based if labelField.name.lowercased().contains("expiry") && labelField.type == .text { // Check if scanned expiry date is too close to actual date let daysUntilExpiry = daysUntilExpiry(from: labelField.text) // Your method let dayLimit = 3 if daysUntilExpiry Anchor { return .bottomCenter } // This defines the offset from the anchor point func labelCaptureAdvancedOverlay(_ overlay: LabelCaptureAdvancedOverlay, offsetFor capturedField: LabelField, of capturedLabel: CapturedLabel) -> PointWithUnit { return PointWithUnit(x: .zero, y: .zero) } } ``` ## Validation Flow ```swift // Create the overlay let validationFlowOverlay = LabelCaptureValidationFlowOverlay( labelCapture: labelCapture, dataCaptureView: dataCaptureView ) // Set the delegate to receive validation events validationFlowOverlay.delegate = self ``` ### Define a Listener When the user has verified that all fields are correctly captured and presses the finish button, the Validation Flow triggers a callback with the final results. To receive these results, implement the `LabelCaptureValidationFlowOverlayDelegate` protocol: ```swift extension YourScanViewController: LabelCaptureValidationFlowDelegate { // This is called by the validation flow overlay when a label has been fully captured and validated func labelCaptureValidationFlowOverlay(_ overlay: LabelCaptureValidationFlowOverlay, didCaptureLabelWith fields: [LabelField]) { let barcodeData = fields.first { $0.name == "" }?.barcode?.data let expiryDate = fields.first { $0.name == "" }?.text // Handle the captured values } } ``` ```swift let validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.init() validationFlowOverlaySettings.setPlaceholderText("MM/DD/YYYY", forLabelDefinition: "Expiry Date") validationFlowOverlay.apply(validationFlowOverlaySettings) ``` ```swift let validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.init() validationFlowOverlaySettings.restartButtonText = "Borrar todo" validationFlowOverlaySettings.pauseButtonText = "Pausar" validationFlowOverlaySettings.finishButtonText = "Finalizar" validationFlowOverlay.apply(validationFlowOverlaySettings) ``` ```swift let validationFlowOverlaySettings = LabelCaptureValidationFlowSettings() validationFlowOverlaySettings.standbyHintText = "No label detected, camera paused" validationFlowOverlaySettings.validationHintText = "data fields collected" // X/Y (X fields out of total Y) is shown in front of this string validationFlowOverlay.applySettings(validationFlowOverlaySettings) ``` ```swift let validationFlowOverlaySettings = LabelCaptureValidationFlowSettings() validationFlowOverlaySettings.validationErrorText = "Incorrect format." validationFlowOverlaySettings.scanningText = "Scan in progress" validationFlowOverlaySettings.adaptiveScanningText = "Processing" validationFlowOverlay.applySettings(validationFlowOverlaySettings) ``` ```swift let labelCaptureSettings = try LabelCaptureSettings { LabelDefinition("Retail Item") { CustomBarcode( name: "Barcode", symbologies: [.ean13UPCA, .gs1DatabarExpanded, .code128] ) ExpiryDateText(name: "Expiry Date") .labelDateFormat( LabelDateFormat( componentFormat: LabelDateComponentFormat.MDY, acceptPartialDates: false ) ) } .adaptiveRecognition(.auto) } ``` See [AdaptiveRecognitionMode](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/label-definition.html#property-scandit.datacapture.label.LabelDefinition.AdaptiveRecognitionMode) for available options. --- ## Get Started With SwiftUI # Get Started With SwiftUI In this guide you will learn step-by-step how to add Smart Label Capture to your application using SwiftUI. The general steps are: 1. **Create a UIViewController**: Implement the Smart Label Capture logic following the main [Get Started guide](./get-started.md) 2. **Create a SwiftUI wrapper**: Use `UIViewControllerRepresentable` to integrate the `UIViewController` 3. **Use in your SwiftUI app**: Add the SwiftUI view to your app's view hierarchy The core Smart Label Capture implementation (data capture context, settings, camera setup, etc.) remains the same as described in the main guide. ## Create a UIViewController for Smart Label Capture To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a `UIViewController` that handles the Smart Label Capture functionality. This follows the same implementation as described in the main [Get Started guide](./get-started.md). Create a `LabelCaptureViewController` class that implements all the steps from the UIKit guide: ```swift import ScanditLabelCapture import UIKit class LabelCaptureViewController: UIViewController { private var context: DataCaptureContext! private var camera: Camera? private var labelCapture: LabelCapture! private var dataCaptureView: DataCaptureView! private var labelCaptureOverlay: LabelCaptureBasicOverlay! override func viewDidLoad() { super.viewDidLoad() setupRecognition() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) labelCapture.isEnabled = true camera?.switch(toDesiredState: .on) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) labelCapture.isEnabled = false camera?.switch(toDesiredState: .off) } func setupRecognition() { // Follow the implementation from the Get Started guide: // 1. Initialize the Data Capture context // 2. Initialize the Label Capture mode with label definitions // 3. Add listener to handle captured labels // 4. Visualize the scan process with DataCaptureView and overlays // 5. Configure and start the camera } } extension LabelCaptureViewController: LabelCaptureListener { func labelCapture(_ labelCapture: LabelCapture, didUpdate session: LabelCaptureSession, frameData: FrameData) { // Handle label capture results // See the main Get Started guide } } ``` ## Create a SwiftUI View using UIViewControllerRepresentable Now create a SwiftUI wrapper that integrates the UIViewController into your SwiftUI app: ```swift import SwiftUI import UIKit struct LabelCaptureRepresentable: UIViewControllerRepresentable { typealias UIViewControllerType = LabelCaptureViewController func makeUIViewController(context: Context) -> LabelCaptureViewController { return LabelCaptureViewController() } func updateUIViewController(_ uiViewController: LabelCaptureViewController, context: Context) { // Update the view controller if needed } } ``` ## Use the SwiftUI View in Your App Finally, use the `LabelCaptureRepresentable` in your SwiftUI app: ```swift import SwiftUI @main struct MyApp: App { var body: some Scene { WindowGroup { LabelCaptureRepresentable() } } } ``` Or within another SwiftUI view: ```swift struct ContentView: View { var body: some View { NavigationView { LabelCaptureRepresentable() .navigationTitle("Smart Label Capture") } } } ``` ## Alternative: Using UIViewRepresentable As an alternative to wrapping a `UIViewController`, you can implement the Smart Label Capture functionality directly using `UIViewRepresentable`. This approach uses a `Coordinator` to hold the SDK objects, ensuring they are created once and persist across SwiftUI updates: ```swift import ScanditLabelCapture import SwiftUI struct LabelCaptureView: UIViewRepresentable { let labelDefinitions: [LabelDefinition] let onLabelCaptured: ([CapturedLabel]) -> Void func makeCoordinator() -> Coordinator { Coordinator(labelDefinitions: labelDefinitions, onLabelCaptured: onLabelCaptured) } func makeUIView(context: Context) -> UIView { let coordinator = context.coordinator if let camera = Camera.default { // Apply recommended camera settings let cameraSettings = LabelCapture.recommendedCameraSettings camera.apply(cameraSettings) // Set the camera as the frame source coordinator.dataCaptureContext.setFrameSource(camera) camera.switch(toDesiredState: .on) coordinator.camera = camera } // Enable Label Capture coordinator.labelCapture.isEnabled = true // Create the capture view let captureView = DataCaptureView(context: coordinator.dataCaptureContext, frame: .zero) captureView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // Create the overlay (automatically added to the capture view) coordinator.overlay = LabelCaptureBasicOverlay(labelCapture: coordinator.labelCapture, view: captureView) return captureView } func updateUIView(_ uiView: UIView, context: Context) { context.coordinator.onLabelCaptured = onLabelCaptured } static func dismantleUIView(_ uiView: UIView, coordinator: Coordinator) { coordinator.labelCapture.isEnabled = false coordinator.camera?.switch(toDesiredState: .off) } class Coordinator: NSObject, LabelCaptureListener { let dataCaptureContext: DataCaptureContext let labelCapture: LabelCapture var overlay: LabelCaptureBasicOverlay? var camera: Camera? var onLabelCaptured: ([CapturedLabel]) -> Void init(labelDefinitions: [LabelDefinition], onLabelCaptured: @escaping ([CapturedLabel]) -> Void) { // Create the data capture context DataCaptureContext.initialize(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") dataCaptureContext = DataCaptureContext.shared self.onLabelCaptured = onLabelCaptured // Configure Label Capture settings guard let settings = try? LabelCaptureSettings(labelDefinitions: labelDefinitions) else { fatalError("Invalid label definitions") } // Create Label Capture mode labelCapture = LabelCapture(context: dataCaptureContext, settings: settings) super.init() labelCapture.addListener(self) } nonisolated func labelCapture(_ labelCapture: LabelCapture, didUpdate session: LabelCaptureSession, frameData: FrameData) { let capturedLabels = session.capturedLabels guard !capturedLabels.isEmpty else { return } DispatchQueue.main.async { self.onLabelCaptured(capturedLabels) } } } } ``` You can then use this view directly in your SwiftUI app: ```swift struct ContentView: View { private let labelDefinitions: [LabelDefinition] = [ LabelDefinition("Retail Item") { CustomBarcode(name: "Barcode", symbology: .ean13UPCA) ExpiryDateText(name: "Expiry Date") } ] var body: some View { NavigationView { LabelCaptureView( labelDefinitions: labelDefinitions, onLabelCaptured: { labels in // Handle captured labels } ) .navigationTitle("Smart Label Capture") } } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Smart Label Capture to your application. The general steps are: - Create a view controller - Initialize the Data Capture context - Initialize the Label Capture mode - Implement a listener to handle captured labels - Visualize the scan process - Start the camera - Provide feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you have added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import LabelCaptureModuleOverview from '../../../partials/get-started/_smart-label-capture-module-overview.mdx'; ## Create a view controller ```swift import ScanditLabelCapture class YourScanViewController: UIViewController { private var context: DataCaptureContext! private var labelCapture: LabelCapture! private var dataCaptureView: DataCaptureView! private var labelCaptureOverlay: LabelCaptureBasicOverlay! private var camera: Camera? override func viewDidLoad() { super.viewDidLoad() /* Initialize the components as lined out in the following sections */ } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) /* Start the camera */ } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) /* Stop the camera, disable capture mode */ } // ... } ``` ## Initialize the Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Initialize the Label Capture Mode The main entry point for the Label Capture Mode is the [LabelCapture](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/label-capture.html#class-scandit.datacapture.label.LabelCapture) object. It is configured through [LabelCaptureSettings](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/label-capture-settings.html#class-scandit.datacapture.label.LabelCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) that get informed whenever a new frame has been processed. ```swift let labelCaptureSettings = try LabelCaptureSettings { LabelDefinition("") { /* * Add a barcode field with the expected symbologies and pattern. * You can omit the valueRegexes if the content of the barcode is unknown. */ CustomBarcode( name: "", symbologies: [.ean13UPCA, .code128] ) .valueRegexes(["\\d{12,14}"]) /* * Add a text field for capturing expiry dates. * The field is set as mandatory by default. */ ExpiryDateText(name: "") } } /* * Create the label capture mode with the settings * and data capture context created earlier */ labelCapture = LabelCapture(context: context, settings: labelCaptureSettings) /* * Add a listener to the label capture mode, see the following section * for more information on implementing the listener */ labelCapture.addListener(self) ``` ## Implement a Listener to Handle Captured Labels To get informed whenever a new label has been recognized, add a [LabelCaptureListener](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) through [LabelCapture.addListener()](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/label-capture.html#method-scandit.datacapture.label.LabelCapture.AddListener) and implement the listener methods to suit your application’s needs. First conform to the `LabelCaptureListener` interface. Here is an example of how to implement a listener that processes the captured labels based on the label capture settings defined above: ```swift extension YourScanViewController: LabelCaptureListener { func labelCapture( _ labelCapture: LabelCapture, didUpdate session: LabelCaptureSession, frameData: FrameData ) { /* * The did update callback is called for every processed frame. * Check if the session contains any captured labels; * if not, continue capturing. */ guard let label = session.capturedLabels.first else { return } /* * Given the label capture settings defined above, barcode data will always be present. */ guard let barcodeField = label.fields.first(where: { $0.name == ""}), let barcodeData = barcodeField.barcode?.data else { return } /* * The expiry date field is optional. * Check for nil in your result handling. */ let expiryDate = label.fields.first(where: { $0.name == ""})?.text /* * Emit feedback to notify the user that a label has been captured. */ Feedback.default.emit() DispatchQueue.main.async { self.camera?.switch(toDesiredState: .off) labelCapture.isEnabled = false /* * Handle the captured barcode and expiry date here. */ } } } ``` ## Visualize the Scan Process The capture process can be visualized by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy. The view controls the UI elements, such as the viewfinder and overlays, that are shown to visualize captured labels. To visualize the results of Label Capture, you can choose between two overlays, [LabelCaptureBasicOverlay](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/ui/label-capture-basic-overlay.html#label-capture-basic-overlay) and [LabelCaptureAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/ui/label-capture-advanced-overlay.html#label-capture-advanced-overlay). Here is an example of how to add a `LabelCaptureBasicOverlay` to the `DataCaptureView`: ```swift /* * Create the data capture view and attach it to the data capture context created earlier. */ dataCaptureView = DataCaptureView(context: dataCaptureContext, frame: .zero) /* * Add the data capture view to your view hierarchy, e.g. with insertSubview. */ containerView.insertSubview(dataCaptureView, at: 0) /* * Create the overlay with the label capture mode and data capture view created earlier. */ labelCaptureOverlay = LabelCaptureBasicOverlay(labelCapture: labelCapture, view: dataCaptureView) labelCaptureOverlay.viewfinder = RectangularViewfinder(style: .square) ``` :::tip See the [Advanced Configurations](advanced.md) section for more information about how to customize the appearance of the overlays and how to use the advanced overlay to display arbitrary iOS views such as text views, icons or images. ::: ## Start the Camera Next, you need to create a new instance of the [`SDCCamera`](https://docs.scandit.com/data-capture-sdk/ios/core/api/camera.html#class-scandit.datacapture.core.Camera) class to indicate the camera that will be used to stream previews and capture images. You can initialize the camera with the recommended settings for Label Capture: ```swift camera = Camera.default context.setFrameSource(camera, completionHandler: nil) let recommendedCameraSettings = LabelCapture.recommendedCameraSettings camera?.apply(recommendedCameraSettings) ``` Once the Camera, DataCaptureContext, DataCaptureView and LabelCapture are initialized, you can switch on the camera to start capturing labels. This can be done in the `viewWillAppear` method of your view controller, or once a user presses continue scanning after handling a previous scan. ```swift camera?.switch(toDesiredState: .on) ``` ## Provide Feedback Smart Label Capture provides customizable feedback, emitted automatically when a label is recognized and successfully processed, configurable via [`LabelCapture.feedback`](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/label-capture.html#property-scandit.datacapture.label.LabelCapture.Feedback). You can use the default feedback, or configure your own sound or vibration. :::tip If you already have a [Feedback](https://docs.scandit.com/data-capture-sdk/ios/core/api/feedback.html#class-scandit.datacapture.core.Feedback) instance implemented in your application, remove it to avoid double feedback. ::: ```swift labelCapture.feedback = LabelCaptureFeedback.default ``` :::note Audio feedback is only played if the device is not muted. ::: --- ## About Smart Label Capture import AboutLabelCapture from '../../../partials/intro/_about-smart-label-capture.mdx'; import ValidationFlow from '../../../partials/intro/_about_validation_flow.mdx'; See [here](./advanced.md#validation-flow) for more details. --- ## Label Definitions # Label Definitions Smart Label Capture provides a [Label Definition](https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/label-definition.html#label-definition) API, enabling you to configure and extract structured data from predefined and custom labels. This feature provides a flexible way to recognize and decode fields within a specific label layout such as price tags, VIN labels, or packaging stickers without needing to write custom code for each label type. A **Label Definition** is a configuration that defines the label, and its relevant fields, that Smart Label Capture should recognize and extract during scans. There are two approaches to using label definitions: - [**Pre-built Labels**](#pre-built-labels) - [**Custom Labels**](#custom-labels) ## Pre-built Labels Smart Label Capture includes ready-made label definitions for common use cases. These pre-built options let you recognize and extract information from standard label types without creating custom configurations: ### Example: Price label Configure a pre-built label definition for price labels, such as those found in retail environments: ![Price Label Example](/img/slc/price-label.png) ```swift let settings = try LabelCaptureSettings { LabelDefinition.priceCapture(withName: "price-label") } ``` ## Custom Labels If Smart Label Capture’s pre-built options don’t fit your needs, define a custom label instead. Custom labels can combine your own fields with any of the available pre-built ones. :::tip The following characters are recognized: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ()-./:,$¶"`. ::: ### Custom Fields There are two types of custom fields you can define: The following fluent methods are available to configure custom fields: | Method | Optional | Description | |--------|----------|-------------| | `valueRegex()` / `valueRegexes()` | No | The regex patterns that identify the target string in the scanned content. | | `anchorRegex()` / `anchorRegexes()` | Yes | Used to specify keywords or phrases that help identify the context of the field. This is particularly useful when the label contains multiple fields that could match the same pattern (e.g., when both packaging and expiry dates are present). | | `symbologies` (init param) | No | The barcode symbologies to match for barcode fields. This is important for ensuring that the field only captures data from specific barcode types, enhancing accuracy and relevance. | | `optional()` | Yes | Whether the field is optional or mandatory. This is helpful when certain fields may not be present on every scan. | #### Example: Fish Shipping Box This example shows how to create a custom label definition for a fish shipping box, which includes fields for barcode and batch number. ![Fish Shipping Box Example](/img/slc/fish-shipping-box.png) ```swift let settings = try LabelCaptureSettings { LabelDefinition("shipping-label") { CustomBarcode( name: "barcode-field", symbologies: [.code128] ) CustomText(name: "batch-number-field") .anchorRegexes(["Batch"]) .valueRegexes(["FZ\\d{5,10}"]) .optional(true) } } ``` ### Pre-built Fields You can also configure your label by using pre-built fields. These are some common fields provided for faster integration, with all value regex patterns and anchor regex patterns already predefined. Customization of pre-built fields is done via the `valueRegex()`, `valueRegexes()`, `anchorRegex()`, `anchorRegexes()`, and `optional()` fluent methods, which allow you to specify the expected format of the field data. :::tip All pre-built fields come with default value and anchor regex patterns that are suitable for most use cases. **Using these methods is optional and will override the defaults**. The `resetAnchorRegexes()` method can be used to remove the default anchor regexes, allowing you to rely solely on the value patterns for detection. ::: import FeatureList from '@site/src/components/FeatureList'; #### Barcode Fields #### Price and Weight Fields #### Date and Custom Text Fields #### Example: Hard disk drive label This example demonstrates how to configure a label definition for a hard disk drive (HDD) label, which typically includes common fields like serial number and part number. ![Hard Disk Drive Label Example](/img/slc/hdd-label.png) ```swift let settings = try LabelCaptureSettings { LabelDefinition("hdd-label") { SerialNumberBarcode(name: "serial-number") PartNumberBarcode(name: "part-number") } } ``` --- ## Adding AR Overlays # Adding AR Overlays In the previous section we covered how to vizualize the scan process using the [`BarcodeBatchBasicOverlay`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay). In this section we will cover how to add custom AR overlays to your MatrixScan application. There are two ways to add custom AR overlays to your application: * Using the [`BarcodeBatchAdvancedOverlay`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) class, our ready-to-use implementation for view-based AR overlays. * Provide your own fully custom implementation by using the [`SDCBarcodeBatchListener.barcodeBatch:didUpdate:frameData:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) function to retrieve the tracking information and implement your own AR overlay. The first option is the easiest and recommended approach for most applications. It covers adding, removing, and animating the overlay’s views whenever needed and is also flexible enough to cover the majority of use cases. ## Using BarcodeBatchAdvancedOverlay The advanced overlay combined with its listener offers an easy way of adding augmentations to your [`SDCDataCaptureView`](https://docs.scandit.com/data-capture-sdk/ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). In this example we'll add a view above each barcode showing its content. First, create a new instance of `SDCBarcodeBatchAdvancedOverlay` and add it to your `SDCDataCaptureView`: ```swift let overlay = BarcodeBatchAdvancedOverlay(barcodeBatch: barcodeBatch, view: captureView) ``` There are two ways to proceed from here: * Add a [`SDCBarcodeBatchAdvancedOverlayDelegate`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) to the overlay. * Use the `setters` in the [`overlay`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) to specify the view, anchor, and offset for each barcode. :::note The second way will take priority over the first one, meaning that if a view for a barcode has been set using [`SDCBarcodeBatchAdvancedOverlay.setView:forTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), the function [`SDCBarcodeBatchAdvancedOverlayDelegate.barcodeBatchAdvancedOverlay:viewForTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) won’t be invoked for that specific barcode. ::: ### Using the Delegate For this option, keep in mind that: * You need to conform to `SDCBarcodeBatchAdvancedOverlayDelegate`. This protocol’s methods are invoked every time a barcode is newly tracked. * [`SDCBarcodeBatchAdvancedOverlayDelegate.barcodeBatchAdvancedOverlay:viewForTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) asks for a view to animate on top of the barcode. Returning `nil` will show no view. * [`SDCBarcodeBatchAdvancedOverlayDelegate.barcodeBatchAdvancedOverlay:anchorForTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode) asks how to anchor the view to the barcode through [`SDCAnchor`](https://docs.scandit.com/data-capture-sdk/ios/core/api/anchor.html#enum-scandit.datacapture.core.Anchor). Be aware that it anchors the view’s center to the anchor point. To achieve anchoring the top of the view or the bottom you will have to set an offset. * [`SDCBarcodeBatchAdvancedOverlayDelegate.barcodeBatchAdvancedOverlay:offsetForTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode) asks for an offset that is applied on the already anchored view. This offset is expressed through a [`SDCPointWithUnit`](https://docs.scandit.com/data-capture-sdk/ios/core/api/common.html#struct-scandit.datacapture.core.PointWithUnit). ```swift func barcodeBatchAdvancedOverlay(_ overlay: BarcodeBatchAdvancedOverlay, viewFor trackedBarcode: TrackedBarcode) -> UIView? { // Create and return the view you want to show for this tracked barcode. You can also return nil, to have no view for this barcode. let label = UILabel() label.text = trackedBarcode.barcode.data label.backgroundColor = .white label.sizeToFit() return label } func barcodeBatchAdvancedOverlay(_ overlay: BarcodeBatchAdvancedOverlay, anchorFor trackedBarcode: TrackedBarcode) -> Anchor { // As we want the view to be above the barcode, we anchor the view's center to the top-center of the barcode quadrilateral. // Use the function below to adjust the position of the view by providing an offset. return .topCenter } func barcodeBatchAdvancedOverlay(_ overlay: BarcodeBatchAdvancedOverlay, offsetFor trackedBarcode: TrackedBarcode) -> PointWithUnit { // This is the offset that will be applied to the view. // You can use .fraction to give a measure relative to the view itself, the sdk will take care of transforming this into pixel size. // We now center horizontally and move up the view to make sure it's centered and above the barcode quadrilateral by half of the view's height. return PointWithUnit( x: FloatWithUnit(value: 0, unit: .fraction), y: FloatWithUnit(value: -1, unit: .fraction) ) } ``` ### Using the Setters The function [`SDCBarcodeBatchListener.barcodeBatch:didUpdate:frameData:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) gives you access to a [session](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession). This session object contains all added, updated, and removed tracked barcodes. From there you can create the view you want to display, and then call: * [`SDCBarcodeBatchAdvancedOverlay.setView:forTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode) * [`SDCBarcodeBatchAdvancedOverlay.setAnchor:forTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode) * [`SDCBarcodeBatchAdvancedOverlay.setOffset:forTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode) ```swift func barcodeBatch(_ barcodeBatch: BarcodeBatch, didUpdate session: BarcodeBatchSession, frameData: FrameData) { DispatchQueue.main.async { for trackedBarcode in session.addedTrackedBarcodes { let label = UILabel() label.text = trackedBarcode.barcode.data label.backgroundColor = .white label.sizeToFit() self.overlay.setView(label, for: trackedBarcode) self.overlay.setAnchor(.topCenter, for: trackedBarcode) let point = PointWithUnit(x: FloatWithUnit(value: 0, unit: .fraction), y: FloatWithUnit(value: -1, unit: .fraction)) self.overlay.setOffset(point, for: trackedBarcode) } } } ``` ## Using Custom Implementations If you do not want to use the overlay, it is also possible to add augmented reality features based on the tracking identifier and the [quadrilateral](https://docs.scandit.com/data-capture-sdk/ios/core/api/common.html#struct-scandit.datacapture.core.Quadrilateral) coordinates of every tracked barcode. When doing so, keep the following in mind: * Set a [`SDCBarcodeBatchListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) on the barcode tracking * In the [`SDCBarcodeBatchListener.barcodeBatch:didUpdate:frameData:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) function fetch the [added](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.AddedTrackedBarcodes) and [removed](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.RemovedTrackedBarcodes) tracked barcodes * Create and show the views for the added barcodes * Remove the views for the lost barcode * Via [`CADisplayLink`](https://developer.apple.com/documentation/quartzcore/cadisplaylink), add a method called 60fps when [`SDCBarcodeBatch`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) is enabled. In this method, for each [`SDCTrackedBarcode`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/tracked-barcode.html#class-scandit.datacapture.barcode.batch.TrackedBarcode) on-screen, update the position based on [`SDCTrackedBarcode.location`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location). There is no need to animate the change of location, the change of position will happen frequently enough that the view will look animated. * The frame coordinates from `SDCTrackedBarcode.location` need to be mapped to view coordinates using [`SDCDataCaptureView.viewQuadrilateralForFrameQuadrilateral:`](https://docs.scandit.com/data-capture-sdk/ios/core/api/ui/data-capture-view.html#method-scandit.datacapture.core.ui.DataCaptureView.MapFrameQuadrilateralToView). ```swift func barcodeBatch(_ barcodeBatch: BarcodeBatch, didUpdate session: BarcodeBatchSession, frameData: FrameData) { DispatchQueue.main.async { for lostTrackIdentifier in session.removedTrackedBarcodes { // You now know the identifier of the tracked barcode that has been lost. Usually here you would remove the views associated. } for trackedBarcode in session.addedTrackedBarcodes { // Fixed identifier for the tracked barcode. let trackingIdentifier = trackedBarcode.identifier // Current location of the tracked barcode. let location = trackedBarcode.location let quadrilateral = self.captureView.viewQuadrilateral(forFrameQuadrilateral: location) // You now know this new tracking's identifier and location. Usually here you would create and show the views. } } } ``` --- ## Get Started With SwiftUI # Get Started With SwiftUI In this guide you will learn step-by-step how to add MatrixScan to your application using SwiftUI. The general steps are: 1. **Create a UIViewController**: Implement the MatrixScan logic following the main [Get Started guide](./get-started.md) 2. **Create a SwiftUI wrapper**: Use `UIViewControllerRepresentable` to integrate the `UIViewController` 3. **Use in your SwiftUI app**: Add the SwiftUI view to your app's view hierarchy The core MatrixScan implementation (data capture context, settings, camera setup, etc.) remains the same as described in the main guide. ## Create a UIViewController for MatrixScan To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a `UIViewController` that handles the MatrixScan functionality. This follows the same implementation as described in the main [Get Started guide](./get-started.md). Create a `MatrixScanViewController` class that implements all the steps from the UIKit guide: ```swift import ScanditBarcodeCapture import UIKit class MatrixScanViewController: UIViewController { private var context: DataCaptureContext! private var camera: Camera? private var barcodeBatch: BarcodeBatch! private var captureView: DataCaptureView! private var overlay: BarcodeBatchBasicOverlay! override func viewDidLoad() { super.viewDidLoad() setupRecognition() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodeBatch.isEnabled = true camera?.switch(toDesiredState: .on) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) barcodeBatch.isEnabled = false camera?.switch(toDesiredState: .off) } func setupRecognition() { // Follow the implementation from the Get Started guide: // 1. Create data capture context // 2. Configure the Barcode Batch Mode // 3. Use the built-in camera // 4. Visualize the scan process // 5. Provide feedback } } extension MatrixScanViewController: BarcodeBatchBasicOverlayDelegate { func barcodeBatchBasicOverlay(_ overlay: BarcodeBatchBasicOverlay, brushFor trackedBarcode: TrackedBarcode) -> Brush? { // Return a custom Brush based on the tracked barcode. } func barcodeBatchBasicOverlay(_ overlay: BarcodeBatchBasicOverlay, didTap trackedBarcode: TrackedBarcode) { // Handle barcode tap // See the main Get Started guide } } ``` ## Create a SwiftUI View using UIViewControllerRepresentable Now create a SwiftUI wrapper that integrates the UIViewController into your SwiftUI app: ```swift import SwiftUI import UIKit struct MatrixScanRepresentable: UIViewControllerRepresentable { typealias UIViewControllerType = MatrixScanViewController func makeUIViewController(context: Context) -> MatrixScanViewController { return MatrixScanViewController() } func updateUIViewController(_ uiViewController: MatrixScanViewController, context: Context) { // Update the view controller if needed } } ``` ## Use the SwiftUI View in Your App Finally, use the `MatrixScanRepresentable` in your SwiftUI app: ```swift import SwiftUI @main struct MyApp: App { var body: some Scene { WindowGroup { MatrixScanRepresentable() } } } ``` Or within another SwiftUI view: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanRepresentable() .navigationTitle("MatrixScan") } } } ``` ## Alternative: Using UIViewRepresentable As an alternative to wrapping a `UIViewController`, you can implement the MatrixScan functionality directly using `UIViewRepresentable`. This approach uses a `Coordinator` to hold the SDK objects, ensuring they are created once and persist across SwiftUI updates: ```swift import ScanditBarcodeCapture import SwiftUI struct MatrixScanView: UIViewRepresentable { let onBarcodeBatchUpdated: ([TrackedBarcode]) -> Void func makeCoordinator() -> Coordinator { Coordinator() } func makeUIView(context: Context) -> UIView { let coordinator = context.coordinator coordinator.onBarcodesUpdated = onBarcodeBatchUpdated if let camera = Camera.default { // Apply recommended camera settings let cameraSettings = BarcodeBatch.recommendedCameraSettings camera.apply(cameraSettings) // Turn on the camera coordinator.dataCaptureContext.setFrameSource(camera) camera.switch(toDesiredState: .on) coordinator.camera = camera } // Enable Barcode Batch coordinator.barcodeBatch.isEnabled = true // Create the capture view let captureView = DataCaptureView(context: coordinator.dataCaptureContext, frame: .zero) captureView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // Create the overlay coordinator.overlay = BarcodeBatchBasicOverlay(barcodeBatch: coordinator.barcodeBatch, view: captureView, style: .frame) return captureView } func updateUIView(_ uiView: UIView, context: Context) { context.coordinator.onBarcodesUpdated = onBarcodeBatchUpdated } static func dismantleUIView(_ uiView: UIView, coordinator: Coordinator) { coordinator.barcodeBatch.isEnabled = false coordinator.camera?.switch(toDesiredState: .off) } class Coordinator: NSObject, BarcodeBatchListener { let dataCaptureContext: DataCaptureContext let barcodeBatch: BarcodeBatch var overlay: BarcodeBatchBasicOverlay? var camera: Camera? var onBarcodesUpdated: (([TrackedBarcode]) -> Void)? override init() { // Create the data capture context DataCaptureContext.initialize(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") dataCaptureContext = DataCaptureContext.shared // Configure barcode batch settings let settings = BarcodeBatchSettings() // ... // Create barcode batch mode barcodeBatch = BarcodeBatch(context: dataCaptureContext, settings: settings) super.init() barcodeBatch.addListener(self) } nonisolated func barcodeBatch(_ barcodeBatch: BarcodeBatch, didUpdate session: BarcodeBatchSession, frameData: FrameData) { let trackedBarcodes = session.trackedBarcodes.values.map { $0 } DispatchQueue.main.async { self.onBarcodesUpdated?(trackedBarcodes) } } } } ``` You can then use this view directly in your SwiftUI app: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanView { trackedBarcodes in // Handle the tracked barcodes } .navigationTitle("MatrixScan") } } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan to your application. The general steps are: - Creating a new Data Capture Context instance - Configuring the MatrixScan mode - Using the built-in camera - Visualizing the scan process - Providing feedback - Disabling barcode tracking ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Configure the Barcode Batch Mode The main entry point for the Barcode Batch Mode is the [`SDcBarcodeBatch`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object. It is configured through [`SDCBarcodeBatchSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) and allows to register one or more listeners that will get informed whenever a new frame has been processed. :::note Typically you will not need to conform to a [`SDCBarcodeBatchListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener), instead you will add a [`SDCBarcodeBatchBasicOverlay`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) and conform to a [`SDCBarcodeBatchBasicOverlayDelegate`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener). ::: Here we will setup Barcode Batch for tracking QR codes: ```swift let settings = BarcodeBatchSettings() settings.set(symbology: .qr, enabled: true) ``` Next, create a [`SDcBarcodeBatch`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance with the data capture context and the settings initialized in the previous steps: ```swift barcodeBatch = BarcodeBatch(context: context, settings: settings) ``` ## Use the Built-in Camera :::note In iOS the user must explicitly grant permission to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission by including the [`NSCameraUsageDescription`](https://developer.apple.com/documentation/bundleresources/information_property_list/nscamerausagedescription) key in your app’s `Info.plist` file. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. ```swift let cameraSettings = BarcodeBatch.recommendedCameraSettings // Depending on the use case further camera settings adjustments can be made here. let camera = Camera.default camera?.apply(cameraSettings) ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [`SDCDataCaptureContext.setFrameSource:completionHandler:`](https://docs.scandit.com/data-capture-sdk/ios/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```swift context.setFrameSource(camera) ``` The camera is off by default and must be turned on. This is done by calling [`SDCFrameSource.switchToDesiredState:completionHandler:`](https://docs.scandit.com/data-capture-sdk/ios/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [`SDCFrameSourceStateOn`](https://docs.scandit.com/data-capture-sdk/ios/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```swift camera?.switch(toDesiredState: .on) ``` ## Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [`SDCDataCaptureView`](https://docs.scandit.com/data-capture-sdk/ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```swift let captureView = DataCaptureView(context: context, frame: view.bounds) captureView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(captureView) ``` To visualize the results of Barcode Batch, first you need to add the following overlay: ```swift let overlay = BarcodeBatchBasicOverlay(barcodeBatch: barcodeBatch, view: captureView) ``` Once the overlay has been added, you should conform to the [`SDCBarcodeBatchBasicOverlayDelegate`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) protocol. The method [`SDCBarcodeBatchBasicOverlayDelegate.barcodeBatchBasicOverlay:brushForTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode) is invoked every time a new tracked barcode appears and it can be used to set a brush used to highlight that specific barcode in the overlay. ```swift extension ViewController: BarcodeBatchBasicOverlayDelegate { func barcodeBatchBasicOverlay(_ overlay: BarcodeBatchBasicOverlay, brushFor trackedBarcode: TrackedBarcode) -> Brush? { // Return a custom Brush based on the tracked barcode. } } ``` If you would like to make the highlights tappable, you need to implement the [`SDCBarcodeBatchBasicOverlayDelegate.barcodeBatchBasicOverlay:didTapTrackedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped) method. ```swift extension ViewController: BarcodeBatchBasicOverlayDelegate { func barcodeBatchBasicOverlay(_ overlay: BarcodeBatchBasicOverlay, didTap trackedBarcode: TrackedBarcode) { // A tracked barcode was tapped. } } ``` ## Barcode Batch Feedback Barcode Batch, unlike Barcode Capture, doesn’t emit feedback (sound or vibration) when a new barcode is recognized. However, you may implement a [`SDCBarcodeBatchListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) to provide a similar experience. Here, we use the default [`SDCFeedback`](https://docs.scandit.com/data-capture-sdk/ios/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration. ```swift override func viewDidLoad() { super.viewDidLoad() feedback = Feedback.default } ``` Next, use this feedback in a `SDCBarcodeBatchListener`: ```swift extension ViewController: BarcodeBatchListener { func barcodeBatch(_ barcodeBatch: BarcodeBatch, didUpdate session: BarcodeBatchSession, frameData: FrameData) { if !session.addedTrackedBarcodes.isEmpty { feedback?.emit() } } } ``` [`SDCBarcodeBatchListener.barcodeBatch:didUpdate:frameData:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) is invoked for every processed frame. The session parameter contains information about the currently tracked barcodes. We check if there are any newly recognized barcodes and emit the feedback if so. As the last step, register the delegate responsible for emitting the feedback with the [`SDcBarcodeBatch`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance. ```swift barcodeBatch.addListener(self) ``` ## Disable Barcode Batch To disable barcode tracking set [`SDCBarcodeBatch.enabled`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-batch.html#property-scandit.datacapture.barcode.batch.BarcodeBatch.IsEnabled) to `NO`. The effect is immediate, no more frames will be processed after the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off or put it in standby calling [`SwitchToDesiredState`](https://docs.scandit.com/data-capture-sdk/ios/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of `StandBy`. --- ## About MatrixScan Batch # About MatrixScan Batch import AboutMatrixScan from '../../../partials/intro/_about-matrixscan.mdx' --- ## Get Started With SwiftUI # Get Started With SwiftUI In this guide you will learn step-by-step how to add MatrixScan AR to your application using SwiftUI. The general steps are: 1. **Create a UIViewController**: Implement the MatrixScan AR logic following the main [Get Started guide](./get-started.md) 2. **Create a SwiftUI wrapper**: Use `UIViewControllerRepresentable` to integrate the `UIViewController` 3. **Use in your SwiftUI app**: Add the SwiftUI view to your app's view hierarchy The core MatrixScan AR implementation (data capture context, settings, camera setup, etc.) remains the same as described in the main guide. ## Create a UIViewController for MatrixScan AR To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a `UIViewController` that handles the MatrixScan AR functionality. This follows the same implementation as described in the main [Get Started guide](./get-started.md). Create a `MatrixScanArViewController` class that implements all the steps from the UIKit guide: ```swift import ScanditBarcodeCapture import UIKit class MatrixScanArViewController: UIViewController { private var context: DataCaptureContext! private var barcodeAr: BarcodeAr! private var barcodeArView: BarcodeArView! override func viewDidLoad() { super.viewDidLoad() setupRecognition() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodeArView.start() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) barcodeArView.stop() } func setupRecognition() { // Follow the implementation from the Get Started guide: // 1. Create data capture context // 2. Configure the Barcode AR Mode // 3. Setup the Barcode AR View // 4. Register the providers } } extension MatrixScanArViewController: BarcodeArAnnotationProvider { func annotation(for barcode: Barcode) async -> (any UIView & BarcodeArAnnotation)? { // Provide annotations for barcodes // See the main Get Started guide return nil } } extension MatrixScanArViewController: BarcodeArHighlightProvider { func highlight(for barcode: Barcode) async -> (any UIView & BarcodeArHighlight)? { // Provide highlights for barcodes // See the main Get Started guide return nil } } extension MatrixScanArViewController: BarcodeArViewUIDelegate { func barcodeAr(_ barcodeAr: BarcodeAr, didTapHighlightFor barcode: Barcode, highlight: any UIView & BarcodeArHighlight) { // Handle tap events } } ``` ## Create a SwiftUI View using UIViewControllerRepresentable Now create a SwiftUI wrapper that integrates the UIViewController into your SwiftUI app: ```swift import SwiftUI import UIKit struct MatrixScanArRepresentable: UIViewControllerRepresentable { typealias UIViewControllerType = MatrixScanArViewController func makeUIViewController(context: Context) -> MatrixScanArViewController { return MatrixScanArViewController() } func updateUIViewController(_ uiViewController: MatrixScanArViewController, context: Context) { // Update the view controller if needed } } ``` ## Use the SwiftUI View in Your App Finally, use the `MatrixScanArRepresentable` in your SwiftUI app: ```swift import SwiftUI @main struct MyApp: App { var body: some Scene { WindowGroup { MatrixScanArRepresentable() } } } ``` Or within another SwiftUI view: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanArRepresentable() .navigationTitle("MatrixScan AR") } } } ``` ## Alternative: Using UIViewRepresentable As an alternative to wrapping a `UIViewController`, you can implement the MatrixScan AR functionality directly using `UIViewRepresentable`. This approach uses a `Coordinator` to hold the SDK objects and implement the highlight and annotation providers: ```swift import ScanditBarcodeCapture import SwiftUI struct MatrixScanArView: UIViewRepresentable { func makeCoordinator() -> Coordinator { Coordinator() } func makeUIView(context: Context) -> UIView { let coordinator = context.coordinator let view = UIView() // Configure Barcode AR view settings let viewSettings = BarcodeArViewSettings() // ... // Create the Barcode AR view let barcodeArView = BarcodeArView(parentView: view, barcodeAr: coordinator.barcodeAr, settings: viewSettings, cameraSettings: nil) barcodeArView.highlightProvider = coordinator barcodeArView.annotationProvider = coordinator coordinator.barcodeArView = barcodeArView // Start the AR view barcodeArView.start() return view } func updateUIView(_ uiView: UIView, context: Context) {} static func dismantleUIView(_ uiView: UIView, coordinator: Coordinator) { coordinator.barcodeArView?.stop() } class Coordinator: NSObject, BarcodeArHighlightProvider, BarcodeArAnnotationProvider { let dataCaptureContext: DataCaptureContext let barcodeAr: BarcodeAr var barcodeArView: BarcodeArView? override init() { // Create the data capture context DataCaptureContext.initialize(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") dataCaptureContext = DataCaptureContext.shared // Configure Barcode AR settings let settings = BarcodeArSettings() // ... // Create Barcode AR mode barcodeAr = BarcodeAr(context: dataCaptureContext, settings: settings) super.init() } func highlight(for barcode: Barcode) async -> (any UIView & BarcodeArHighlight)? { return BarcodeArRectangleHighlight(barcode: barcode) } func annotation(for barcode: Barcode) async -> (any UIView & BarcodeArAnnotation)? { let annotation = BarcodeArStatusIconAnnotation(barcode: barcode) annotation.text = "Example annotation" return annotation } } } ``` You can then use this view directly in your SwiftUI app: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanArView() .navigationTitle("MatrixScan AR") } } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan AR to your application. Implementing MatrixScan AR involves two primary elements: - Barcode AR: The data capture mode that is used for scan and check functionality. - A Barcode AR View: The pre-built UI elements used to highlight items to be checked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode AR Mode - Setup the Barcode AR View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Configure the Barcode AR Mode The main entry point for the Barcode AR Mode is the `BarcodeAr` object. You can configure the supported Symbologies through its [`BarcodeArSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-ar-settings.html). Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```swift let settings = BarcodeArSettings() settings.set(symbology: .ean13UPCA, enabled: true) ``` Then create the mode with the previously created settings: ```swift let barcodeAr = BarcodeAr(context: context, settings: settings) ``` ## Setup the `BarcodeArView` MatrixScan AR’s built-in AR user interface includes buttons and overlays that guide the user through the scan and check process. By adding a [`BarcodeArView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.ar.ui.BarcodeArView), the scanning interface is added automatically to your application. The `BarcodeArView` is where you provide the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.ar.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.ar.ui.BarcodeArView.AnnotationProvider) to supply the highlight and annotation information for the barcodes to be checked. If *null*, a default highlight is used and no annotations are provided. The `BarcodeArView` appearance can be customized through [`BarcodeArViewSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-ar-view-settings.html#class-scandit.datacapture.barcode.ar.ui.BarcodeArViewSettings), properties on the`BarcodeArView`, and the corresponding settings for your desired highlights and/or annotations, to match your application’s look and feel. The following settings can be customized: * Audio and haptic feedback * Camera position * Torch button visibility and its position * Switch camera button visibility and its position * Zoom control visibility and its position * The size, colors, and styles of the highlights and annotations ```swift let viewSettings = BarcodeArViewSettings() viewSettings.hapticEnabled = false viewSettings.soundEnabled = false viewSettings.defaultCameraPosition = .userFacing ``` Next, create a `BarcodeArView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodeArView` is automatically added to the provided parent view. ```swift let barcodeArView = BarcodeArView(parentView: parentView, barcodeAr: barcodeAr, settings: viewSettings, cameraSettings: BarcodeAr.recommendedCameraSettings) barcodeArView.shouldShowCameraSwitchControl = true barcodeArView.shouldShowTorchControl = true barcodeArView.shouldShowZoomControl = true barcodeArView.cameraSwitchControlPosition = .topRight barcodeArView.torchControlPosition = .bottomRight barcodeArView.zoomControlPosition = .topLeft ``` Configure the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.ar.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.ar.ui.BarcodeArView.AnnotationProvider). ```swift extension ViewController: BarcodeArAnnotationProvider { func annotation(for barcode: Barcode, completionHandler: @escaping ((any UIView & BarcodeArAnnotation)?) -> Void) { let annotation = BarcodeArStatusIconAnnotation(barcode: barcode) annotation.text = "Example annotation" completionHandler(annotation) } } extension ViewController: BarcodeArHighlightProvider { func highlight(for barcode: Barcode, completionHandler: @escaping ((any UIView & BarcodeArHighlight)?) -> Void) { let highlight = BarcodeArRectangleHighlight(barcode: barcode) completionHandler(highlight) } } ``` And set them to the view: ```swift barcodeArView.annotationProvider = self barcodeArView.highlightProvider = self ``` Connect the `BarcodeArView` to the iOS lifecycle. The view is dependent on calling `BarcodeArView.start()` and `BarcodeArView.stop()` to set up the camera and its overlays properly. ```swift override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodeArView.start() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) barcodeArView.stop() } ``` ## Register the Listener If you want a callback when a highlight is tapped, register a [BarcodeArViewUIDelegate](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-ar-view.html#interface-scandit.datacapture.barcode.ar.ui.IBarcodeArViewUiListener). ```swift extension ViewController: BarcodeArViewUIDelegate { func barcodeAr(_ barcodeAr: BarcodeAr, didTapHighlightFor barcode: Barcode, highlight: any UIView & BarcodeArHighlight) { // Handle tap } } ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `barcodeArView.start()`. ```swift override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodeArView.start() } ``` --- ## About MatrixScan AR # About MatrixScan AR import AboutMatrixScanCheck from '../../../partials/intro/_about-matrixscan-ar.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Count is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Count to best fit your needs. ## Scanning Against a List There is a function to set a list of expected barcodes if you are scanning against a manifest or item list. If this is used, a progress bar is added to the UI so you can keep track of the process while scanning. When scanning against a list, the UI will also show red icons to mark scanned barcodes that aren’t present on the list. To set the list of expected barcodes, use the following code: ```swift let targetBarcodes = Set(arrayLiteral: TargetBarcode(data: "data", quantity: 1)) let captureList = BarcodeCountCaptureList(listener: self, targetBarcodes: targetBarcodes) barcodeCount.setCaptureList(captureList) ``` ## Barcode Count Status This feature is used to provide users with more details regarding the items they’re scanning in order to aid effective handling. The icons appear as an AR overlay after tapping the “Status Mode” button and can be used to highlight the following: ![Barcode Count Status](/img/matrixscan-count/barcode_count_status.png) See the [Expiry Management Sample](https://github.com/Scandit/datacapture-ios-samples/tree/master/03_Advanced_Batch_Scanning_Samples/02_Counting_and_Receiving/ExpiryManagementSample) for an example of how to use this feature. ## Clustering import Clustering from '../../../partials/count/_clustering.mdx' ## Tote Mapping import Totes from '../../../partials/count/_tote-mapping.mdx' ## Strap Mode It can be difficult to reach the shutter button if the smart device is attached to the user’s wrist by a strap or similar. You can enable a floating shutter button that can be positioned by the end user in a more ergonomically suitable position: ```swift barcodeCountView.shouldShowFloatingShutterButton = true ``` ## Filtering If there several types of barcodes on your label you may want to scan only one of them. In this case, you can filter the others out by symbology, symbol count, or setting a regex. For example, you might want to scan only Code 128 barcodes and no PDF417 barcodes. You can do this by setting the following: ```swift let filterSettings = BarcodeFilterSettings() filterSettings.excludedSymbologies = [.pdf417] let barcodeCountSettings = BarcodeCountSettings() barcodeCountSettings.set(symbology: .code128, enabled: true) barcodeCountSettings.set(symbology: .pdf417, enabled: true) barcodeCountSettings.filterSettings = filterSettings ``` Or to exclude all the barcodes starting with 4 numbers: ```swift let filterSettings = BarcodeFilterSettings() filterSettings.excludedCodesRegex = "^1234.*" let barcodeCountSettings = BarcodeCountSettings() barcodeCountSettings.filterSettings = filterSettings ``` By default the filters applied to the relevant barcodes are transparent, but you can use [`BarcodeFilterHighlightSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-filter-highlight-settings.html#barcode-filter-highlight-settings) to change the color and level of transparency. ![Different Filters in MatrixScan Count](/img/matrixscan-count/filtering_styles.png) ## Clear Screen Button There are situations in which the user may find it helpful to clean up their screen (i.e. clear all the AR overlays) but keep the list of barcodes scanned. For this you can enable the “Clear screen” button: ```swift barcodeCountView.shouldShowClearHighlightsButton = true ``` ## Customizing the AR Overlays MatrixScan Count comes with recommended and user-tested AR overlays. You can customize the overlay colors once the overlay has been added according to the [`SDCBarcodeCountViewDelegate`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-count-view-listener.html#interface-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener) protocol. The methods [`SDCBarcodeCountViewDelegate.barcodeCountView:brushForRecognizedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForRecognizedBarcode) and [`SDCBarcodeCountViewDelegate.barcodeCountView:brushForUnrecognizedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForUnrecognizedBarcode) are invoked every time a new recognized or unrecognized barcode appears. These can be used to set a brush that will highlight that specific barcode in the overlay. Keep in mind that these methods are relevant only when using the style [`SDCBarcodeCountViewStyleDot`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-count-view.html#value-scandit.datacapture.barcode.count.ui.BarcodeCountViewStyle.Dot). ```swift func barcodeCountView(_ view: BarcodeCountView, brushForRecognizedBarcode trackedBarcode: TrackedBarcode) -> Brush? { // Return a custom brush } func barcodeCountView(_ view: BarcodeCountView, brushForUnrecognizedBarcode trackedBarcode: TrackedBarcode) -> Brush? { // Return a custom brush } ``` ## Notifications To be notified when a user taps on an overlay, you need to implement the [`SDCBarcodeCountViewDelegate.barcodeCountView:didTapRecognizedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnRecognizedBarcodeTapped) and [`SDCBarcodeCountViewDelegate.barcodeCountView:didTapUnrecognizedBarcode:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped) methods: ```swift func barcodeCountView(_ view: BarcodeCountView, didTapRecognizedBarcode trackedBarcode: TrackedBarcode) { // Do something with the tapped barcode } func barcodeCountView(_ view: BarcodeCountView, didTapUnrecognizedBarcode trackedBarcode: TrackedBarcode) { // Do something with the tapped barcode } ``` ## Disable UI Elements The UI is an integral part of MatrixScan Count and we do not recommend that you use it without it. However, if you wish to disable UI elements you can so as follows. To disable buttons: ```swift barcodeCountView.shouldShowListButton = false barcodeCountView.shouldShowExitButton = false barcodeCountView.shouldShowShutterButton = false ``` To disable feedback and hints: ```swift barcodeCountView.shouldShowHints = false barcodeCountView.shouldShowUserGuidanceView = false ``` --- ## Get Started With SwiftUI # Get Started With SwiftUI In this guide you will learn step-by-step how to add MatrixScan Count to your application using SwiftUI. The general steps are: 1. **Create a UIViewController**: Implement the MatrixScan Count logic following the main [Get Started guide](./get-started.md) 2. **Create a SwiftUI wrapper**: Use `UIViewControllerRepresentable` to integrate the `UIViewController` 3. **Use in your SwiftUI app**: Add the SwiftUI view to your app's view hierarchy The core MatrixScan Count implementation (data capture context, settings, camera setup, etc.) remains the same as described in the main guide. ## Create a UIViewController for MatrixScan Count To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a `UIViewController` that handles the MatrixScan Count functionality. This follows the same implementation as described in the main [Get Started guide](./get-started.md). Create a `MatrixScanCountViewController` class that implements all the steps from the UIKit guide: ```swift import ScanditBarcodeCapture import UIKit class MatrixScanCountViewController: UIViewController { private var context: DataCaptureContext! private var camera: Camera? private var barcodeCount: BarcodeCount! private var barcodeCountView: BarcodeCountView! override func viewDidLoad() { super.viewDidLoad() setupRecognition() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) camera?.switch(toDesiredState: .on) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) camera?.switch(toDesiredState: .off) } func setupRecognition() { // Follow the implementation from the Get Started guide: // 1. Create data capture context // 2. Configure the Barcode Count Mode // 3. Obtain the camera instance and set frame source // 4. Register the listener to be informed when scan phase is complete // 5. Set the capture view and AR overlays // 6. Configure UI delegate for list and exit callbacks } } extension MatrixScanCountViewController: BarcodeCountListener { func barcodeCount(_ barcodeCount: BarcodeCount, didScanIn session: BarcodeCountSession, frameData: FrameData) { // Handle barcode count results // See the main Get Started guide } } extension MatrixScanCountViewController: BarcodeCountViewUIDelegate { func listButtonTapped(for view: BarcodeCountView) { // Handle list button tap } func exitButtonTapped(for view: BarcodeCountView) { // Handle exit button tap } } ``` ## Create a SwiftUI View using UIViewControllerRepresentable Now create a SwiftUI wrapper that integrates the UIViewController into your SwiftUI app: ```swift import SwiftUI import UIKit struct MatrixScanCountRepresentable: UIViewControllerRepresentable { typealias UIViewControllerType = MatrixScanCountViewController func makeUIViewController(context: Context) -> MatrixScanCountViewController { return MatrixScanCountViewController() } func updateUIViewController(_ uiViewController: MatrixScanCountViewController, context: Context) { // Update the view controller if needed } } ``` ## Use the SwiftUI View in Your App Finally, use the `MatrixScanCountRepresentable` in your SwiftUI app: ```swift import SwiftUI @main struct MyApp: App { var body: some Scene { WindowGroup { MatrixScanCountRepresentable() } } } ``` Or within another SwiftUI view: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanCountRepresentable() .navigationTitle("MatrixScan Count") } } } ``` ## Alternative: Using UIViewRepresentable As an alternative to wrapping a `UIViewController`, you can implement the MatrixScan Count functionality directly using `UIViewRepresentable`. This approach uses a `Coordinator` to hold the SDK objects, ensuring they are created once and persist across SwiftUI updates: ```swift import ScanditBarcodeCapture import SwiftUI struct MatrixScanCountView: UIViewRepresentable { let onScanCompleted: ([Barcode]) -> Void func makeCoordinator() -> Coordinator { Coordinator() } func makeUIView(context: Context) -> BarcodeCountView { let coordinator = context.coordinator coordinator.onScanCompleted = onScanCompleted if let camera = Camera.default { // Apply recommended camera settings let cameraSettings = BarcodeCount.recommendedCameraSettings camera.apply(cameraSettings) // Set the camera as the frame source (camera starts off) coordinator.dataCaptureContext.setFrameSource(camera) coordinator.camera = camera } // Create the Barcode Count view let barcodeCountView = BarcodeCountView(frame: .zero, context: coordinator.dataCaptureContext, barcodeCount: coordinator.barcodeCount) barcodeCountView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // Prepare scanning and turn on the camera barcodeCountView.prepareScanning(with: coordinator.dataCaptureContext) coordinator.camera?.switch(toDesiredState: .on) return barcodeCountView } func updateUIView(_ uiView: BarcodeCountView, context: Context) { context.coordinator.onScanCompleted = onScanCompleted } static func dismantleUIView(_ uiView: BarcodeCountView, coordinator: Coordinator) { uiView.stopScanning() coordinator.camera?.switch(toDesiredState: .off) } class Coordinator: NSObject, BarcodeCountListener { let dataCaptureContext: DataCaptureContext let barcodeCount: BarcodeCount var camera: Camera? var onScanCompleted: (([Barcode]) -> Void)? override init() { // Create the data capture context DataCaptureContext.initialize(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") dataCaptureContext = DataCaptureContext.shared // Configure Barcode Count settings let settings = BarcodeCountSettings() // ... // Create Barcode Count mode barcodeCount = BarcodeCount(context: dataCaptureContext, settings: settings) super.init() barcodeCount.addListener(self) } nonisolated func barcodeCount(_ barcodeCount: BarcodeCount, didScanIn session: BarcodeCountSession, frameData: FrameData) { let barcodes = session.recognizedBarcodes DispatchQueue.main.async { self.onScanCompleted?(barcodes) } } } } ``` You can then use this view directly in your SwiftUI app: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanCountView { barcodes in // Handle recognized barcodes } .navigationTitle("MatrixScan Count") } } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Count to your application. :::note MatrixScan Count is implemented via [`SDCBarcodeCount`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount). ::: The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Count Mode - Obtaining the camera instance and set frame source - Registering the listener to be informed when scan phase is complete - Setting the capture view and AR overlays - Configuring the camera for scanning view - Storing and retrieving the captured barcodes - Resetting the Barcode Count Mode - List and exit callbacks ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Configure the Barcode Count Mode The main entry point for the Barcode Count Mode is the `SDCBarcodeCount` object. It is configured through [`SDCBarcodeCountSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-count-settings.html#class-scandit.datacapture.barcode.count.BarcodeCountSettings) and allows you to register one or more listeners that are informed whenever a scan phase has finished. Here we will set up Barcode Count for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. If you are sure that your environment will only have unique barcodes, you can also enable [`SDCBarcodeCountSettings.expectsOnlyUniqueBarcodes`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-count-settings.html#property-scandit.datacapture.barcode.count.BarcodeCountSettings.ExpectsOnlyUniqueBarcodes). This option improves scanning performance as long as you are sure that no duplicates will be present. ```swift let settings = BarcodeCountSettings() settings.set(symbology: .ean13UPCA, enabled: true) ``` Next, create a `SDCBarcodeCount` instance with the Data Capture Context and the settings initialized in the previous step: ```swift let barcodeCount = BarcodeCount(context: context, settings: settings) ``` ## Camera Instance And Set Frame Source Our recommended camera settings should be used to achieve the best performance and user experience. The following code shows how to get the recommended settings for MatrixScan Count and create the camera from it: ```swift let cameraSettings = BarcodeCount.recommendedCameraSettings let camera = Camera.default camera?.apply(cameraSettings) ``` Because the frame source is configurable the data capture context must be told which frame source to use. This is done with a call to [`SDCDataCaptureContext.setFrameSource:completionHandler:`](https://docs.scandit.com/data-capture-sdk/ios/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```swift context.setFrameSource(camera) ``` ## Registering the Listener To keep track of the barcodes that have been scanned, implement the [`SDCBarcodeCountListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) protocol and register the listener. ```swift // Register self as a listener to monitor the barcode count session. barcodeCount.addListener(self) ``` [`SDCBarcodeCountListener.barcodeCount:didScanInSession:frameData:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan) is called when the scan phase has finished and results can be retrieved from [`SDCBarcodeCountSession`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession). ## Setting the Capture View and AR Overlays MatrixScan Count’s built-in AR user interface includes buttons and overlays that guide the user through the capturing process. By adding a [`SDCBarcodeCountView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) the scanning interface will be added automatically to your application. Add a `SDCBarcodeCountView` to your view hierarchy: ```swift let barcodeCountView = BarcodeCountView(frame: view.bounds, context: context, barcodeCount: barcodeCount) barcodeCountView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(barcodeCountView) ``` ## Configuring the Camera for Scanning View The camera is not automatically turned on when you are in a scanning view. You need to set up the camera so that it switches on when needed and it switches off when not needed anymore. Similarly `SDCBarcodeCount` should also be enabled and disabled. For example, you should switch off the camera when the `SDCBarcodeCountView` is not visible and switch on the camera when the `SDCBarcodeCountView` is visible. For example: ```swift override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) camera?.switch(toDesiredState: .on) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) camera?.switch(toDesiredState: .off) } ``` ## Store And Retrieve Scanned Barcodes The values captured as part of the scanning process are part of the [`session`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession), and the session is not accessible outside `SDCBarcodeCountListener.barcodeCount:didScanInSession:frameData:`. We recommend you store the values to present a list, for example when the user taps the list icon. To do this, make a copy of [`SDCBarcodeCountSession.recognizedBarcodes`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-count-session.html#property-scandit.datacapture.barcode.count.BarcodeCountSession.RecognizedBarcodes): ```swift extension ViewController: BarcodeCountListener { func barcodeCount(_ barcodeCount: BarcodeCount, didScanIn session: BarcodeCountSession, frameData: FrameData) { // Gather all the recognized barcodes let allRecognizedBarcodes = session.recognizedBarcodes // This method is invoked from a recognition internal thread. // Dispatch to the main thread to update the internal barcode list. DispatchQueue.main.async { // Update the internal list self.allRecognizedBarcodes = allRecognizedBarcodes } } } ``` ## Resetting the Barcode Count Mode When the scanning process is over, you need to reset the mode to make it ready for the next process. This clears the list of barcodes scanned and all the AR overlays. To reset Barcode Count’s scanning process, call the [`SDCBarcodeCount.reset`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-count.html#method-scandit.datacapture.barcode.count.BarcodeCount.Reset) method: ```swift barcodeCount.reset() ``` ## List and Exit Callbacks The UI includes two icons (buttons): “List” and “Exit”. The SDK provides the callbacks so you can add the desired action when those icons are tapped by the user: ```swift extension ViewController: BarcodeCountViewUIDelegate { func listButtonTapped(for view: BarcodeCountView) { // Show the current progress but the order is not completed } func exitButtonTapped(for view: BarcodeCountView) { // The order is completed } } ``` --- ## About MatrixScan Count # About MatrixScan Count import AboutMatrixScanCount from '../../../partials/intro/_about-matrixscan-count.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Find is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Find to best fit your needs. ## BarcodeFind Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodeFind` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`SDCBarcodeFindListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-find-listener.html#interface-scandit.datacapture.barcode.find.IBarcodeFindListener) on the mode itself, keeping in mind that these listeners are called from a background thread. ```swift mode.addListener(self) extension PlaygroundViewController: BarcodeFindListener { func barcodeFind(_ barcodeFind: BarcodeFind, didPauseSearch foundItems: Set) { // The mode was paused } func barcodeFindDidStartSearch(_ barcodeFind: BarcodeFind) { // The mode was started } func barcodeFind(_ barcodeFind: BarcodeFind, didStopSearch foundItems: Set) { // The mode was stopped } } ``` ## Multiple criteria You can assign different brushes to each BarcodeFindItem, so they appear visually different to the end user. This can be used to make some items stand out more, or to help the user mentally group certain items together. ```swift let availableBrush = Brush(fill: .green.withAlphaComponent(0.2), stroke: .green, strokeWidth: 1) let expiredBrush = Brush(fill: .red.withAlphaComponent(0.2), stroke: .red, strokeWidth: 1) var items = Set() items.insert(BarcodeFindItem( searchOptions: BarcodeFindItemSearchOptions(barcodeData: "9783598215438", brush: availableBrush), content: BarcodeFindItemContent( info: "Mini Screwdriver Set", additionalInfo: "(6-Piece)", image: nil) )) items.insert(BarcodeFindItem( searchOptions: BarcodeFindItemSearchOptions(barcodeData: "9783598215414", brush: expiredBrush), content: nil )) ``` ## Set Up a Transformation Sometimes the barcode data needs to be transformed. For example, if the barcode contains the product identifier and other information, when a product is scanned, the barcode data is first parsed (via a transformation) and then the input list is checked. First conform to the [`SDCBarcodeFindTransformer`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-find-transformer.html#interface-scandit.datacapture.barcode.find.IBarcodeFindTransformer) protocol. For example, if you want to only consider the first 5 characters: ```swift class Transformer: NSObject, BarcodeFindTransformer { func transformBarcodeData(_ data: String) -> String? { return String(data.prefix(5)) } } ``` Then the transformer needs to be set so it can be used by Barcode Find: ```swift barcodeFind.setBarcodeTransformer(Transformer()) ``` ## UI Customization The [`SDCBarcodeFindView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) by default shows a set of UI elements, any of which can be optionally hidden: - Play/Pause button - Finish button - Searched items carousel - Guidance hints - Progress bar (hidden by default) Each of these elements can be shown or hidden as needed. For example: ```swift barcodeFindView.shouldShowCarousel = false barcodeFindView.shouldShowProgressBar = true ``` --- ## Get Started With SwiftUI # Get Started With SwiftUI In this guide you will learn step-by-step how to add MatrixScan Find to your application using SwiftUI. The general steps are: 1. **Create a UIViewController**: Implement the MatrixScan Find logic following the main [Get Started guide](./get-started.md) 2. **Create a SwiftUI wrapper**: Use `UIViewControllerRepresentable` to integrate the `UIViewController` 3. **Use in your SwiftUI app**: Add the SwiftUI view to your app's view hierarchy The core MatrixScan Find implementation (data capture context, settings, camera setup, etc.) remains the same as described in the main guide. ## Create a UIViewController for MatrixScan Find To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a `UIViewController` that handles the MatrixScan Find functionality. This follows the same implementation as described in the main [Get Started guide](./get-started.md). Create a `MatrixScanFindViewController` class that implements all the steps from the UIKit guide: ```swift import ScanditBarcodeCapture import UIKit class MatrixScanFindViewController: UIViewController { private var context: DataCaptureContext! private var barcodeFind: BarcodeFind! private var barcodeFindView: BarcodeFindView! override func viewDidLoad() { super.viewDidLoad() setupRecognition() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodeFindView.startSearching() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) barcodeFindView.stopSearching() } func setupRecognition() { // Follow the implementation from the Get Started guide: // 1. Create data capture context // 2. Configure the Barcode Find Mode // 3. Setup the Barcode Find View // 4. Call prepareSearching() on the view // 5. Register the UI delegate to handle finish button } } extension MatrixScanFindViewController: BarcodeFindViewUIDelegate { func barcodeFindView(_ view: BarcodeFindView, didTapFinishButton foundItems: Set) { // Handle finish button tap } } ``` ## Create a SwiftUI View using UIViewControllerRepresentable Now create a SwiftUI wrapper that integrates the UIViewController into your SwiftUI app: ```swift import SwiftUI import UIKit struct MatrixScanFindRepresentable: UIViewControllerRepresentable { typealias UIViewControllerType = MatrixScanFindViewController func makeUIViewController(context: Context) -> MatrixScanFindViewController { return MatrixScanFindViewController() } func updateUIViewController(_ uiViewController: MatrixScanFindViewController, context: Context) { // Update the view controller if needed } } ``` ## Use the SwiftUI View in Your App Finally, use the `MatrixScanFindRepresentable` in your SwiftUI app: ```swift import SwiftUI @main struct MyApp: App { var body: some Scene { WindowGroup { MatrixScanFindRepresentable() } } } ``` Or within another SwiftUI view: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanFindRepresentable() .navigationTitle("MatrixScan Find") } } } ``` ## Alternative: Using UIViewRepresentable As an alternative to wrapping a `UIViewController`, you can implement the MatrixScan Find functionality directly using `UIViewRepresentable`. This approach creates the find view directly without an intermediate view controller: ```swift import ScanditBarcodeCapture import SwiftUI struct MatrixScanFindView: UIViewRepresentable { let itemsToFind: Set let onFinishButtonTapped: (Set) -> Void init(itemsToFind: Set, onFinishButtonTapped: @escaping (Set) -> Void) { self.itemsToFind = itemsToFind self.onFinishButtonTapped = onFinishButtonTapped } func makeCoordinator() -> Coordinator { return Coordinator() } func makeUIView(context: Context) -> UIView { let coordinator = context.coordinator let view = UIView() coordinator.onFinishButtonTapped = onFinishButtonTapped coordinator.barcodeFind.setItemList(itemsToFind) // Configure Barcode Find view settings let viewSettings = BarcodeFindViewSettings() // ... // Create the Barcode Find view (automatically added to parent view) let barcodeFindView = BarcodeFindView(parentView: view, context: coordinator.dataCaptureContext, barcodeFind: coordinator.barcodeFind, settings: viewSettings) barcodeFindView.uiDelegate = coordinator coordinator.barcodeFindView = barcodeFindView // Prepare then start searching barcodeFindView.prepareSearching() barcodeFindView.startSearching() return view } func updateUIView(_ uiView: UIView, context: Context) { context.coordinator.onFinishButtonTapped = onFinishButtonTapped context.coordinator.barcodeFind.setItemList(itemsToFind) } static func dismantleUIView(_ uiView: UIView, coordinator: Coordinator) { coordinator.barcodeFindView?.stopSearching() } class Coordinator: NSObject, BarcodeFindViewUIDelegate { let dataCaptureContext: DataCaptureContext let barcodeFind: BarcodeFind var barcodeFindView: BarcodeFindView? var onFinishButtonTapped: ((Set) -> Void)? override init() { // Create the data capture context DataCaptureContext.initialize(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") dataCaptureContext = DataCaptureContext.shared // Configure Barcode Find settings let settings = BarcodeFindSettings() // ... // Create Barcode Find mode (items will be set in makeUIView) barcodeFind = BarcodeFind(settings: settings) super.init() } func barcodeFindView(_ view: BarcodeFindView, didTapFinishButton foundItems: Set) { onFinishButtonTapped?(foundItems) } } } ``` You can then use this view directly in your SwiftUI app: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanFindView( itemsToFind: itemsToFind, onFinishButtonTapped: { foundItems in // Handle found items } ) .navigationTitle("MatrixScan Find") } } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Find to your application. Implementing MatrixScan Find involves two primary elements: - Barcode Find: The data capture mode that is used for search and find functionality. - A Barcode Find View: The pre-built UI elements used to highlight found items. :::note MatrixScan Count is implemented via [`SDCBarcodeFind`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind). ::: The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Find Mode - Setup the Barcode Find View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Configure the Barcode Count Mode The main entry point for the Barcode Find Mode is the [`SDCBarcodeFind`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind) object. You can configure the supported Symbologies through its [`SDCBarcodeFindSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-find-settings.html#class-scandit.datacapture.barcode.find.BarcodeFindSettings), and set up the list of items that you want MatrixScan Find to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```swift let settings = BarcodeFindSettings() settings.set(symbology: .ean13UPCA, enabled: true) ``` Next, create the list of items that will be actively searched for. We will also attach some optional information to the first item that can be used by the [`BarcodeFindView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) to display extra information: ```swift var items = Set() items.insert(BarcodeFindItem( searchOptions: BarcodeFindItemSearchOptions(barcodeData: "9783598215438"), content: BarcodeFindItemContent( info: "Mini Screwdriver Set", additionalInfo: "(6-Piece)", image: nil) )) items.insert(BarcodeFindItem( searchOptions: BarcodeFindItemSearchOptions(barcodeData: "9783598215414"), content: nil // Content information is optional, used for display only )) ``` Finally, create a [`SDCBarcodeFind`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind) instance with the Data Capture Context and the settings initialized in the previous step: ```swift let barcodeFind = BarcodeFind(settings: settings) barcodeFind.setItemList(items) ``` ## Setup the `BarcodeFindView` MatrixScan Find’s built-in AR user interface includes buttons and overlays that guide the user through the searching process. By adding a `SDCBarcodeFindView`, the scanning interface is added automatically to your application. The [`BarcodeFindView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) appearance can be customized through [`SDCBarcodeFindViewSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-find-view-settings.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindViewSettings) to match your application’s look and feel. For example, you can change the color of the dots that are overlaid on top of the items that are found and enable sound and haptic alerts. ```swift let viewSettings = BarcodeFindViewSettings() viewSettings.inListItemColor = .green viewSettings.notInListItemColor = .red viewSettings.soundEnabled = true viewSettings.hapticEnabled = true ``` Next, create a `SDCBarcodeFindView` instance with the Data Capture Context and the settings initialized in the previous step. he BarcodeFindView is automatically added to the provided parent view. ```swift let barcodeFindView = BarcodeFindView(parentView: view, context: context, barcodeFind: barcodeFind, settings: viewSettings) ``` Last, connect the [`BarcodeFindView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) to the iOS view controller lifecycle. :::note Be sure to call `BarcodeFindView.prepareSearching()` on your `UIViewController`’s [`viewWillAppear`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621510-viewwillappear) method to ensure optimal start up time. ::: ```swift override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodeFindView.prepareSearching() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) barcodeFindView.stopSearching() } ``` ## Register the Listener The [`BarcodeFindView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) displays a **Finish** button next to its shutter button. Here we register a [`SDCBarcodeFindViewUIDelegate`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-find-view.html#interface-scandit.datacapture.barcode.find.ui.IBarcodeFindViewUiListener) to be notified what items have been found once the finish button is pressed, and then navigate back to the previous screen to finish the find session. ```swift barcodeFindView.uiDelegate = self extension ViewController: BarcodeFindViewUIDelegate { func barcodeFindView(_ view: BarcodeFindView, didTapFinishButton foundItems: Set) { navigationController?.popViewController(animated: true) } } ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `barcodeFindView.startSearching()`. ```swift override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) barcodeFindView.startSearching() } ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Find # About MatrixScan Find import AboutFind from '../../../partials/intro/_about-matrixscan-find.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Pick is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Pick to best fit your needs. ## BarcodePick Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodePick` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodePickListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-pick-listener.html#interface-scandit.datacapture.barcode.pick.IBarcodePickListener) on the mode itself, keeping in mind that these listeners are called from a background thread. ```swift extension ViewController: BarcodePickListener { func barcodePick(_ barcodePick: BarcodePick, didUpdate session: BarcodePickSession) { // This callback will be invoked on a background thread every frame. The session object contains // updated the newly tracked items. } } ``` ## BarcodePickView Listener For lifecycle events on the `BarcodePickView` itself — when scanning starts, freezes, pauses, or stops — register a [`BarcodePickViewListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-pick-view-listener.html#interface-scandit.datacapture.barcode.pick.ui.BarcodePickViewListener) on the view. All callbacks are optional; implement only the ones you need. ```swift extension ViewController: BarcodePickViewListener { func barcodePickViewDidStartScanning(_ view: BarcodePickView) { // Invoked when the view starts scanning (e.g. after a call to start()). } func barcodePickViewDidFreezeScanning(_ view: BarcodePickView) { // Invoked when the view freezes the current frame (e.g. after a call to freeze()). } func barcodePickViewDidPauseScanning(_ view: BarcodePickView) { // Invoked when the view pauses scanning (e.g. after a call to pause()). } func barcodePickViewDidStopScanning(_ view: BarcodePickView) { // Invoked when the view stops scanning (e.g. after a call to stop()). } } ``` Register it on the view: ```swift barcodePickView.addListener(self) ``` --- ## Get Started With SwiftUI # Get Started With SwiftUI In this guide you will learn step-by-step how to add MatrixScan Pick to your application using SwiftUI. The general steps are: 1. **Create a UIViewController**: Implement the MatrixScan Pick logic following the main [Get Started guide](./get-started.md) 2. **Create a SwiftUI wrapper**: Use `UIViewControllerRepresentable` to integrate the `UIViewController` 3. **Use in your SwiftUI app**: Add the SwiftUI view to your app's view hierarchy The core MatrixScan Pick implementation (data capture context, settings, camera setup, etc.) remains the same as described in the main guide. ## Create a UIViewController for MatrixScan Pick To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a `UIViewController` that handles the MatrixScan Pick functionality. This follows the same implementation as described in the main [Get Started guide](./get-started.md). Create a `MatrixScanPickViewController` class that implements all the steps from the UIKit guide: ```swift import ScanditBarcodeCapture import UIKit class MatrixScanPickViewController: UIViewController { private var context: DataCaptureContext! private var barcodePick: BarcodePick! private var barcodePickView: BarcodePickView! override func viewDidLoad() { super.viewDidLoad() setupRecognition() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodePickView.start() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) barcodePickView.pause() if isMovingFromParent { barcodePickView.stop() } } func setupRecognition() { // Follow the implementation from the Get Started guide: // 1. Create data capture context // 2. Configure the Barcode Pick Mode with product provider // 3. Setup the Barcode Pick View // 4. Register the UI delegate and view listener } } extension MatrixScanPickViewController: BarcodePickAsyncMapperProductProviderDelegate { func mapItems(_ items: [String], completionHandler: @escaping ([BarcodePickProductProviderCallbackItem]) -> Void) { // Map scanned items to products // See the main Get Started guide } } extension MatrixScanPickViewController: BarcodePickViewUIDelegate { func barcodePickViewDidTapFinishButton(_ view: BarcodePickView) { // Handle finish button tap } } extension MatrixScanPickViewController: BarcodePickActionListener { func didPickItem(withData data: String, completionHandler: @escaping (Bool) -> Void) { // Confirm or reject the pick — required for picks to complete. completionHandler(true) } func didUnpickItem(withData data: String, completionHandler: @escaping (Bool) -> Void) { completionHandler(true) } } extension MatrixScanPickViewController: BarcodePickScanningListener { func barcodePick(_ barcodePick: BarcodePick, didUpdate scanningSession: BarcodePickScanningSession) { // Invoked on a background thread every time the picked state of an item changes. } func barcodePick(_ barcodePick: BarcodePick, didComplete scanningSession: BarcodePickScanningSession) { // Invoked when all the registered items needing picking have been picked. } } ``` ## Create a SwiftUI View using UIViewControllerRepresentable Now create a SwiftUI wrapper that integrates the `UIViewController` into your SwiftUI app: ```swift import SwiftUI import UIKit struct MatrixScanPickRepresentable: UIViewControllerRepresentable { typealias UIViewControllerType = MatrixScanPickViewController func makeUIViewController(context: Context) -> MatrixScanPickViewController { return MatrixScanPickViewController() } func updateUIViewController(_ uiViewController: MatrixScanPickViewController, context: Context) { // Update the view controller if needed } } ``` ## Use the SwiftUI View in Your App Finally, use the `MatrixScanPickRepresentable` in your SwiftUI app: ```swift import SwiftUI @main struct MyApp: App { var body: some Scene { WindowGroup { MatrixScanPickRepresentable() } } } ``` Or within another SwiftUI view: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanPickRepresentable() .navigationTitle("MatrixScan Pick") } } } ``` ## Alternative: Using UIViewRepresentable As an alternative to wrapping a `UIViewController`, you can implement the MatrixScan Pick functionality directly using `UIViewRepresentable`. This approach uses a `Coordinator` to hold the SDK objects, ensuring they are created once and persist across SwiftUI updates: ```swift import ScanditBarcodeCapture import SwiftUI struct MatrixScanPickView: UIViewRepresentable { let products: Set let productMapper: ([String]) async -> [BarcodePickProductProviderCallbackItem] let onFinishButtonTapped: () -> Void func makeCoordinator() -> Coordinator { Coordinator(products: products, productMapper: productMapper, onFinishButtonTapped: onFinishButtonTapped) } func makeUIView(context: Context) -> BarcodePickView { let coordinator = context.coordinator // Configure Barcode Pick view settings let viewSettings = BarcodePickViewSettings() // ... // Create the Barcode Pick view let barcodePickView = BarcodePickView(frame: .zero, context: coordinator.dataCaptureContext, barcodePick: coordinator.barcodePick, settings: viewSettings) barcodePickView.uiDelegate = coordinator barcodePickView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // Start the pick view barcodePickView.start() return barcodePickView } func updateUIView(_ uiView: BarcodePickView, context: Context) { context.coordinator.onFinishButtonTapped = onFinishButtonTapped } static func dismantleUIView(_ uiView: BarcodePickView, coordinator: Coordinator) { uiView.stop() } class Coordinator: NSObject, BarcodePickViewUIDelegate { let dataCaptureContext: DataCaptureContext let barcodePick: BarcodePick private let providerDelegate: ProviderDelegate var onFinishButtonTapped: () -> Void init(products: Set, productMapper: @escaping ([String]) async -> [BarcodePickProductProviderCallbackItem], onFinishButtonTapped: @escaping () -> Void) { // Create the data capture context DataCaptureContext.initialize(licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --") dataCaptureContext = DataCaptureContext.shared self.onFinishButtonTapped = onFinishButtonTapped // Configure Barcode Pick settings let settings = BarcodePickSettings() // ... // Create product provider providerDelegate = ProviderDelegate(productMapper: productMapper) let productProvider = BarcodePickAsyncMapperProductProvider(products: products, providerDelegate: providerDelegate) // Create Barcode Pick mode barcodePick = BarcodePick(context: dataCaptureContext, settings: settings, productProvider: productProvider) super.init() } func barcodePickViewDidTapFinishButton(_ view: BarcodePickView) { onFinishButtonTapped() } } } private class ProviderDelegate: NSObject, BarcodePickAsyncMapperProductProviderDelegate { let productMapper: ([String]) async -> [BarcodePickProductProviderCallbackItem] init(productMapper: @escaping ([String]) async -> [BarcodePickProductProviderCallbackItem]) { self.productMapper = productMapper super.init() } func mapItems(_ items: [String], completionHandler: @escaping ([BarcodePickProductProviderCallbackItem]) -> Void) { Task { let result = await productMapper(items) completionHandler(result) } } } ``` You can then use this view directly in your SwiftUI app: ```swift struct ContentView: View { var body: some View { NavigationView { MatrixScanPickView( products: productsToPick, productMapper: { items in // Map scanned items to products // ... return [] }, onFinishButtonTapped: { // Handle finish button tap } ) .navigationTitle("MatrixScan Pick") } } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Pick to your application. Implementing MatrixScan Pick involves two primary elements: - Barcode Pick: The data capture mode that is used for scan and pick functionality. - A Barcode Pick View: The pre-built UI elements used to highlight items to be picked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Pick Mode - Setup the Barcode Pick View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Configure the Barcode Pick Mode The main entry point for the Barcode Pick Mode is the `BarcodePick` object. You can configure the supported Symbologies through its [`BarcodePickSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-pick-settings.html), and set up the list of items that you want MatrixScan Pick to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```swift let settings = BarcodePickSettings() settings.set(symbology: .ean13UPCA, enabled: true) ``` Sound and haptic feedback are also configured on `BarcodePickSettings` (not on the view settings) — both are on by default: ```swift settings.isSoundEnabled = false // mute the beep settings.isHapticsEnabled = false // mute the vibration ``` Then you have to create the product provider for the Barcode Pick mode. This provider is responsible for providing the items that should be highlighted in the AR view. Note that in this example we are using a hardcoded list of items, but in a real-world scenario, you would fetch this list from your backend. ```swift let productDatabase: [ProductDatabaseEntry] = [ .init( identifier: "product_1", quantity: 2, items: [ "9783598215438", "9783598215414", "9783598215441", "9783598215412" ]), .init( identifier: "product_2", quantity: 3, items: [ "9783598215471", "9783598215481", "9783598215458", "9783598215498", "9783598215421" ]) ] var products: Set = [] productDatabase.forEach { entry in products.insert(.init(identifier: entry.identifier, quantityToPick: entry.quantity)) } let productProvider = BarcodePickAsyncMapperProductProvider(products: products, providerDelegate: self) ``` And the product provider delegate: ```swift extension ViewController: BarcodePickAsyncMapperProductProviderDelegate { func mapItems(_ items: [String], completionHandler: @escaping ([BarcodePickProductProviderCallbackItem]) -> Void) { var result: [BarcodePickProductProviderCallbackItem] = [] // Use the scanned items list to retrieve the identifier of the product they belong to. // This should be an async query in real world scenarios if there are a lot of products/items to loop. items.forEach { item in if let product = productDatabase.first(where: { entry in entry.items.contains(item) }) { result.append(.init(itemData: item, productIdentifier: product.identifier)) } } completionHandler(result) } } ``` Then create the mode with the previously created settings: ```swift let mode = BarcodePick(context: context, settings: settings, productProvider: productProvider) ``` ## Setup the `BarcodePickView` MatrixScan Pick’s built-in AR user interface includes buttons and overlays that guide the user through the scan and pick process. By adding a [`BarcodePickView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-pick-view.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickView), the scanning interface is added automatically to your application. The `BarcodePickView` appearance can be customized through [`BarcodePickViewSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/barcode-pick-view-settings.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickViewSettings) to match your application’s look and feel. The following settings can be customized: * Colors of dots in augmented reality overlay * Guidelines text * Showing hints * Finish button * Pause button * Zoom button * Loading Dialog ```swift let viewSettings = BarcodePickViewSettings() // setup the desired appearance settings by updating the fields in the object above ``` Next, create a `BarcodePickView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodePickView` is automatically added to the provided parent view. ```swift let barcodePickView = BarcodePickView(frame: view.bounds, context: context, barcodePick: mode, settings: viewSettings) ``` Connect the `BarcodePickView` to the iOS view controller lifecycle. Call `start()` in [`viewWillAppear`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621510-viewwillappear), `pause()` in [`viewWillDisappear`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621504-viewwilldisappear), and `stop()` only when `isMovingFromParent` is `true` — so the camera is released when the screen is truly being popped, not just covered by another view. ```swift override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) barcodePickView.start() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) barcodePickView.pause() if isMovingFromParent { barcodePickView.stop() } } ``` And the BarcodePickViewUIDelegate: ```swift extension ViewController: BarcodePickViewUIDelegate { func barcodePickViewDidTapFinishButton(_ view: BarcodePickView) { // Handle the user tapping the finish button — pop, dismiss, present a summary, etc. // The right call depends on how this screen was presented. } } ``` ## BarcodePickAction Listener `BarcodePick` does not auto-finalize a pick. When the user taps a code, the SDK calls your [`BarcodePickActionListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-pick-action-listener.html) and waits for `completionHandler(true)` before transitioning the highlight to "picked". This indirection is what lets you validate against a backend (stock check, task assignment) before committing the action. This listener is required. ```swift extension ViewController: BarcodePickActionListener { func didPickItem(withData data: String, completionHandler: @escaping (Bool) -> Void) { // Perform any checks (e.g. backend validation) and invoke completionHandler(true) // to confirm the pick, or completionHandler(false) to reject it. completionHandler(true) } func didUnpickItem(withData data: String, completionHandler: @escaping (Bool) -> Void) { // Same contract for un-picking — call completionHandler(true) to confirm. completionHandler(true) } } ``` Register it on the view: ```swift barcodePickView.addActionListener(self) ``` ## Register the Scanning Listener Register a [`BarcodePickScanningListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-pick-scanning-listener.html#interface-scandit.datacapture.barcode.pick.IBarcodePickScanningListener) on the mode to be notified every time the pick state changes. The session object contains the list of picked and scanned items. ```swift extension ViewController: BarcodePickScanningListener { func barcodePick(_ barcodePick: BarcodePick, didUpdate scanningSession: BarcodePickScanningSession) { // Invoked on a background thread every time the picked state of an item changes. // The session object contains the list of picked and scanned items. } func barcodePick(_ barcodePick: BarcodePick, didComplete scanningSession: BarcodePickScanningSession) { // Invoked when all the registered items needing picking have been picked. } } ``` Register it on the mode: ```swift barcodePick.addScanningListener(self) ``` --- ## About MatrixScan Pick # About MatrixScan Pick MatrixScan Pick is a pre-built UI that uses augmented reality overlays to highlight specific items that need to be picked. Whereas MatrixScan AR is fully customizable, MatrixScan Pick is a pre-built solution that allows you to add a scan and pick experience with augmented reality to an existing native app, with just a few lines of code. MatrixScan Pick is implemented through functionality provided by [`BarcodePick`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/barcode-pick.html). ## UI Overview * MatrixScan Pick is inspired by the familiar paradigm of a camera, including a shutter button that the user operates in order start and pause the scanning view. The Finish button is used at any time to exit the workflow. * It highlights items with obvious and colorful visual dots on screen. * When paused, MatrixScan Pick freezes the display at the last view, even if the device is moved. The Play button transitions back to the live view. * Textual guidance is displayed from the beginning of the session and as the workflow progresses, informing of the user of changes in item status (i.e. Detected, Ignored, To-Pick, or Picked). * Status icons can be defined to provide further information to users for a given barcode. In the live view, the icons are displayed but not tappable. In the frozen view, the status icons can be tapped and expanded to provide additional textual information. * The Quick Start Guide takes you through the process to install the full UI. However, you can then customize it by choosing to remove any elements on the screen except for the AR overlays. This allows you to create custom UIs suitable for your own workflows. ## Supported Symbologies MatrixScan Find supports all [symbologies](../barcode-symbologies.mdx) **except** DotCode, MaxiCode and postal codes (KIX, RM4SCC). If you are not familiar with the symbologies that are relevant for your use case, you can use capture presets that are tailored for different verticals (e.g. retail, logistics, etc.). --- ## Get Started # Get Started The parser parses data strings, e.g. as found in barcodes, into a set of key-value mappings. In this guide, you will know briefly how to use a parser and what types of parser are currently supported by Scandit. These data formats are supported: [Health Industry Bar Code (HIBC)](https://docs.scandit.com/data-capture-sdk/ios/parser/hibc.html), [GS1 Application Identifier system](https://docs.scandit.com/data-capture-sdk/ios/parser/gs1ai.html) and [Swiss QR Codes](https://docs.scandit.com/data-capture-sdk/ios/parser/swissqr.html), [VIN Vehicle Identification Number](https://docs.scandit.com/data-capture-sdk/ios/parser/vin.html), [IATA Bar Coded Boarding Pass (BCBP)](https://docs.scandit.com/data-capture-sdk/ios/parser/iata-bcbp.html), [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/ios/parser/epc.html). More data formats will be added in future releases. Please contact us if the data format you are using is not yet supported, or you want to use the parser on a currently unsupported platform. ## Format-Specific Documentation - [Supported Data Formats](https://docs.scandit.com/data-capture-sdk/ios/parser/formats.html) - [HIBC](https://docs.scandit.com/data-capture-sdk/ios/parser/hibc.html) - [GS1 AI](https://docs.scandit.com/data-capture-sdk/ios/parser/gs1ai.html) - [GS1 Digital Link](https://docs.scandit.com/data-capture-sdk/ios/parser/gs1-digital-link.html) - [Swiss QR](https://docs.scandit.com/data-capture-sdk/ios/parser/swissqr.html) - [VIN](https://docs.scandit.com/data-capture-sdk/ios/parser/vin.html) - [IATA BCBP](https://docs.scandit.com/data-capture-sdk/ios/parser/iata-bcbp.html) - [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/ios/parser/epc.html) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: First of all, include the ScanditParser library and its dependencies to your project, if any. ### Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### New Features #### Barcode * MatrixScan Sequence: Introduced several new configurations to adapt the sequencing flow: - Configure the duration of the idle timeout. - Toggle the per-row tray indicator label (e.g. "Row 1") through `shouldShowTrayIndicatorText` on the `BarcodeSequenceView`. * Added a new standalone iOS Price Capture sample (`PriceCaptureSample`) demonstrating a (barcode, price) pair captured from a shelf price label in one shot using Smart Label Capture's pre-built Price Capture definition, validated against a bundled CSV reference database, with fields highlighted by color brushes — green (correct), red (incorrect), grey (unknown) — and the whole-label outline hidden. * Added group scanning to MatrixScan Count, enabled via `BarcodeCountSettings`. Group scanning lets users count items in distinct groups, for example one pallet or delivery at a time, within a single session. Three controls manage the flow: Next group saves the current group's scans and clears its AR highlights so the next group starts on a clean screen; Redo clears the scans for the current group only, leaving already-completed groups untouched; Finish ends the session. * Added `BarcodeCountSettings.ExpectedNumberOfBarcodesPerCluster` to MatrixScan Count to declare how many barcodes each cluster should contain (for example, 2 for labels carrying two barcodes). Any cluster that deviates from the expected count is flagged and highlighted with a default yellow brush (overridable). * Added support for `ScanditIcon` in MatrixScan Count highlights. * MatrixScan Count now offers Scan Preview, a new option that previews which barcodes will be scanned and tracks reliably across large, complex setups. Highlights appear in real time before capture, so users can position themselves for the best result. They stay anchored to their barcodes across wide areas, deep stacks, and items at varied angles and depths. Scan Preview is best suited to large surfaces or irregularly arranged groups. For standard counting on a single flat surface, the default mode remains the recommended choice. Enable via BarcodeCountSettings(scanPreviewEnabled: true) * Added support for `ScanditIcon` in MatrixScan Count Scan Preview highlights. * Added the SelectionMode API to replace the SparkScan target-mode APIs and `ScanIntention.smartSelection`: Set `selectionMode` (off/on/auto) in the `BarcodeCaptureSettings` and `SparkScanSettings` to control whether an aimed-at barcode is scanned automatically or requires explicit selection. * Added `logoStyle` and `logoAnchor` customization properties to `BarcodeArView`, `BarcodeCountView`, `BarcodeFindView`, `BarcodePickView`, and `BarcodeSequenceView`. #### Id * Added Irish Garda Age Card as `RegionSpecificSubtype.IrelandAgeCard`. * Added a new `PassportType` property to `MrzResult`. * Added double-sided support for the Oman residence card. * Added single-sided support for extraction of issue date and birth date from the 2025 NYC Municipal ID. * Added `ReadID_UI` and `ScanditIdCaptureNfc.xcframework` to support NFC document capture. #### Smart Label Capture * Extended VIN label capture to also scan Code 128 barcodes (in addition to QR, Code 39, and Data Matrix) via `createVinLabelDefinition()`. * Extended LabelCapture to accept label definitions where both "barcode" and "text" field types use the "semantics" feature simultaneously; previously this was restricted to only one field type at a time. ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Smart Label Capture * Improved Receipt Scanning efficiency by optimizing receipt image processing before extraction. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. * Updated `SymbologyDescription.forIdentifier` to return `null` for unrecognized identifiers (e.g. `"EAN-8"` instead of `"ean8"`); previously such input was silently mapped to `Codabar`. #### Id * Updated iOS to Read ID 4.126.0. ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in item-based scanning. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Id * Fixed an issue where cropped document images were rotated when Frame Image was also enabled. * Corrected the orientation of cropped Visa document images that were being rotated incorrectly when scanned using a single-frame image source. * Fixed parser handling of non-standard Surrey BC AAMVA barcodes that were incorrectly returning "Invalid Format". #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed a thread-safety race in `SDCDataCaptureContext` that could cause an `NSGenericException` when scanning modes were added or removed from multiple threads concurrently; `_modes`/`activeMode` access is now serialized through a mutex. * Fixed an iOS camera issue where CVPixelBuffer read locks could leak on every frame for planar (YUV) buffers, eventually starving the buffer pool and stalling frame delivery. * Fixed a crash when the `DataCaptureContext` singleton was initialized more than once. ### Deprecations #### Barcode * The SparkScan target-mode APIs and `ScanIntention.smartSelection` are deprecated in favour of selectionMode. * Added `ScanditIcon` support for `BarcodeCount` status mode highlights, and deprecated the `SDCBarcodeCountStatus`-based highlight API. ## 8.4.1 **Released**: June 23, 2026 ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in SparkScan when using the item-based API. #### Id * Fixed an issue where cropped document images were rotated when they are recovered using the getFrame API. * Resolved a duplicate Objective-C class registration that could trigger spurious casting failures or crashes when an app links both ScanditCaptureCore and ScanditIdCapture. ## 8.4.0 **Released**: May 18, 2026 ### New Features #### Barcode * Added an Error entry to `BarcodeSequenceState`, triggered when the sequencing process encounters an error. * Added `dotRadius` property to `BarcodeBatchBasicOverlay` to allow customizing the size of dots when using the Dot overlay style. * Added `shouldShowShutterButton` flag in `BarcodeSequenceView` to hide the main shutter button and blinking indicator; added `BarcodeSequenceView::startSequencing()` and `BarcodeSequenceView::pauseSequencing()` (iOS) / `BarcodeSequenceView::stopSequencing()` (Android) to programmatically replicate the shutter button behavior; exposed `BarcodeSequenceState` enum and `BarcodeSequenceViewUIListener::onStateChanged` to be notified when a state change occurs; exposed `BarcodeSequenceView::state` to retrieve the current state; exposed `BarcodeSequenceView::sequencedShelfModule` to retrieve the scanned shelf module. #### Id * Added support for reading the vehicle table on the back of New Zealand driving licences, with the latest expiry date returned; supported vehicle classes are 1–6, including L=learner and R=restricted variants. * Added support for new versions of USA, California – Driver's License; USA, North Carolina – Driver's License; USA, Texas – Driver's License; and USA, Oklahoma – Driver's License. #### Smart Label Capture * Added a Swift extension for `LabelDateResult` to improve ergonomics when using Swift.. #### Core * Redesigned `ZoomSwitchControl` to support multiple configurable zoom levels; the control now displays as a compact button that expands to show all available zoom levels, automatically filtered to those supported by the device hardware. * Added a new `PinchToZoom` gesture. * Introduced a new `ZoomListener` on the Camera object. ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. #### Core * Updated mbedtls from version 3.6.5 to 3.6.6. ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. * Fixed an issue where `BarcodeCountView` would display incorrectly after rotating the device when a sibling view was present in the same parent view. * Fixed an unnecessary second scan callback that occurs after freezing barcode recognition. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed an issue where the Smart Scan Selection aimer would become too small when scan-area margins restricted the visible scan area; the aimer is now sized relative to the view, keeping a consistent on-screen size regardless of margins. #### Id * Fixed an issue where the US Permanent Residence Card was not processed through the VizMrz flow. * Fixed an issue where AAMVA verification was being performed even when no AAMVA document types were enabled in the accepted documents. #### Smart Label Capture * Fixed a memory leak in LabelCapture * Fixed an issue where the validation flow viewfinder was not displayed. * Fixed a race condition in the validation flow. * Fixed a bug where the label capture validation flow overlay sometimes did not reflect label capture settings when reused. * Fixed a bug that caused error messages in `DataCaptureView` to be rendered partially out-of-view. * Fixed a rare race condition in Label Capture. * Added `.asDate()` support to `ExpiryDate` and `PackingDate` label fields when the text is provided as manual input or as an Adaptive-Recognition-Engine response. * Fixed a bug where the receipt scanning overlay and validation flow overlay could not be used on the same LabelCapture mode instance. #### Core * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ### Deprecations #### Core * Added `zoomLevels` property to `CameraSettings` and deprecated `zoomGestureZoomFactor`. * Deprecated `ZoomSwitchControlListener` and the `addListener`/`removeListener` methods on `ZoomSwitchControl`; use `ZoomListener` on Camera instead. * Deprecated the image-based APIs for `ZoomSwitchControl`. ## 8.3.1 **Released**: April 14, 2026 ### New Features #### Barcode * Added `shouldShowShutterButton` flag in `BarcodeSequenceView` to hide the main shutter button and blinking indicator; added `BarcodeSequenceView::startSequencing()` and `BarcodeSequenceView::pauseSequencing()` to programmatically replicate the shutter button behavior; exposed `BarcodeSequenceState` enum as well as `BarcodeSequenceViewUIListener::onStateChanged` to be notified when a state change occurs; exposed `BarcodeSequenceView::state` to retrieve the current state; exposed `BarcodeSequenceView::sequencedShelfModule` to retrieve the scanned shelf module. ### Bug Fixes #### Barcode * Removed the ARKit framework import to prevent App Store submission rejections #### Smart Label Capture * Fixed the validation flow to accept dates in more formats when manually entered * Fixed a race condition in the validation flow ## 8.3.0 **Released**: March 26, 2026 ### New Features #### Barcode * Added support for composite codes in SparkScan * Added PDF417 barcode generation support with configurable options like error correction level, compaction mode, and dimensions through the new `Pdf417BarcodeGeneratorBuilder`. #### Id * Added support for OCR scanning of the 2026 version of Victoria mobile driver licenses * Added IdCaptureSettings.anonymizeDefaultFields setting that controls whether the SDK applies default anonymization rules for specific document types and regions * US, EU/ Schengen + UK passports no longer fallback to MRZ only. Now, US, EU/ Schengen + UK passports must capture VIZ instead of returning MRZ values after the configurable timeout has elapsed. This applies to FullDocumentScanner or SingleSideScanner when both VIZ and MRZ zones are enabled. #### Smart Label Capture * Fixed a rare race condition ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Improved speed of MatrixScan Count scanning phase for mid- and high-end devices ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. #### Id * Fixed BarcodeDictionary anonymization setting for iOS and Web * Fixed support for UAE Esaad card * Sanitized name fields on ACT driver license to split FullName and populate first and last name properties * Added support for scanning MRZ from the back of Argentinian DN when using `FullDocumentScanner` * Fixed misplaced MRZ anonymization on FullFrame images. #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.2.1 **Released**: March 5, 2026 ### Bug Fixes #### Id * Sanitized name fields on ACT DL. Splits FullName to populate first and last name properties #### Smart Label Capture * Fixed a rare race condition ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Barcode * Added access to closeUp and farAway annotations in MatrixScan AR #### Id * Enabled scanning of MRZ on the backside of several EU residence permits * Added extraction of a cropped document image from Passports and VISAs that do not support VIZ extraction * Added extraction of the date of birth from Romanian IDs #### Smart Label Capture * The Validation Flow, our ready‑to‑use workflow in Smart Label Capture for capturing and validating label data with minimal code, now features a completely redesigned user interface. The update improves ergonomics through a simplified API and highly requested customization options, making Smart Label Capture more intuitive and significantly reducing integration and customization effort across a wider range of use cases * Added LabelCapture Validation Flow Manual input delegate, that allows the developer to receive a callback when the users trigger the manual input. #### Core * Added a third standby stage to the iOS camera that turns everything off for improved power management ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes * Barcode Generator: Improved DataMatrix encoding efficiency, which depending on input data may result in smaller generated codes ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed BarcodeCount Scan Preview issues including: fixed an issue where preview barcodes were used to populate the scanning list, the correct feedback is played when a barcode not in list is scanned, fixed an issue where scanning was not possible after the app was put in background, and corrected highlight orientation in landscape * Fixed an issue where MatrixScan AR circle highlights stopped pulsing when the app was restored from the background * Added cameraStateOnStop property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed the missing found item icon in the MatrixScan Find carousel #### Id * Treated Puerto Rico driver licenses as AAMVA to enforce barcode capture with FullScanner * Fixed a bug that would cause Canada Northwest Territories driver license scans to be incomplete #### Core * Fixed an issue where the interface and video feed could have different visual orientations * Fixed an issue where some LabelCapture fields were being returned incorrectly on TS frameworks ### Deprecations #### Smart Label Capture * Deprecated some LabelCaptureValidationFlowSetting APIs: requiredFieldErrorText, missingFieldsHintText, manualInputButtonText, as those don't make sense anymore with the redesign of Validation Flow in 8.2 ## 8.1.5 **Released**: June 10, 2026 ### New Features #### Barcode * Added `shouldShowTrayIndicatorText` to `BarcodeSequenceView` to toggle the per-row tray indicator label (e.g. "Row 1"). * Added an option to configure the duration of BarcodeSequence's idle timeout. ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in item-based scanning. #### Smart Label Capture * Fixed a memory leak in LabelCapture. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. #### Core * Fixed a rare issue that was causing a crash when the app moved to the background. ## 8.1.3 **Released**: March 25, 2026 ### New Features #### Barcode * Added `shouldShowShutterButton` flag in `BarcodeSequenceView` to hide the main shutter button and blinking indicator; added `BarcodeSequenceView::startSequencing()` and `BarcodeSequenceView::pauseSequencing()` to programmatically replicate the shutter button behavior; exposed `BarcodeSequenceState` enum as well as `BarcodeSequenceViewUIListener::onStateChanged` to be notified when a state change occurs; exposed `BarcodeSequenceView::state` to retrieve the current state; exposed `BarcodeSequenceView::sequencedShelfModule` to retrieve the scanned shelf module. ### Bug Fixes #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.1.2 **Released**: March 9, 2026 ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session #### Smart Label Capture * Fixed a rare race condition ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Core * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed an issue where the interface and video feed could have different visual orientations ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Smart Scan Selection is now available in Barcode Capture. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. * Added, in `BarcodeAr`, a `BarcodeArFilter` interface to selectively control which barcodes are displayed in the AR overlay based on custom filtering logic. You can set a filter via `BarcodeAr.SetBarcodeFilter`. * Added `ScanditIconType.Slash` which can be used in `BarcodeArStatusIconAnnotationAnchor`. #### Id * Added NationalityISO property that maps results from Nationality field to country ISO code * Added RejectionDiagnosticJSON property to CapturedId to report debug info during Timeout rejections * Added rejectionTimeoutSeconds to IdCaptureSettings allowing customers to use timeout other than default (6s). Minimum timeout is 1s. * Added IdCaptureLite to CocoaPods. It is identical to IdCapture but without the dependency on ScanditIDC. This reduces the app size for customers that do not require VIZ scanning capabilities * Added support for new California DL, new South Carolina DL, Arizona Medical Marijuana Card, Kuwait Civil card, and new Texas DL * Our SDK can now scan the following documents both in single-side and double-side mode: - All Mexican DLs - Mexican Voter Cards #### Smart Label Capture * It's now possible to use Swift's result builder pattern to build a `LabelDefinition` #### Core * Added support for QuadHD resolution to provide improved performance and extended range for MatrixScan modes on slower devices * Added Electronic Product Code (EPC) parser ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the [“strict" symbology extension](../symbology-properties#symbology-extension-descriptions) #### Smart Label Capture * Incremental improvements in accuracy across all use-cases for the OCR model powering Smart Label Capture. * Some Label Capture API have been refined for Swift. For example: - `CustomBarcode(name: "barcode", symbologies: [NSNumber(value: Symbology.ean13UPCA.rawValue)])` - now becomes `CustomBarcode(name: "barcode", symbologies: [.ean13UPCA])` ### Behavioral Changes #### Barcode * Enabling the [“ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 (“Missing Resource”) #### Smart Label Capture * Validation Flow: Manually input values for barcodes will go through a stricter validation. Some values may no longer be accepted if they do not match the symbology specs for the symbology’s definition ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Added the `cameraStateOnStop` property to BarcodeFindView to optimize camera transitions when switching between modes #### Id * Fixed an issue where front expiry date anonymization rectangle is erroneously drawn on front and back * Fixed a bug that prevented VizResult anonymization of the following fields: additionalAddressInformation, bloodType, employer, fathersName, issuingAuthority, maritalStatus, mothersName, placeOfBirth, profession, race, residentialStatus * Fixed a bug concerning return complete instead of cropped images on the back of EU driving licenses #### Core * Fixed a small memory leak that affected fresh install runs only * Fixed an issue where barcode scanning would permanently stop after the app returned from background, particularly when camera permission dialogs were shown during initialization ## 8.0.1 **Released**: January 14, 2026 ### New Features #### Barcode * Added, in `BarcodeAr`, a `BarcodeArFilter` interface to selectively control which barcodes are displayed in the AR overlay based on custom filtering logic. You can set a filter via `BarcodeAr.SetBarcodeFilter`. * Fixed an issue where the optional and location fields of BarcodeDefinition and TextDefinition could not be set with builder methods #### Id * Added IdCaptureLite to CocoaPods. It is identical to IdCapture but without the dependency on ScanditIDC. This reduces the app size for customers that do not require VIZ scanning capabilities ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance #### Core * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a small memory leak that affected fresh install runs only ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. #### Core * The minimum iOS version is now 14. #### Barcode * SparkScan is not limited to only barcodes anymore, but can also scan items - in other words any combinations of barcodes and text present on a target to be scanned. The feature is available in beta at the moment, please contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out. #### Smart Label Capture * We’re introducing an enhancement that makes Smart Label Capture more robust and scalable by complementing its on-device model with a larger, more capable model. When the on-device model can’t capture certain labels, the SDK automatically escalates to this enhancement to handle complex or unforeseen cases with high accuracy and reliability. This capability is currently available in `beta`. If you’re interested in trying it, please contact Scandit Support. For configuration details, see `labelDefinition.adaptiveRecognitionEngine`. #### ID * Added `ElementsToRetain` to `MobileDocumentScanner`: The set of data elements that the application intends to retain from scanned mobile documents. This information is used to set the `IntentToRetain` flag in ISO 18013-5 mdoc requests, which is required for legal compliance with data protection standards. An empty set indicates no elements will be retained, and `IntentToRetain` will be set to `false` for all fields. * ID Capture now supports full-frame anonymization. * The result of `decodeMobileDriverLicenseViz`, which is currently returned as part of the `VizResult` within `CapturedId`, will now be provided through a new field named `mobileDocumentOcr`. * Added `CapturedId::isCitizenPassport`, which indicates whether the passport was issued to a citizen of the issuing country. Returns `false` for travel documents such as refugee, stateless, or alien passports, and for any passports issued by organizations rather than states. * The following Chinese travel permits now extract VIZ + MIZ data during double-sided scanning flows: * CT - Taiwan Residents Mainland Travel Permit * W - Mainland Residents Exit-Entry Permit to and from Hong Kong and Macao * CD - Mainland Residents Entry-Exit Permit to and from Taiwan ### Behavioral Changes #### Barcode * Symbology `RM4SCC` has been renamed to `ROYAL_MAIL_4STATE`. * Changed the default highlight brush in SparkScan and Barcode Capture. #### Label * The `LabelFieldDefinition` API has been updated with the following changes: * Renamed property: `pattern` → `valueRegex`, `patterns` → `valueRegexes` * Renamed property: `dataTypePattern` → `anchorRegex`, `dataTypePatterns` → `anchorRegexes` * Our Receipt Scanning Capture feature, available in beta (contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out), has been updated to improve performance and the API: * `ReceiptScanningResult`: * Removed properties: `storeNumber`, `storeStreet`, `storeZip`, `storeState`, `storePhone`, `paymentMethod`, and `paymentCurrency`. * Added property: `storeAddress` - Full address of the store (Street Number, Street, City, State, NPA). * Renamed property: `paymentSubtotal` → `paymentPreTaxTotal` - Total balance before taxes are applied. * `ReceiptScanningLineItem`: * Removed property: `category`. * Renamed properties: `price` → `unitPrice` (Price for a single unit of the item), `total` → `totalPrice` (Total price for a specific product, quantity × unitPrice). #### ID * The configuration for the following documents has been changed as detailed below: * Australian mobile driver licenses (mDL) are now treated as normal documents, with no separate mode. * US Green Cards are now treated as residence permits. * Removed the deprecated API `DateResult::toDate`. Use `DateResult::toLocalDate` or `DateResult::toUtcDate` instead. * `fullName` now an optional field on all `IdCapture` result types and `capturedMrz` now an optional field on `MrzResult`. ### Bug Fixes #### Core * Fixed an issue where macro mode would not be maintained when resuming the app from background, causing the camera to switch unexpectedly. #### ID * Fixed a bug that could get the scanner stuck when scanning a US passport card. ### Deprecations #### Core * `VideoResolution::Auto` is now deprecated. Please use the capture mode's `recommendedCameraSettings` for the best results. #### Barcode * All previously deprecated APIs have been removed in this release. ## 7.6.7 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/ios/release-notes) --- ## Advanced Configurations # Advanced Configurations SparkScan is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are some cases where you might want to customize the behavior of SparkScan. This guide will show you how to add additional capabilities and further customize SparkScan to best fit your needs. ## Advanced Capabilities ### Hardware Button Control Allowing the end user to control the scanner with hardware buttons can be useful if your users typically wear gloves. It can also improve ergonomics in some workflows. SparkScan offers a built-in API to let you do this via [`SDCSparkScanViewSettings.isHardwareTriggerEnabled`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled). ### Trigger Error State You may want to introduce logic in your app to show an error message when scanning specific barcodes (e.g. barcodes already added to the list, barcodes from the wrong lot etc.). SparkScan offers a built-in error state you can easily set to trigger an error feedback prompt to the user. You can customize: * The text message. - The timeout of the error message: the scanner will be paused for the specified amount of time, but the user can quickly restart the scanning process by tapping the trigger button. :::tip A high timeout (>10s) typically requires the users to interact with the UI to start scanning again. This is a good choice when you want to interrupt the scanning workflow (e.g. because a wrong barcode is scanned and some actions need to be performed). A small timeout (\ SparkScanBarcodeFeedback? { guard !barcode.isRejected else { return SparkScanBarcodeErrorFeedback(message: "This code should not have been scanned", resumeCapturingDelay: 60) } return SparkScanBarcodeSuccessFeedback() } } ``` You can have different error states triggered by different logic conditions. For example you can trigger an error state when a wrong barcode is scanned, and another one when a duplicate barcode is scanned. These errors can show different colors and have different timeouts. This error state for a code that should not have been scanned. This error state for a code that has been scanned more than once. ### Reject Barcodes To prevent scanning unwanted barcodes (like those already listed or from incorrect lots), use SparkScan’s built-in error state. Setting the [SDCSparkScanBarcodeErrorFeedback.resumeCapturingDelay](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-barcode-feedback.html#property-scandit.datacapture.barcode.spark.feedback.Error.ResumeCapturingDelay) parameter to `0` allows the user to continue scanning immediately without pausing on rejected codes. ## UI Customization :::tip Please refer to [SDCSparkScanView](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) for the full list of parameters. ::: import Customization from '../../../partials/advanced/_sparkscan-customization.mdx'; #### State-Based Customization You can customize your UI dynamically by observing SparkScan view state changes. Implement [`SparkScanViewUIDelegate`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view.html?highlight=sparkscanviewuilisten#interface-scandit.datacapture.barcode.spark.ui.ISparkScanViewUiListener) to receive callbacks whenever the scanner transitions between states, then update your UI accordingly. The scanner can be in one of the following states: | State | Description | | --- | --- | | **Initial** | The view has just been created. | | **Idle** | The scanner is not running. Reached via `pauseScanning()`, closing the preview, or `triggerButtonCollapseTimeout`. | | **Inactive** | The scanner is not running. Reached after a scan or via `inactiveStateTimeout`. | | **Active** | The scanner is running. Reached via `startScanning()` or after a scan in continuous mode. | | **Error** | The scanner is not running. Reached after triggering `SparkScanBarcodeErrorFeedback`. | For example, if you have implemented a custom trigger button, you can dynamically update its label based on the current state: ```swift sparkScanView.uiDelegate = self ``` Use the delegate callback to update the button label when the state changes: ```swift private var sparkScanState: SparkScanViewState = .idle extension ViewController: SparkScanViewUIDelegate { func sparkScanView(_ sparkScanView: SparkScanView, didChange viewState: SparkScanViewState) { sparkScanState = viewState switch viewState { case .initial, .idle, .inactive: triggerButton.setTitle("START SCANNING", for: .normal) case .active: triggerButton.setTitle("STOP SCANNING", for: .normal) case .error: triggerButton.setTitle("RESUME SCANNING", for: .normal) } } } ``` In your button's action handler, use the tracked state to decide whether to start or pause scanning: ```swift @objc func triggerButtonTapped() { switch sparkScanState { case .initial, .idle, .inactive, .error: sparkScanView.startScanning() case .active: sparkScanView.pauseScanning() } } ``` ## Workflow Options This section explains all the available options to configure SparkScan to best fit your case, in case you found something that didn't work well in the default configuration (that remains our recommended option). Developers can set a combination of scanning mode, scanning behavior and camera preview behavior - defining the initial state of the scanner. This can be done by setting the default scanning mode ([SDCSparkScanViewSettings.defaultScanningMode](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.DefaultScanningMode)). This combination allows for flexible configurations to suit different scanning needs. ### Scanning Mode The scanning mode determines the programmatic presence of an aimer in the preview to help with precision scanning. | Mode | Description | | ----------- | --------------------------------------------------- | | **Default** | Generally recommended. This mode will display a small camera preview to aid with aiming. The preview size and zoom level can be adjusted as needed. User can aim easily at the intended barcode. | | **Target** | This mode will always add an aimer to the camera preview to precisely select the barcode to scan. This is recommended only when selecting among many close barcodes is the common task. | :::tip Even in the *Default* mode, SparkScan will automatically show an aimer when multiple barcodes are present in the view and no clear intention from the user to scan a single one is recorded ([`SDCSparkScanSettings.ScanIntention`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/spark-scan-settings.html#property-scandit.datacapture.barcode.spark.SparkScanSettings.ScanIntention)). Enabling the *Target* mode will simply force this "precision selection" state to be on at all time. ::: ### Scanning Behavior The scanning behavior determines how barcodes are scanned - one at a time or continuously. | Behavior | Description | | ------------------- | ---------------------------------------------------------- | | **Single scan** | Scan one barcode at a time. The user needs to trigger the scanner every time to scan a barcode. This allows for a more controlled scanning and lower battery consumption. | | **Continuous scan** | Scan barcodes consecutively. The user needs to trigger the scanner once and barcodes will be scanned without any further interaction before each scan. This allows for a smoother experience when multiple barcodes need to be scanned consecutively. | :::tip Users can enable continuous scanning by holding down the trigger button. This gesture can be disabled ([`SDCSparkScanViewSettings.isHoldToScanEnabled`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HoldToScanEnabled)). ::: ### Preview Behavior The preview behavior determines how the camera preview behaves when the scanner is not actively scanning. | Behavior | Description | | -------------- | -------------------------- | | **Default** | Preview fades away when the scanner is off. This lets the user check important information displayed by the app and reduces battery consumption. | | **Persistent** | Preview remains visible, but darkened, even when the scanner is off. This is useful for scenarios where you want to select a barcode (among many) or need to look through the preview at all times (to ensure the right scan) - especially if used in conjunction with the target mode. | --- ## Get Started With SwiftUI # Get Started With SwiftUI In this guide you will learn step-by-step how to add SparkScan to your application using SwiftUI. The general steps are: 1. **Create a UIViewController**: Implement the SparkScan logic following the main [Get Started guide](./get-started.md) 2. **Use the withSparkScan view modifier**: Apply the SparkScan view controller to your SwiftUI views 3. **Integrate into your SwiftUI app**: Use the view modifier in your SwiftUI view hierarchy The core SparkScan implementation (data capture context, settings, SparkScanView setup, etc.) remains the same as described in the main guide. ## Create a UIViewController for SparkScan To integrate the Scandit Data Capture SDK with SwiftUI, you'll need to create a `UIViewController` that handles the SparkScan functionality. This follows the same implementation as described in the main [Get Started guide](./get-started.md). Create a `SparkScanViewController` class that implements all the steps from the UIKit guide: ```swift import ScanditBarcodeCapture import UIKit class SparkScanViewController: UIViewController { private var context: DataCaptureContext! private var sparkScan: SparkScan! private var sparkScanView: SparkScanView! override func viewDidLoad() { super.viewDidLoad() setupSparkScan() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) sparkScanView.prepareScanning() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) sparkScanView.stopScanning() } func setupSparkScan() { // Follow the implementation from the Get Started guide: // 1. Create data capture context // 2. Configure the SparkScan Mode // 3. Create the SparkScan View // 4. Register the listener } } extension SparkScanViewController: SparkScanListener { func sparkScan(_ sparkScan: SparkScan, didScanIn session: SparkScanSession, frameData: FrameData?) { // Handle SparkScan results // See the main Get Started guide } } ``` ## Use the withSparkScan View Modifier SparkScan provides a convenient SwiftUI view modifier called `withSparkScan` that allows you to easily integrate SparkScan into your SwiftUI view hierarchy. Use the `withSparkScan` view modifier on any SwiftUI view, passing your SparkScan view controller instance: ```swift import SwiftUI import ScanditBarcodeCapture struct ContentView: View { @State private var sparkScanViewController = SparkScanViewController() var body: some View { VStack { Image(systemName: "barcode.viewfinder") .imageScale(.large) .foregroundStyle(.tint) Text("Scan barcodes with SparkScan") } .withSparkScan(sparkScanViewController) } } ``` ## Use SparkScan in Your SwiftUI App You can use SparkScan in your main app view: ```swift import SwiftUI import ScanditBarcodeCapture @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } } } ``` Or integrate it into more complex view hierarchies: ```swift struct MainView: View { @State private var sparkScanViewController = SparkScanViewController() var body: some View { NavigationView { TabView { ScanningView() .withSparkScan(sparkScanViewController) .tabItem { Image(systemName: "barcode.viewfinder") Text("Scan") } HistoryView() .tabItem { Image(systemName: "list.bullet") Text("History") } } .navigationTitle("SparkScan Demo") } } } struct ScanningView: View { var body: some View { VStack { Text("Point camera at barcodes") .font(.headline) .padding() Spacer() } } } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add SparkScan to your application by: - Creating a new Data Capture Context instance - Configuring the Spark Scan Mode - Creating the SparkScanView with the desired settings and binding it to the application’s lifecycle - Registering the listener to be informed when new barcodes are scanned and updating the UI accordingly ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context import DataCaptureContextIos from '../../../partials/get-started/_create-data-capture-context-ios.mdx'; ## Configure the SparkScan Mode The SparkScan Mode is configured through SparkScanSettings and allows you to register one or more listeners that are informed whenever a new barcode is scanned. For this tutorial, we will set up SparkScan for scanning EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```swift let settings = SparkScanSettings() settings.set(symbology: .ean13UPCA, enabled: true) ``` Next, create a SparkScan instance with the settings initialized in the previous step: ```swift let sparkScan = SparkScan(settings: settings) ``` ## Create the SparkScan View The SparkScan built-in user interface includes the camera preview and scanning UI elements. These guide the user through the scanning process. The [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view.html) appearance can be customized through [`SparkScanViewSettings`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view-settings.html). ```swift let viewSettings = SparkScanViewSettings() // setup the desired settings by updating the viewSettings object ``` By adding a [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view.html), the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view.html) to your view hierarchy: Construct a new [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view.html), and it is automatically added to the provided parentView: ```swift let sparkScanView = SparkScanView(parentView: view, context: context, sparkScan: sparkScan, settings: viewSettings) ``` See the [SparkScan Workflow Options](./advanced.md#workflow-options) section for more information. Additionally, make sure to call [`SDCSparkScanView.prepareScanning`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.PrepareScanning) and [`SDCSparkScanView.stopScanning`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.StopScanning) in your UIViewController’s [`viewWillAppear`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621510-viewwillappear) and [`viewWillDisappear`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621485-viewwilldisappear) callbacks, to make sure that start up time is optimal and scanning is stopped when the app is going in the background. ```swift override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) sparkScanView.prepareScanning() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) sparkScanView.stopScanning() } ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [`SDCSparkScanListener`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) protocol and register the listener to the SparkScan mode. ```swift // Register self as a listener to monitor the spark scan session. sparkScan.addListener(self) ``` [`SDCSparkScanListener.sparkScan:didScanInSession:frameData:`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/spark-scan-listener.html#method-scandit.datacapture.barcode.spark.ISparkScanListener.OnBarcodeScanned) is called when a new barcode has been scanned. This result can be retrieved from the first object in the provided barcodes list: [`SDCSparkScanSession.newlyRecognizedBarcode`](https://docs.scandit.com/data-capture-sdk/ios/barcode-capture/api/spark-scan-session.html#property-scandit.datacapture.barcode.spark.SparkScanSession.NewlyRecognizedBarcode). Please note that this list only contains one barcode entry. ```swift extension ViewController: SparkScanListener { func sparkScan(_ sparkScan: SparkScan, didScanIn session: SparkScanSession, frameData: FrameData?) { // Gather the recognized barcode let barcode = session.newlyRecognizedBarcode // This method is invoked from a recognition internal thread. // Dispatch to the main thread to update the internal barcode list. DispatchQueue.main.async { // Update the internal list and the UI with the barcode retrieved above self.latestBarcode = barcode // Handle the barcode } } } ``` --- ## About SparkScan # About SparkScan SparkScan is our pre-built smartphone scanning interface designed for high-performance barcode scanning. It fits on top of any smartphone application, providing an intuitive user interface for simple, fast and ergonomic scanning in scan-intensive workflows such as inventory management in retail, or goods receiving in logistics. SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs. ## UI Overview The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience. Two main elements compose the UI: ![SparkScan UI](/img/sparkscan/features_web.png) - **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc). - **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space. There are additional UI elements available for displaying additional scanning modes, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section. ## Workflow Description When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use. To start scanning, the user can simply tap on it. When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app). In the default configuration: - Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away. - Tapping on the trigger button or the mini preview will restart immediately the scanner. Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state. If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released. List building use case using SparkScan. The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field. But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more. ## Supported Symbologies SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx). ## AI-Powered Features SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide. --- ## Installation # Installation This page describes how to integrate the Scandit Data Capture SDK into your Linux project. The Scandit Data Capture SDK for Linux is provided as a Debian package. ## Prerequisites Before you begin, make sure you have the following prerequisites in place: * Meet the [system requirements](/sdks/web/system-requirements/#linux) * Download the Scandit SDK for Linux from the [Scandit dashboard](https://ssl.scandit.com/dashboard/sign-in) * Have a valid Scandit license key ## Installation To install the Scandit SDK, use the following command while specifying the correct version number and architecture: ```bash $ sudo dpkg -i libscandit-barcodescanner-X.Y.Z-architecture.deb ``` The architecture you need to use depends on your system: - amd64 for 64bit x86 systems - arm64 for 64bit ARM systems such as the Nvidia Jetson TX2 or the Raspberry Pi 4 or 5 For example, if using a 64bit x86 Ubuntu desktop the correct command would be: ```bash $ sudo dpkg -i libscandit-barcodescanner-5.27.1-amd64.deb ``` ## Python API The Python bindings for the Scandit SDK are located in the zip file. To use them, you need to ensure that they are located in a path that Python searches for modules. One way to achieve this is to extend the `PYTHONPATH` to also list the directory that contains `scanditsdk.py` Note that the Python bindings are provided on a best-effort basis. They aren't an officially supported product from Scandit. ## Raspberry Pi's The SDK supports the Raspberry Pi 3, 4 and 5. The camera has to support Video4Linux2 (V4L2). The following steps are required to setup V4L2: ```bash $ sudo apt-get install v4l-utils ``` Put bcm2835-v4l2 into `/etc/modules-load.d/modules.conf`. Reboot the device. ## Sample Applications All sample applications are contained the samples directory and have the following dependencies: * Camera samples: Video4Linux2 for camera access: `$ sudo apt-get install libv4l-dev` * CommandLineBarcodeScannerImageProcessingSample: SDL2 for loading images. `$ sudo apt-get install libsdl2-dev libsdl2-image-dev` * CommandLineBarcodeScannerImageProcessingSample.py: SDL2 for python3 also for image loading. `$ sudo apt-get install python3-sdl2` * CommandLineBarcodeGeneratorSample: libpng for generating the output image. `$ sudo apt-get install libpng-dev` Insert your license key to all sample source files. Compile: ```bash $ cd samples $ make ``` Execute the image processing sample: ```bash $ ./CommandLineBarcodeScannerImageProcessingSample ean13-code.png ``` Execute the camera sample: ```bash $ ./CommandLineBarcodeScannerCameraSample /dev/video0 640 480 ``` Execute the MatrixScan sample: ```bash $ ./CommandLineMatrixScanCameraSample /dev/video0 1920 1080 ``` Execute the barcode generator sample: ```bash $ ./CommandLineBarcodeGeneratorSample ``` Execute the Python image processing sample: ```bash $ python CommandLineBarcodeScannerImageProcessingSample.py ean13-code.png ``` ### Gstreamer Refer to the documentation in `samples/gstreamer/README.md`. ### OpenCV OpenCV barcode scanner samples are in `samples/opencv_py_demo` folder. These examples configure the SDK for a single image use case without any resource restrictions. * OpenCvCppSample.cpp: OpenCV C++ API sample: ``` mkdir build cd build cmake .. make ``` * OpenCvPySample.py: OpenCV Python API sample: 1. Copy ../public_api/python/scanditsdk.py locally 2. Update LD_LIBRARY_PATH variable with a path to libscanditsdk.so library, e.g. ``` export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/$USER/scanditsdk/lib ``` --- ## Scan add-on / extension codes # Scan add-on / extension codes The Scandit SDK supports add-on codes (also known as Extension Codes) for EAN-8, EAN-13, UPC-A and UPC-E codes. These codes encode additional product data like an issue number, date or price. There is a two (EAN-2/two-digit add-on) and a five digit (EAN-5/five-digit add-on) version. ![EAN13 with two digit add-on code](/img/symbologies/ean13_with_addon2.png) ![EAN13 with five digit add-on code](/img/symbologies/ean13_with_addon5.png) ## Enable add-on codes in the SDK * Enable both the main symbologies (e.g. EAN-13) and the add-on symbology (e.g. two-digit add-on) that you want to scan. * Set the number of codes to scan in a frame to 2. Accumulate scan results until two codes were scanned that fulfill the following conditions: 1. One corresponds to the main symbology 2. The other one corresponds to a symbology extension The data of the two scanned codes is then returned as two separate results. Be aware that it can happen that only the main code is found in a particular frame. Isolated extension codes are never returned as a result. ### Example Settings setup for EAN-13/UPC-A codes with a 3 or 5 digit add-on on Linux: ```c ScBarcodeScannerSettings *settings = sc_barcode_scanner_settings_new(); sc_barcode_scanner_settings_set_symbology_enabled(settings, SC_SYMBOLOGY_EAN13_UPCA, SC_TRUE); sc_barcode_scanner_settings_set_symbology_enabled(settings, SC_SYMBOLOGY_TWO_DIGIT_ADD_ON, SC_TRUE); sc_barcode_scanner_settings_set_symbology_enabled(settings, SC_SYMBOLOGY_FIVE_DIGIT_ADD_ON, SC_TRUE); sc_barcode_scanner_settings_set_max_number_of_codes_per_frame(settings, 2); ScBarcodeScanner *sc_barcode_scanner_new_with_settings(context, settings); ``` The Add-On code and the main code (EAN13/UPCA, EAN8, or UPCE) are returned as two separate codes and the result needs to be combined from the scan session. A possible implementation of the result collection can look like this: ```c ScBool addon_code_found(ScBarcodeScannerSession const *session) { ScBarcode *other_code = NULL; ScBarcode *addon_code = NULL; ScBarcodeArray *codes = sc_barcode_scanner_session_get_newly_localized_codes(session); // will contain 0 to 2 codes. uint32_t const count = sc_barcode_array_get_size(codes); for (uint32_t i = 0; i < count; i++) { ScBarcode *code = sc_barcode_array_get_item_at(codes, i); if (sc_barcode_get_symbology(code) == SC_SYMBOLOGY_TWO_DIGIT_ADD_ON || sc_barcode_get_symbology(code) == SC_SYMBOLOGY_FIVE_DIGIT_ADD_ON) { addon_code = code; } else { other_code = code; } } if (addon_code != NULL && other_code != NULL) { // concatenate or process the data using sc_barcode_get_data() return SC_TRUE; } // only a main code or no code was found return SC_FALSE; } ``` --- ## Scan composite codes # Scan composite codes Composite codes are combinations of a linear (1d) barcode and a 2d code. The linear component encodes the item’s primary identification. The 2d component describes additional data like a batch number or expiration date. The Scandit SDK version 4.14 or newer supports all GS1 Composite Codes as defined in ISO/IEC 24723:2010. The specification defines three different types; A, B and C. The 1d component of a composite A or B code can be any of the following symbologies: * EAN/UPC symbology (EAN-13, EAN-8, UPC-A, or UPC-E) * GS1-128 (Code 128) * Any member of the GS1 DataBar family Version C supports GS1-128 as the linear component only. The 2d component of a composite code is either a PDF417 or a MicroPDF417. ## Enable composite codes in the SDK * Enable all 1d symbologies required by the desired composite code type (see above). * Enable the required 2d symbology supported by the composite type (PDF417 or MicroPDF417). * Set the number of codes to scan in a frame to 2. Accumulate scan results until a 1d and a 2d code were scanned that fulfill the following conditions: 1. EAN/UPC or GS1-128 code with the composite flag set to unknown or linked or a GS1 DataBar code with the composite flag set to linked. 2. A PDF417 or MicroPDF417 code with the composite flag set to GS1_A, GS1_B or GS1_C. Concatenate the results from the linear and the 2d code into one valid GS1 encoded result. ## GS1 Composite Code A (CC-A) ![DataBar Limited Composite Code](/img/symbologies/composite_type_a.png) * Extends a linear GS1 barcode using an additional MicroPDF417 code. * Optimized to use as little space as possible. * Only a special set of MicroPDF417 column, row and error correction level combinations can be used. * Data is encoded in a special base 928 compaction mode. * Three column version has no left row address patterns. ## GS1 Composite Code B (CC-B) ![DataBar-14 Composite Code](/img/symbologies/composite_type_b.png) * Extends a linear GS1 barcode using an additional MicroPDF417 code. * A subset of the MicroPDF417 column and row combinations can be used. * Marked by the (Micro)PDF417 symbol 920 at the first position. * (Micro)PDF417 data is encoded in byte compaction mode. ## GS1 Composite Code C (CC-C) ![GS1 128 Composite Code](/img/symbologies/composite_type_c.png) * Extends a GS1-128 (Code 128) barcode using an additional PDF417 code. * Same encoding as CC-B. --- ## Configure Barcode Symbologies # Configure Barcode Symbologies Symbologies often have different properties, such as symbol count (length of the barcode) or inverted colors (printed white on black). To provide optimal performances, some properties/values are disabled by default in our SDK. You might need to scan a symbology whose properties are by default disabled. This article explains you how to enable the specific properties and which one are available per symbology. ## Setting Symbology Properties You can set the properties of a symbology using the methods of the `ScSymbologySettings` class. You can get the symbology settings of Code128 as follows: ```c ScSymbologySettings *symbology_settings = sc_barcode_scanner_settings_get_symbology_settings(settings, SC_SYMBOLOGY_CODE128) ``` Some symbologies have optional checksums. A specific checksum method can be set in the following way: ```c sc_symbology_settings_set_checksums(symbology_settings, SC_CHECKSUM_MOD_10); ``` Symbologies may also have a certain length range configured by default. The length of a barcode can be checked using the "Any Code" mode of our demo app (Apple/Play Store). A new length range can be set by the dedicated symbol count method on the ScSymbologySettings class. ```c uint16_t symbol_counts[] = { 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; sc_symbology_settings_set_active_symbol_counts(symbology_settings, symbol_counts, sizeof(symbol_counts)); ``` When working with symbologies printed white on black (default is black on white), you can set it using the dedicated inverted color method on the `ScSymbologySettings` class. ```c sc_symbology_settings_set_color_inverted_enabled(symbology_settings, SC_TRUE); ``` Symbologies may also have optional extensions/properties, as detailed in the next section. You can enforce these properties through a generic method on the `ScSymbologySettings` class. ```c sc_symbology_settings_set_extension_enabled(symbology_settings, "relaxed_sharp_quiet_zone_check", SC_TRUE); ``` Some symbologies support Optical Character Recognition (OCR) as a fallback when scanning fails. When the extension is enabled, an optional regular expression can be used to constrain results to a specific format, using the following method on the `ScSymbologySettings` class: ```c sc_symbology_settings_set_ocr_fallback_regex(symbology_settings, regex); ``` ## 1D Symbology Properties Keep the following in mind when configuring 1D symbologies: * All symbologies and all extensions are disabled by default when using the low-level API. * Color-inverted (bright bars on dark background) decoding for symbologies that support it is disabled and must be explicitly enabled. * Optional checksum digits (e.g. for interleaved 2 of 5 codes, or MSI-Plessey codes) are always returned as part of the data. | Symbology | Mandatory Checksums | Supported Optional Checksums | Default Optional Checksum | Default Symbol Count Range | Supported Symbol Count Range | Color-Inverted Codes | Extensions | Generator Support | |-------------------------------|---------------------|-----------------------------------|--------------------------------|-------------------------------------------------|------------------------------|---------------------------|------------------------------------------------------------------|-------------------| | EAN-13 / UPC-A | mod10 | | | 12 | 12 | yes | ocr_fallback, remove_leading_upca_zero, strict | yes | | EAN-8 | mod10 | | | 8 | 8 | yes | strict | no | | UPC-E | mod10 | | | 6 | 6 | yes | return_as_upca, remove_leading_upca_zero, strict | no | | Two-Digit Add-on | mod10 | | | 2 | 2 | yes | strict | no | | Five-Digit Add-on | mod10 | | | 5 | 5 | yes | strict | no | | MSI Plessey | none | mod10, mod11, mod1010, mod1110 | mod10 | 6-32 | 3-32 | no | strict | no | | Code 128 | mod103 | | | 6-40 (includes 1 checksum and 2 guard symbols) | 4-50 | yes | ocr_fallback, strip_leading_fnc11, strict | yes | | Code 11 | none | mod11 | mod11 | 7-20 (includes 0-2 checksum digits) | 3-32 | no | strict | no | | Code 25 | none | mod10 | | 7-20 | 3-32 | no | strict | no | | IATA 2 of 5 | none | mod1010 | | 7-20 | 3-32 | no | strict | no | | Matrix 2 of 5 | none | mod10 | | 7-20 | 3-32 | no | strict | no | | Code 32 | mod10 | | | 8 (plus one check digit) | 8 | no | strict | no | | Code 39 | none | mod43 | | 6-40 (includes 2 guard symbols) | 3-50 | yes | ocr_fallback, full_ascii, relaxed_sharp_quiet_zone_check, strict | yes | | Code 93 | mod47 | | | 6-40 (includes 2 checksums and 2 guard symbols) | 5-60 | no | full_ascii2, strict | no | | Codabar | none | mod16, mod11 | | 7-20 (includes 2 guard symbols) | 3-34 | no | ocr_fallback, strict, remove_delimiter_data | no | | GS1 DataBar 14 | mod10 | | | 2 (encoding 14 digits) | 2 | no | strict | no | | GS1 DataBar Expanded | mod211 | | | 1-11 (encoding 1-74 characters) | 1-11 | no | strict | no | | GS1 DataBar Limited | mod89 | | | 1 (encoding 14 digits) | 1 | no | relaxed_sharp_quiet_zone_check, strict | no | | Interleaved-Two-of-Five (ITF) | none | mod10 | | 6-40 | 4-50 | no | strict | yes | | Royal Mail 4-State | mod36 | | | 7-24 | 4-50 | no | fluorescent_orange_ink | no | | KIX | none | | | 7-24 | 7-24 | no | | no | | LAPA | none | | | 16 | 16 | no | | no | | USPS Intelligent Mail | none | | | 65 | 65 | no | | no | | UPU 4-State | none | | | 19 or 25 | 19 or 25 | no | fluorescent_orange_ink, swiss_post_decoding | no | | Australian Post 4-State | none | | | 10-41 (10 digits, 0-31 customer info characters)| 10-41 | no | one of force_table_c, force_table_n, decode_bar_states | no | | French Post | none | | | - | - | no | fluorescent_orange_ink | no | 1: Enabled by default 2: Always enabled ## 2D Symbology Properties Keep the following in mind when configuring 2D symbologies: * All symbologies and all extensions are disabled by default when using the low-level API. * Color-inverted decoding for symbologies that support it is disabled and must be explicitly enabled, except where mentioned. | Symbology | Color-Inverted Codes | Extensions | Generator Support | |---------------|---------------------------|----------------------------------------------------------|-------------------| | ArUco | yes | | no | | Aztec Code | yes | | yes | | Data Matrix | yes | strip_leading_fnc11, direct_part_marking_mode | yes | | DotCode | yes | | no | | MaxiCode | no | | no | | MicroPDF417 | no | | no | | PDF417 | no | | no | | QR Code | yes1 | strict | yes | | Micro QR Code | yes1 | | no | 1: Enabled by default. ## Symbology Extensions | Extension Name | Description | |-----------------|-------------| | full_ascii | Interprets the Code39 code data using two symbols per output character to encode all ASCII characters. | | relaxed_sharp_quiet_zone_check | Enables scanning codes that have quiet zones (white area before and after the code) that are significantly smaller than allowed by the symbology specification. Use this extension if you are having difficulties to scan codes due to quiet zone violations. However, enabling it may come at the cost of more false positives under certain circumstances. | | return_as_upca | Transforms the UPCE result into its EAN-13/UPC-A representation. | | remove_leading_upca_zero | Removes the leading zero digit from the result if the UPC-A representation extension 'return_as_upca' is enabled. | | strip_leading_fnc1 | Removes the leading FNC1 character that indicates a GS1 code. To determine whether a certain code is a GS1 code, use sc_barcode_is_gs1_data_carrier. | | direct_part_marking_mode | Use this mode to improve scan performance when reading direct part marked (DPM) Data Matrix codes. Enabling this extension comes at the cost of increased frame processing times. It is recommended to restrict the scanning area to a smaller part of the image for best performance. | | strict | Enforce strict standard adherence to eliminate false positives in blurry, irregular or damaged barcodes at the cost of reduced scan performance. | | fluorescent_orange_ink | Enables the scanning of low contrast fluorescent orange codes. Enabling this option can have a negative impact on the scan performance of other symbologies. | | force_table_c | (For Australian Post 4-State) Forces decoding of Australian Post 4-State customer information with Table C. | | force_table_n | (For Australian Post 4-State) Forces decoding of Australian Post 4-State customer information with Table N. | | decode_bar_states | (For Australian Post 4-State) Returns the error-corrected customer information bars as a string of the bar states, A for ascending, D for descending, T for tracker and F for full. | | swiss_post_decoding | Enables scanning of proprietary Swiss Post UPU 4-State symbology. | | remove_delimiter_data | Removes start and stop patterns from the result of scanning a Codabar code. | | ocr_fallback | Enables Optical Character Recognition of text as a fallback when other readers fail. For more details, refer to section "Using OCR Fallback Symbology Extension". | ## Using OCR Fallback Symbology Extension When enabled, the OCR Fallback symbology extension performs text detection and recognition next to detected codes. This extension requires Smart Scan Intention which is available in SparkScan, Barcode Capture, or through the Linux settings preset `SC_PRESET_SINGLE_CODE_HAND_HELD`. It also requires the LabelText module. OCR Fallback is triggered after 1 second of unsuccessful decoding while remaining stationary. The duration can be customized by setting the `ocr_fallback_smart_stationary_timeout` engine property with a value in milliseconds. When the scanner is configured with multiple symbologies enabled with OCR Fallback, OCR is performed for each symbology in a hard-coded sequence. As soon as a result is detected that is valid for one symbology, OCR Fallback ends and the result is returned. For some symbologies with overlapping character set and no checkum algorithms for the printed text label, this may cause unwanted results. For instance, a Code128 label may be misidentified as Code39, or vice-versa, depending on the order of execution. It is advised to configure different OCR regular expressions for each symbology when possible, so that codes are identified properly. When no OCR regular expression is configured for Code128 or Code39, results returned by OCR Fallback may only contain alpha-numerical characters to reduce false-positives. Characters detected through OCR that are non-alpha-numerical are removed from results. To scan codes containing non-alpha-numerical characters, such as spaces or dashes, it is required to configure a regular expression that matches those characters. ## Calculating Symbol Counts for Variable-Length Symbologies The length of data encoded in variable-length symbologies such as Code 128, Codabar, Code 39 etc. is measured as the number of symbols. Depending on the symbology, the symbol count includes the start and end symbol, and/or checksum characters. The following list shows how to calculate the number of symbols for each variable-length symbology. These counts can be used as the input to [`sc_symbology_settings_set_active_symbol_counts`](https://docs.scandit.com/stable/c_api/struct_sc_symbology_settings.html#a0f06eab88bee48cb45ed96af0f170d16). ### Interleaved-Two-of-Five The number of symbols corresponds to the number of digits in the code. Note that the number of digits must be even. Example: the code `“1234567890123”` has a symbol count of 14. For the active symbol count calculation, optional checksum digits are treated like normal data symbols. ### Codabar The number of symbols corresponds to the number of digits in the code, plus the start and end symbols. Example: the code `“A2334253D”` has a symbol count of 7 + 2 = 9. ### Code 11 The number of symbols corresponds to the number of digits in the code, plus one or two checksum symbols. For less than ten digits in the code, one checksum symbol is added. Two checksum symbols are added for ten or more digits in the code. Example: the code `“912-34956”` (`“912-349566”`) has a symbol count of 9 + 1 = 10. The code `“912-3495-6”` (`“912-3495-638”`) has a symbol count of 10 + 2 = 12. ### Code 128 The number of symbols depends on the encoding used (A, B or C). All encodings require a start, an end and a checksum symbol. The ASCII encoding modes (A and B) store each character in one symbol. Example: the code `“ABC123”` in mode A has a symbol count of 6 + 2 + 1 = 9. The numeric encoding mode (C) encodes pairs of digits in one symbol. Example: the code `“123456”` has a symbol count of 3 + 2 + 1 = 6. Some encoders switch modes inside the code using switch symbols to optimize the code length. In this case the exact encoding used is needed to compute the number of symbols. ### Code 93 The number of symbols corresponds to the number of characters in the code, plus the start and end symbols and 2 checksum digits. Shift characters used in “extended code93” are treated as normal data symbols. Example: the code `“ABCDE12345”` has a symbol count of 10 + 2 + 2 = 14. ### Code 39 The number of symbols corresponds to the number of characters in the code, plus the start and end symbols. Note that the start and end symbols are not included in the returned barcode data. Example: the code `“4F70050378196356D”` (`“*4F70050378196356D”`) has a symbol count of 17 + 2 = 19. ### MSI Plessey and Code 25 The number of symbols corresponds to the number of digits in the code. Example: the code `“12345674”` has a symbol count of 8. For the active symbol count calculation, optional checksum digits are treated like normal data symbols. ### GS1 DataBar 14 The symbol count corresponds to the number of finder patterns in the code. Each finder is accompanied by two data segments. ### GS1 DataBar Expanded The symbol count cannot be changed. All lengths defined by the standard are supported. ### RM4SCC The number of symbols corresponds to the number of characters in the code, including the checksum character. ### KIX The number of symbols corresponds to the number of characters in the code. ### UPU 4-State The number of symbols corresponds to the number of code words. Two lengths are supported, 19 or 25 codewords with a maximum number of error correcting codewords of 6 or 12 respectively. ### Australian Post 4-State The number of symbol corresponds to 10 digit FCC and DPID codes, and up to 31 characters representing the customer information bar states. --- ## Configure with JSON # Configure with JSON This document describes the JSON format understood by the [`sc_barcode_scanner_settings_new_from_json()`](https://docs.scandit.com/stable/c_api/struct_sc_barcode_scanner_settings.html#a12865e80efbcf01cac8bc8c749032663) function. ## JSON Format The top-level must always be a dictionary (object) containing one or more key-value pairs. In the simplest form, an empty dictionary can be passed to the function. This will return a default barcode scanner settings instance with all symbologies disabled. All other properties have their default value. In general, missing properties are left at their default value, so only the properties that need to be changed away from their default need to be specified. Key-value pairs not understood the by JSON parser are ignored as if they were not specified. The following table shows the symbology names understood by the JSON parser: Click to expand | Symbology | JSON Name (case is ignored) | |----------------------------|----------------------------------| | ArUco | aruco | | Australia Post 4State | australian-post-4state | | Aztec | aztec | | Codabar | codabar | | Code 11 | code11 | | Code 128 | code128 | | Code 32 | code32 | | Code 39 | code39 | | Code 93 | code93 | | DataBar 14 | databar | | DataBar Expanded | databar-expanded | | DataBar Limited | databar-limited | | DataMatrix | data-matrix | | DotCode | dotcode | | EAN13 / UPCA | ean13upca | | EAN8 | ean8 | | Five-Digit-Add-On | five-digit-add-on | | French Post (La Poste) | french-post | | IATA 2of5 | iata2of5 | | Interleaved 2 of 5 | itf | | KIX | kix | | LAPA 4SC | lapa4sc | | Matrix 2of5 | matrix2of5 | | MaxiCode | maxicode | | MicroPDF417 | micropdf417 | | Micro QR | microqr | | MSI-Plessey | msi-plessey | | PDF417 | pdf417 | | QR Code | qr | | Royal Mail 4State | rm4scc | | Standard 2 of 5 (Code 25) | code25 | | Two-Digit-Add-On | two-digit-add-on | | UPCE | upce | | UPU 4State | upu-4state | | USPS Intelligent Mail | usps-intelligent-mail | ## Symbology Settings By default, all symbologies are disabled. To enable a symbology, it must be listed under the `"symbologies"` key. Symbologies can either be a dictionary, or an array of symbology names: ```json { "symbologies" : [ "ean13upca", "ean8", "code128" ] } ``` When using a dictionary, further symbology options can be specified, such as extensions to enable, used checksums etc.: ```json { "symbologies" : { "code128" : true, "ean13upca" : { "extensions" : ["remove_leading_upca_zero"] }, "itf" : { "checksums" : [ "mod10" ] } } } ``` The following options are currently supported: * `enabled`: boolean indicating whether the symbology should be enabled. When using the dictionary form, `enabled` is automatically set to true. * `colorInvertedEnabled`: boolean indicating whether color-inverted codes of that symbology should be decoded. Default is false. * `activeSymbolCounts`: array of integers specifying the active symbol counts for the symbology. See [`sc_symbology_settings_set_active_symbol_counts`](https://docs.scandit.com/stable/c_api/struct_sc_symbology_settings.html#a0f06eab88bee48cb45ed96af0f170d16) for details. * `extensions`: Extensions to be enabled for the symbology. * `checksums`: List of optional checksums to use for the symbology. Depending on the symbology, some of these properties are ignored. See [Configure Barcode Symbologies](/sdks/linux/barcode-capture/configure-barcode-symbologies.md) for details. ## Code Location and Search Area To customize the search area and code location hints, you can use the `codeLocation1d`, `codeLocation2d`, `searchArea` and `codeDirectionHint` properties. ### Search Area To customize the search area, set the `searchArea` property by defining the rectangle with `x`, `y`, `width`, and `height`. ```json { "searchArea" : { "x" : 0.0, "y" : 0.0, "width" : 1.0, "height" : 0.5 } } ``` ### Code Location To customize code location 1d and code location 2d, use the `codeLocation1d` and `codeLocation2d` properties. They consist of a rectangle, the area, and a constraint. ```json { "codeLocation1d" : { "area" : {"x" : 0.0, "y" : 0.0, "width" : 1.0, "height" : 0.5 }, "constraint" : "restrict" // or "hint" } } ``` Constraint must either be `"restrict"`, or `"hint"`. ### Code Direction Hint To customize the code direction hint, use the `codeDirectionHint` property. ```json { "codeDirectionHint" : "left-to-right" } ``` The code direction hint must either be `"left-to-right"`, `"right-to-left"`, `"bottom-to-top"`, `"top-to-bottom"`, `"none"`, `"vertical"`, or `"horizontal"`. ## Additional Properties `maxNumberOfCodesPerFrame` sets the maximum number of codes per frame, see [`sc_barcode_scanner_settings_set_max_number_of_codes_per_frame()`](https://docs.scandit.com/stable/c_api/struct_sc_barcode_scanner_settings.html#a941eb7ee16744e83ef86ad14c66391cf). `codeDuplicateFilter` sets the code duplicate filter, see [`sc_barcode_scanner_settings_set_code_duplicate_filter()`](https://docs.scandit.com/stable/c_api/struct_sc_barcode_scanner_settings.html#a3b6890b17a508e4931767c1e4bbc6483). `arucoDictionaryPreset` sets the ArUco dictionary preset, see [`sc_aruco_dictionary_from_preset()`](https://docs.scandit.com/stable/c_api/struct_sc_aruco_dictionary.html#a32620469440760f6a07e09ebb9a9bb1e). --- ## Scan structured append codes # Scan structured append codes Structured append mode is a standardized mechanism for spliting message data across a sequence of codes when it wouldn't fit a single code capabilities. Since version 7.6, the Scandit SDK supports structured append mode (also known as Extension Codes) for QR, DataMatrix, Aztec, PDF417/MicroPDF417 - we have added a number of functions to `ScBarcode` API to allow querying whether given scanned code belongs to a structured append codes sequence and which place in the sequence it occupies: - `char const *sc_barcode_get_file_id(ScBarcode const *barcode)` function returns structured append sequence id which should match across all codes belonging to the same sequence. - `int32_t sc_barcode_get_segment_index(ScBarcode const *barcode)` function returns a code's absolute position within a sequence. - `int32_t sc_barcode_get_segment_count(ScBarcode const *barcode)` function returns an expected number of codes within a sequence. For more details see `include/Scandit/ScBarcode.h`. ## Enable structured append codes in the SDK There is nothing special required from the user in order to enable structured append scanning support - just enable the symbologies that you would like to scan an in case the scanned codes happen to be a structured append sequence the information would be returned via the above mentioned APIs. ### Example Given the following four QR codes ![QR structured append code #1](/img/symbologies/qr_sa_04_01.png) ![QR structured append code #2](/img/symbologies/qr_sa_04_02.png) ![QR structured append code #3](/img/symbologies/qr_sa_04_03.png) ![QR structured append code #4](/img/symbologies/qr_sa_04_04.png) Settings setup for structured append QR codes on Linux: ```c ScBarcodeScanner *scanner = sc_barcode_scanner_new(context); ScBarcodeScannerSettings *settings = sc_barcode_scanner_settings_new(); sc_barcode_scanner_settings_set_symbology_enabled(settings, SC_SYMBOLOGY_QR, SC_TRUE); ScContextStatus status = sc_barcode_scanned_apply_settings(scanner, settings); ``` The structured append codes are returned as four separate codes and they need to be combined from the scan session. A possible implementation of the result collection can look like this: ```c char const *structured_append_sequence_id = NULL; char const *structured_append_sequence[32] = {0}; int structured_append_sequence_expected_segments_count = -1; void extract_new_structured_append_codes(ScBarcodeScannerSession const *session) { ScBarcodeArray *codes = sc_barcode_scanner_session_get_newly_recognized_codes(session); // will contain 0 to 4 codes. uint32_t const count = sc_barcode_array_get_size(codes); for (uint32_t i = 0; i 0) { char *segment_data_copy = (char *)malloc(segment_data.size); memcpy(segment_data_copy, segment_data.str, segment_data.size); structured_append_sequence[segment_index] = segment_data_copy; } sc_byte_array_free(segment_data); } else if (std::strcmp(structured_append_sequence_id, code_file_id) != 0) { // found different structured append sequences break; } } else { // code does not belong to a sequence } } sc_barcode_array_release(codes); } ``` --- ## Barcode Generator # Barcode Generator The Barcode Generator is a simple API to generate barcodes directly from the Scandit SDK. The function [`sc_barcode_generator_new`](https://docs.scandit.com/stable/c_api/struct_sc_barcode_generator.html) creates a barcode generator for a sepcific symbology. The Barcode Generator supports the following formats: * Code 39 * Code 128 * EAN 13 * UPCA * ITF * QR * DataMatrix * PDF417 (SDK version >= 8.2) ## Sample A C and Python sample is provided in the Linux SDK archive: `CommandLineBarcodeGeneratorSample.c/py`. ## JSON Configuration The generator can be configured using a JSON string understood by the [`sc_barcode_generator_set_options()`](https://docs.scandit.com/stable/c_api/struct_sc_barcode_generator.html#a045a2b9474895067e8eb1610ae6c5fef) function. ### General Options * `foregroundColor`: 4-tuple of integers [r, g, b, a] with `r`, `g`, `b` and `a` being in the range [0, 255] * `backgroundColor`: 4-tuple of integers [r, g, b, a] with `r`, `g`, `b` and `a` being in the range [0, 255] ### QR Code * `errorCorrectionLevel`: string, may be `"L"` (up to 7% damage), `"M"` (up to 15% damage), `"Q"` (up to 25% damage) or `"H"` (up to 30% damage). Default correction level is `"M"`. * `versionNumber`: integer from 1 to 40, overrides desired version number. Version number is automatically chosen if not set. Barcode generation might fail if version number is too small. Example: ```json { "foregroundColor" : [ 255, 0, 0, 255 ], "backgroundColor" : [ 0, 0, 255, 255 ], "errorCorrectionLevel": "Q" } ``` ### PDF417 All settings are optional. * `errorCorrectionLevel`: integer with values 0 to 8. A higher numbers increases the error correction data in the code. * `compact`: boolean, switches from normal to a compact code layout. * `compaction`: string, values `TEXT`, `BYTE`, `NUMERIC` or `AUTO`. * `dimensions`: object, `{"minCols" : n, "maxCols" : n, "minRows" : n, "maxRows" : n}` symbol dimensions as integer. Encoding fails if incompatible dimensions are defined. Example: ```json { "errorCorrectionLevel": 3, "compact": true, "dimensions" { "minCols" : 1, "maxCols" : 3, "minRows" : 2, "maxRows" : 10 } } ``` --- ## Overview # Overview The Scandit SDK C API offers a low-level interface to the Data Capture SDK. The low-level API is the default interface on Linux but it is also available for Android and iOS. This interface is very limited compared to the Data Capture API provided in the SDKs for all platforms. It allows you to pass image data directly to the data capture modules, such as barcode scanning. The API does not include a user interface, image or stream management, or advanced camera control. On Linux a basic camera interface for Video4Linux 2 (V4L2) cameras is provided. If you are creating a mobile application for Android and/or iOS where the Scandit SDK is the only camera user, then you **should not** use the low-level API and use the Data Capture API instead. Possible scenarios requiring the low-level API include building: * An embedded system with custom camera handling. * A batch or single image processing system on an embedded system or server * A mobile application where multiple consumers (other vision frameworks) access the camera stream and therefore the camera control can not be done by the Scandit Data Capture API. ## Features The low-level API offers single and multi barcode scanning, barcode tracking (MatrixScan), barcode generation and barcode data parsing. ### Single Barcodes Scanning Scanning one barcode or one group of barcodes is the default behavior of the low-level API. Valid groups are EAN/UPC with [add-on codes](barcode-capture/add-on-codes.md) or [composite codes](barcode-capture/composite-codes.md). If you implement a hand held use-case, we recommend using the `SC_PRESET_SINGLE_CODE_HAND_HELD` barcode scanner settings preset. The single scan preset provides some of the SparkScan features on the mobile API, such as smart scan intention and OCR fallback. ### Multi Barcode Scanning and Tracking Scanning multiple barcodes in an image can be implemented in two ways; by enabling multi-scan in the barcode scanner settings (see `sc_barcode_scanner_settings_set_multi_scan_enabled`) or by using the tracking API (see `ScObjectTracker`). A license key with the `tracking` feature enabled is required for both approaches. Please [contact Scandit support](mailto:support@scandit.com) if you need such a license. Barcode tracking identifies and follows multiple codes over time. It can be used to count objects or anchor augmented reality (AR) markers on objects, similar to the functionality of MatrixScan on the mobile API. ## Low-level API Concepts ### Memory Management Rules Object represented by opaque pointers in Scandit SDK internally use reference counting. To claim ownership of an object, the reference count of the object is increased and decreased again when the object is no longer needed. When the reference count drops to zero, e.g. the object has no owners, the object is deallocated (freed). To claim ownership of an object use one of the `sc_*_retain` functions, and use `sc_*_release` when you finish using it. Some objects returned by functions are automatically owned by the caller and must be released after use, while others must be retained manually, if required. The following rules apply: * Objects created by you (using any of the `*_new` functions) must be released after use by you. * Objects returned by functions that explicitly state they transfer ownership to you, must be released after use. An examples of such a function is [`sc_barcode_scanner_session_get_newly_recognized_codes()`](https://docs.scandit.com/stable/c_api/struct_sc_barcode_scanner_session.html#a090af0487a5928ca5893baa66d94f946). * You must release objects on which you called `sc_*_retain` ### Image Coordinate System All (relative) coordinates used in the barcode scanner SDK are defined in image coordinates of the frame in memory. The origin, coordinate (0,0), is in the upper left corner. The x-direction (width) points to the right and the y-direction (height) points downwards. Be aware that the camera sensors of most devices capture images in landscape mode and the display on screen depends on the device orientation and does not necessarily correspond to the layout of the camera image in memory. Different screen coordinate systems and use-cases require mirroring and/or rotation to obtain the correct location areas or code directions in image space. The inverse transform has to be applied if the location of a recognized code should be displayed in screen space. ## Low-Level API Performance By default the Scandit SDK is optimized for real-time video streaming. In general barcodes in the image will not be decoded in every frame. Instead the engine tries to skip bad frames to meet real-time processing constraints. Single image processing use-cases, for example scanning a scanned or photographed document, require a specific setup. * Use a YUV or Grayscale image input format. RGB(A) will be converted internally. * Use an image resolution between 800x600 to 1920x1080. 1280x720 is recommended. * Make sure to have an area of at least 320x160 pixels when setting a restricted code location area for barcode localization. * Having SIMD CPU support (NEON or SSE) improves execution times. * Pre-cropping the image is not required. The SDK can find the barcodes in the image. * Pre-processing (filter, blur, binarize) the image is not recommended. Provide natural images. * Very long codes require that you setup the symbol counts that you want to scan. * Blurry decoding using your custom camera and camera lens will not perform as well as high-end iOS or Android devices. Please [contact us](mailto:support@scandit.com) if specific optimizations for your camera are desired. ### Video Streaming Use-Case The default barcode scanner settings (`SC_PRESET_NONE`) offer a balance speed to accuracy performance on frame sequences for single and multi-scan use-cases. To achieve comparable results as the high level Data Capture API, you have to create barcode specific camera control algorithms that adjust exposure and auto-focus. The `ScCamera` implementations currently provided do not implement this. The recommended input resolution is FullHD (1080p) or 4KUHD (2160p) for extra range. For scenarios where a hand held device is used to scan a single barcode in a static scene, the barcode scanner preset `SC_PRESET_SINGLE_CODE_HAND_HELD` should be set. Among other optimizations, this preset enables Smart Scan Intention, which prevents scans in the background or during fast movement. A frame sequence should only be restarted (see `sc_recognition_context_start_new_frame_sequence`) if the frame stream is discontinuous, e.g. when the camera is switched off or temporarily stopped. ### Single Image Processing Use-Case There are barcode scanner presets to improve the scan robustness. For SDK versions before 7.0, `SC_PRESET_ENABLE_SINGLE_FRAME_MODE` can be set. For SDK versions 7.1 or later `SC_PRESET_HIGH_EFFORT` should be set. These presets try to achieve the best accuracy by spending more time per frame than the default preset. The settings are optimized for high power devices or non real-time requirements. They supports single or multi-code scanning and is recommended for single image or cloud processing use-cases. Recommendations: * The recommended input resolution is FullHD (1080p) or 4KUHD (2160p). * A new frame sequence should be started for every new input image by calling `sc_recognition_context_start_new_frame_sequence`. * The input image should be uncompressed. JPEG encoded image data is often poor as it contains block artifacts. * Try to acquire images that are as sharp as possible and don't contain motion blur. * Disable the code duplicate filter in the session configuration. Despite following above recommendations your single image processing will not perform the same as a mobile app based solution. The Data Capture API on mobile uses a video stream to scan. Scanning from a single image will never perform as well as scanning from a video stream, as the probability of getting a good picture of a code is much lower with just one image. In addition, the SDK can't control the camera based on previous frames if a single image is used. Real-time adjustment of auto-focus and exposure which is optimized for barcode scanning make a significant difference. ### Multi-Threading Dynamic threading is used internally to accelerate the execution if available. The functions of the SDK library are not thread-safe. All context and scanner calls have to happen in the same thread. --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Core * Improved Python API typing in `scanditsdk` for code-location and image-layout constants, allowing direct comparisons against `CODE_LOCATION_*` and `IMAGE_LAYOUT_*` while keeping mypy checks clean. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. ### Bug Fixes #### Barcode * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Core * Fixed camera initialization failure on devices where buffer allocation fails for the multi-planar capture interface; the camera now enumerates supported capture modes via VIDIOC_QUERYCAP and falls back to single-plane capture if multi-planar buffer allocation fails. ## 8.4.1 **Released**: June 23, 2026 No updates for this framework in this release. ## 8.4.0 **Released**: May 18, 2026 ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. ### Bug Fixes #### Barcode * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. ## 8.3.1 **Released**: April 14, 2026 No updates for this framework in this release. ## 8.3.0 **Released**: March 26, 2026 ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Fixed incorrect smart scan intention setup for the barcode scanner settings preset `SC_PRESET_SINGLE_CODE_HAND_HELD` ## 8.2.1 **Released**: March 5, 2026 No updates for this framework in this release. ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Barcode * Added PDF417 barcode generation, including compact mode (`compact`), compaction selection (`compaction` with values auto/text/byte/numeric), error-correction levels 0–8 (`errorCorrectionLevel`), and optional dimension bounds ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes * Barcode Generator: Improved DataMatrix encoding efficiency, which depending on input data may result in smaller generated codes ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. ## 8.1.5 **Released**: June 10, 2026 No updates for this framework in this release. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. ## 8.1.3 **Released**: March 25, 2026 No updates for this framework in this release. ## 8.1.2 **Released**: March 9, 2026 No updates for this framework in this release. ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Barcode * Fixed a typo in the ProcessFrameResult.message function of SDK Python bindings ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the [“strict" symbology extension](../symbology-properties#symbology-extension-descriptions) ### Behavioral Changes #### Barcode * Enabling the [“ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 (“Missing Resource”) ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance ## 8.0.1 **Released**: January 14, 2026 ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. * Updated `ScProcessFrameResult` struct definition with additional detailed error information. * Modified `sc_barcode_scanner_apply_settings` to return `ScContextStatus` with detailed error information. * Added `sc_context_status_free` to public API to free `ScContextStatus` structures holding detailed error information. * Added `sc_process_frame_result_free` to public API to free `ScProcessFrameResult` structures holding detailed error information. * Modified `sc_parser_new_with_context` to take `ScContextStatus *` as the last param instead of just the `ScContextStatusFlag *`. * Improved and accelerated scanning for 1d symbologies at low resolution, in particular Code 128. ### Bug Fixes * Updated Minimum Android API Level to 24 (from 21). * Unscanned default barcode locations are no longer added as a result to the scan session. * Removed the following barcode scanner settings APIs in favor of the new max locations to process per frame APIs: * `sc_barcode_scanner_settings_get_max_number_of_codes_per_frame` (use `sc_barcode_scanner_settings_get_max_num_locations_to_process_per_frame`) * `sc_barcode_scanner_settings_set_max_number_of_codes_per_frame` (use `sc_barcode_scanner_settings_set_max_num_locations_to_process_per_frame`) * Added corresponding Python bindings: `max_num_locations_to_process_per_frame` property on `BarcodeScannerSettings` * Added barcode scanner settings option to switch from single to multi-scan scanning. Multi-scan requires a tracking license. * `sc_barcode_scanner_settings_set_multi_scan_enabled` * `sc_barcode_scanner_settings_get_multi_scan_enabled` * Python: added `BarcodeScannerSettings.multi_scan_enabled` property * Replaced Royal Mail symbology string identifier from `rm4scc` to `royal-mail-4state`. * Removed `sc_barcode_scanner_new_with_settings` API in favor of newly added `sc_barcode_scanner_new` that does not accept settings. New scanner instance must be configured by `sc_barcode_scanner_apply_settings` call. * Removed `sc_context_status_flag_get_message`. * Removed deprecated focus mode APIs: * Removed `sc_barcode_scanner_settings_get_focus_mode` and `sc_barcode_scanner_settings_set_focus_mode`. Set code direction hint to `SC_CODE_DIRECTION_NONE` for devices without auto-focus. * Python API: removed `focus_mode` property from `BarcodeScannerSettings` class * Removed `focusMode` field from barcode scanner settings JSON serialization * Removed deprecated constant `SC_SYMBOLOGY_RM4SCC` (use `SC_SYMBOLOGY_ROYAL_MAIL_4STATE` instead). * In the public API, changed all `_retain` and `_release` functions on opaque pointers to accept const pointers. ## 7.6.5 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/linux/release-notes) --- ## Sample Programs # Sample Programs This page provides a list of sample programs that demonstrate how to use the Scandit Data Capture SDK for C / Linux. All sample applications are contained the samples directory of the SDK package. ## Prerequisites Before you begin, make sure you have the following prerequisites in place for the relevant samples: ### Scanner Samples Requires Video4Linux2 for camera access, install it with: ```bash $ sudo apt-get install libv4l-dev` ``` ### Image Processing Samples If using C, requires SDL2 for loading images, install it with: ```bash $ sudo apt-get install libsdl2-dev libsdl2-image-dev ``` If using Python3, requires SDL2 for python3 also for image loading, install it with: ```bash $ sudo apt-get install python3-sdl2 ``` ### Barcode Generator Sample Requires libpng for generating the output image, install it with: ```bash $ sudo apt-get install libpng-dev ``` ### License Key You must insert your license key to all sample source files before compiling and running them. Sign up for a [free trial](https://www.scandit.com/trial/) if you don't already have a license key. ## Running the Samples To run the samples, follow these steps: 1. Open a terminal and navigate to the SDK package directory. 2. Compile the samples. ```bash $ cd samples $ make ``` 3. Execute the desired sample program, for example: ```bash $ ./CommandLineBarcodeScannerImageProcessingSample ean13-code.png ``` --- ## Installation import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Installation This guide shows you how to add the Scandit Data Capture SDK to current existing project. ## Prerequisites - The latest stable version of [Visual Studio](https://visualstudio.microsoft.com/). - A [.NET SDK](https://dotnet.microsoft.com/en-us/download/dotnet/6.0). - A .NET for Android project with target SDK version 23 (Android 6, Marshmallow) or higher. :::note ID Capture requires a minimum target SDK version of 24. ::: - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). :::tip Android devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps-no-label-capture.mdx'; ## Get a License Key 1. [Sign up](https://ssl.scandit.com/dashboard/sign-up?p=test) or [Sign in](https://ssl.scandit.com/dashboard/sign-in) to your Scandit account 2. Create a project 3. Create a license key If you have a paid subscription, please reach out to [Scandit Support](mailto:support@scandit.com) if you need a new license key. ## Add the SDK The Scandit Data Capture SDK is distributed as [NuGet packages](https://www.nuget.org/packages?q=scandit). You will always need to add the `Scandit.DataCapture.Core` package, which contains the core functionality used by the other data capture packages. When developing MAUI applications you will also need to add the `Scandit.DataCapture.Core.Maui` package. In addition, depending on the data capture task, you will need a reference to: | Functionality | Description | Required Module(s) | | --- | --- | --- | | Barcode Capture | [ScanditBarcodeCapture API](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api.html) if you want to use barcode-related functionality, such as barcode capture or MatrixScan. | _com.scandit.datacapture:barcode_ | | Parser | [ScanditParser API](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/api.html) if you want to parse data strings, for instance, as found in barcodes, into a set of key-value mappings. | _com.scandit.datacapture:parser_ | | ID Capture | [ScanditIdCapture API](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api.html) if you want to scan personal identification documents, such as identity cards, passports or visas. | _com.scandit.datacapture:id_ | :::tip You can safely remove `Scandit.DataCapture.Barcode`, `Scandit.DataCapture.Parser`, or `Scandit.DataCapture.IdCapture` dependencies if you are not going to use their features. ::: ## Additional Information ### Content Providers On Android, the Scandit SDK uses content providers to initialize the scanning capabilities properly. If your own content providers depend on the Scandit SDK, choose an **initOrder** lower than 10 to make sure the SDK is ready first. If not specified, **initOrder** is zero by default and you have nothing to worry about. Check [the official `` documentation](https://developer.android.com/guide/topics/manifest/provider-element). ### Camera Permissions When using the Scandit Data Capture SDK you will want to set the camera as the frame source for various capture modes. On .NET for Android or MAUI, you have to request camera permissions in your own application before starting scanning. To see how you can achieve this, take a look at our [samples](https://github.com/Scandit/datacapture-dotnet-samples/tree/master). import OSSLicense from '../../../partials/_third-party-licenses-csharp.mdx'; --- ## Agent Skills import SkillsPage from '@site/src/components/SkillsPage'; # Agent Skills for .NET Android --- ## Configure Barcode Symbologies # Configure Barcode Symbologies import Intro from '../../../../partials/configure-symbologies/_intro.mdx' ## Enable the Symbologies You Want to Read import EnableSymbologies from '../../../../partials/configure-symbologies/_enable-symbologies.mdx' The following code shows how to enable scanning Code 128 codes for Barcode Capture: ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); settings.EnableSymbology(Symbology.Code128, true); ``` import CapturePresents from '../../../../partials/configure-symbologies/_capture-presents.mdx' ## Configure the Active Symbol Count Barcode symbologies (such as Code 128, Code 39, Code 93, or Interleaved Two of Five) can store variable-length data. For example, Code 39 can be used to store a string from 1 to 40-50 symbols. There is no fixed upper limit, though there are practical limitations to the code’s length for it to still be conveniently readable by barcode scanners. For performance reasons, the Scandit Data Capture SDK limits the [possible symbol range](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.ActiveSymbolCounts) for variable-length symbologies. If you want to read codes that are shorter/longer than the specified default range or you want to tailor your app to only read codes of a certain length, you need to change the active symbol count of the symbology to accommodate the data length you want to use in your application. The below lines of code show how to change the active symbol count for Code 128 to read codes with 6, 7 and 8 symbols. ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); SymbologySettings symbologySettings = settings.GetSymbologySettings(Symbology.Code128); HashSet activeSymbolCounts = new HashSet(new short[] { 6, 7, 8 }); symbologySettings.ActiveSymbolCounts = activeSymbolCounts; ``` import CalculateSymbolCount from '../../../../partials/configure-symbologies/_calculate-symbol-count.mdx' ## Read Bright-on-Dark Barcodes Most barcodes are printed using dark ink on a bright background. Some symbologies allow the colors to be inverted and can also be printed using bright ink on a dark background. This is not possible for all symbologies as it could lead to false reads when the symbology is not designed for this use case. See [symbology properties](../symbology-properties.mdx) to learn which symbologies allow color inversion. When you also want to read bright-on-dark codes, color-inverted reading for that symbology must also be enabled (see [SymbologySettings.ColorInvertedEnabled](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.IsColorInvertedEnabled)): ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); SymbologySettings symbologySettings = settings.GetSymbologySettings(Symbology.Code128); symbologySettings.ColorInvertedEnabled = true; ``` ## Enforce Checksums Some symbologies have a mandatory checksum that will always be enforced while others only have optional [checksums](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/checksum.html#enum-scandit.datacapture.barcode.Checksum). Enforcing an optional checksum will reduce false positives as an additional check can be performed. When enabling a checksum you have to make sure that the data of your codes contains the calculated checksum otherwise the codes get discarded as the checksum doesn’t match. All available checksums per symbology can be found in [symbology properties](../symbology-properties.mdx). You can enforce a specific checksum by setting it through [SymbologySettings.Checksums](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.Checksums): ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); SymbologySettings symbologySettings = settings.GetSymbologySettings(Symbology.Code39); symbologySettings.Checksums = Checksum.Mod43; ``` ## Enable Symbology-Specific Extensions Some symbologies allow further configuration. These configuration options are available as symbology extensions that can be enabled/disabled for each symbology individually. Some extensions affect how the data in the code is formatted, others allow for more relaxed recognition modes that are disabled by default to eliminate false reads. All available extensions per symbology and a description of what they do can be found in the documentation on [symbology properties](../symbology-properties.mdx). To enable/disable a symbology extension, use [SymbologySettings.SetExtensionEnabled()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/symbology-settings.html#method-scandit.datacapture.barcode.SymbologySettings.SetExtensionEnabled). The following code shows how to enable the full ASCII extension for Code 39. ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); SymbologySettings symbologySettings = settings.GetSymbologySettings(Symbology.Code39); symbologySettings.SetExtensionEnabled("full_ascii", true); ``` This extension allows Code 39 to encode all 128 ASCII characters instead of only the 43 characters defined in the standard. The extension is disabled by default as it can lead to false reads when enabled. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Barcode Capture to your application. The general steps are: - Creating a new Data Capture Context instance - Create your barcode capture settings and enable the barcode symbologies you want to read - Create a new barcode capture mode instance and initialize it - Register a barcode capture listener to receive scan events - Process successful scans according to your application’s needs and decide whether more codes will be scanned or the scanning process should be stopped - Obtain a camera instance and set it as the frame source on the data capture context - Display the camera preview by creating a data capture view - If displaying a preview, optionally create a new overlay and add it to data capture view for better visual feedback ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext context = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Scanning Behavior Barcode scanning is orchestrated by the [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) [data capture mode](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). This class is the main entry point for scanning barcodes. It is configured through [BarcodeCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) that will get informed whenever new codes have been recognized. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); HashSet symbologies = new HashSet() { Symbology.Code128, Symbology.Code39, Symbology.Qr, Symbology.Ean8, Symbology.Upce, Symbology.Ean13Upca }; settings.EnableSymbologies(symbologies); ``` If you are not disabling barcode capture immediately after having scanned the first code, consider setting the [BarcodeCaptureSettings.CodeDuplicateFilter](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture-settings.html#property-scandit.datacapture.barcode.BarcodeCaptureSettings.CodeDuplicateFilter) to `TimeSpan.FromMilliseconds(500)` or even `CodeDuplicate.ReportDataAndSymbologyOnlyOnce` (equivalent to `TimeSpan.FromSeconds(-1)`) if you do not want codes to be scanned more than once. Next, create a [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance with the settings initialized in the previous step: ```csharp barcodeCapture = BarcodeCapture.Create(context, settings); ``` ## Register the Barcode Capture Listener To get informed whenever a new code has been recognized, add a [IBarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) through [BarcodeCapture.AddListener()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.AddListener) and implement the listener methods to suit your application’s needs. First implement the [IBarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) interface. For example: ```csharp public void OnBarcodeScanned(BarcodeCapture barcodeCapture, BarcodeCaptureSession session, IFrameData frameData) { Barcode? barcode = session.NewlyRecognizedBarcode; // Do something with the barcode } ``` Then add the listener: ```csharp barcodeCapture.AddListener(this); ``` Alternatively to register [IBarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) interface it is possible to subscribe to corresponding events. For example: ```csharp barcodeCapture.BarcodeScanned += (object sender, BarcodeCaptureEventArgs args) => { Barcode? barcode = args.Session.NewlyRecognizedBarcode; // Do something with the barcode } ``` ### Rejecting Barcodes To prevent scanning unwanted codes, you can reject them by adding the desired logic to the `didScan` method. This will prevent the barcode from being added to the session and will not trigger the `didUpdateSession` method. The example below will only scan barcodes beginning with the digits `09` and ignore all others, using a transparent brush to distinguish a rejected barcode from a recognized one: ```csharp ... if (barcode.Data?.StartsWith("09:") == false) { this.overlay.Brush = Brush.TransparentBrush; return; } ... ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Permissions in Android](https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/permissions) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```csharp camera = Camera.GetDefaultCamera(); camera?.ApplySettingsAsync(BarcodeCapture.RecommendedCameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.SetFrameSourceAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```csharp context.SetFrameSourceAsync(camera); ``` The camera is off by default and must be turned on. This is done by calling [IFrameSource.SwitchToDesiredStateAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```csharp camera?.SwitchToDesiredStateAsync(FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```csharp DataCaptureView dataCaptureView = DataCaptureView.Create(dataCaptureContext); SetContentView(dataCaptureView); ``` Alternatively you can use a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) from XAML in your MAUI application. For example: ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); // Initialization of DataCaptureView happens on handler changed event. dataCaptureView.HandlerChanged += DataCaptureViewHandlerChanged; } private void DataCaptureViewHandlerChanged(object? sender, EventArgs e) { // Your dataCaptureView configuration goes here, e.g. add overlay } } ``` For MAUI development add [Scandit.DataCapture.Core.Maui](https://www.nuget.org/packages/Scandit.DataCapture.Core.Maui) NuGet package into your project. To visualize the results of barcode scanning, the following [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) can be added: ```csharp BarcodeCaptureOverlay overlay = BarcodeCaptureOverlay.Create(barcodeCapture, dataCaptureView); ``` ## Disabling Barcode Capture To disable barcode capture, for instance as a consequence of a barcode being recognized, set [BarcodeCapture.Enabled](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-capture.html#property-scandit.datacapture.barcode.BarcodeCapture.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## Barcode Generator is not available on .NET for Android # Barcode Generator is not available on .NET for Android The Barcode Generator module is not available for the .NET for Android SDK. To view documentation for a platform that supports Barcode Generator, use the framework switcher at the top of the page. --- ## Get Started # Get Started :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/net/android/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: In this guide you will learn step-by-step how to add Barcode Selection to your application. The general steps are: - Create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) instance, initialized with your license key. - Create a [barcode selection settings](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and choose the right configuration. - Create a new [barcode selection mode](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance and initialize it with the settings created above. - Register a [barcode selection listener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-selection-basic-overlay.html#class-scandit.datacapture.barcode.selection.ui.BarcodeSelectionBasicOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## Create the Data Capture Context The first step to add capture capabilities to your application is to create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext context = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Selection Behavior _Symbologies_ Barcode selection is orchestrated by the [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) [data capture mode](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). It is configured through [BarcodeSelectionSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) that will get informed whenever new codes have been selected. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```csharp BarcodeSelectionSettings settings = BarcodeSelectionSettings.Create(); HashSet symbologies = new HashSet() { Symbology.Qr, Symbology.Ean8, Symbology.Upce, Symbology.Ean13Upca }; settings.EnableSymbologies(symbologies); ``` _Selection Types_ The behavior of Barcode Selection can be changed by using a different [selection type](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-type.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionType). This defines the method used by [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) to select codes. Currently there are two types. If you want the user to select barcodes with a tap, then use [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection). This selection type can automatically freeze the camera preview to make the selection easier. You can configure the freezing behavior via [BarcodeSelectionTapSelection.FreezeBehavior](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.FreezeBehavior). With [BarcodeSelectionTapSelection.TapBehavior](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.TapBehavior) you can decide if a second tap on a barcode means that the barcode is unselected or if it is selected another time (increasing the counter). :::note Using [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection) requires the MatrixScan add-on. ::: If you want the selection to happen automatically based on where the user points the camera, then use [BarcodeSelectionAimerSelection](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-aimer-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAimerSelection). It is possible to choose between two different [selection strategies](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-strategy.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionStrategy). Use [BarcodeSelectionAutoSelectionStrategy](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAutoSelectionStrategy) if you want the barcodes to be selected automatically when aiming at them as soon as the intention is understood by our internal algorithms. Use [BarcodeSelectionManualSelectionStrategy](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionManualSelectionStrategy) if you want the barcodes to be selected when aiming at them and tapping anywhere on the screen. _Single Barcode Auto Detection_ If you want to automatically select a barcode when it is the only one on screen, turn on [BarcodeSelectionSettings.SingleBarcodeAutoDetection](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-settings.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionSettings.SingleBarcodeAutoDetection). _Creating the mode_ Next, create a [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance with the settings initialized in the previous step: ```csharp barcodeSelection = BarcodeSelection.Create(context, settings); ``` ## Register the Barcode Selection Listener To get informed whenever a new code has been recognized, add a [IBarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) through [BarcodeSelection.AddListener()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection.html#method-scandit.datacapture.barcode.selection.BarcodeSelection.AddListener) and implement the listener methods to suit your application’s needs. First implement the [IBarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) interface. For example: ```csharp public class MyBarcodeSelectionListener : IBarcodeSelectionListener { public void OnObservationStarted(BarcodeSelection barcodeSelection) { // Called when Barcode Selection is started. // We don't use this callback in this guide. } public void OnObservationStopped(BarcodeSelection barcodeSelection) { // Called when Barcode Selection is stopped. // We don't use this callback in this guide. } public void OnSessionUpdated( BarcodeSelection barcodeSelection, BarcodeSelectionSession session, IFrameData? frameData) { // Called every new frame. // We don't use this callback in this guide. } public void OnSelectionUpdated( BarcodeSelection barcodeSelection, BarcodeSelectionSession session, IFrameData? frameData) { IList newlySelectedBarcodes = session.NewlySelectedBarcodes; IList selectedBarcodes = session.SelectedBarcodes; IList newlyUnselectedBarcodes = session.NewlyUnselectedBarcodes; // Do something with the retrieved barcodes. } } ``` Then add the listener: ```csharp barcodeSelection.AddListener(new MyBarcodeSelectionListener()); ``` Alternatively to register [IBarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) interface it is possible to subscribe to corresponding events. For example: ```csharp barcodeSelection.SelectionUpdated += (object sender, BarcodeSelectionEventArgs args) => { IList newlySelectedBarcodes = args.Session.NewlySelectedBarcodes; IList selectedBarcodes = args.Session.SelectedBarcodes; IList newlyUnselectedBarcodes = args.Session.NewlyUnselectedBarcodes; // Do something with the retrieved barcodes. } ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Permissions in Android](https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/permissions) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```csharp var cameraSettings = BarcodeSelection.RecommendedCameraSettings; // Depending on the use case further camera settings adjustments can be made here. camera = Camera.GetDefaultCamera(); camera?.ApplySettingsAsync(cameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.SetFrameSourceAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```csharp context.SetFrameSourceAsync(camera); ``` The camera is off by default and must be turned on. This is done by calling [IFrameSource.SwitchToDesiredStateAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```csharp camera?.SwitchToDesiredStateAsync(FrameSourceState.On); ``` ## Disabling Barcode Selection To disable barcode selection, for instance when the selection is complete, set [BarcodeSelection.Enabled](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelection.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## About Barcode Selection # About Barcode Selection :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/net/android/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: Barcode Selection enables you to increase scanning accuracy and prevent users from scanning the wrong code in scenarios where there are multiple barcodes present, such as a crowded shelf, an order catalog with barcodes printed closely together, or a label with multiple barcodes. Barcode Selection provides two key capabilities: - **Aim to Select** allows users to select one code at a time. This is especially useful for one-handed operation. - **Tap to Select** is a quick way for users to select several codes from the same view. Selection is done by tapping on highlighted barcodes in the live camera preview or on a frozen screen. :::warning Barcode Selection does not support handling of duplicate codes. If a code appears twice in the visible preview both instances will be marked as selected even if only one of them was selected. ::: --- ## Advanced Configurations # Advanced Configurations There are several advanced configurations that can be used to customize the behavior of the ID Capture SDK and enable additional features. ## Configure Data Anonymization By default, data extracted from documents is anonymized according to local regulations. See [Anonymized Documents](/sdks/net/android/id-capture/supported-documents.md#anonymized-documents) for more information. That means certain data from certain fields won’t be returned, even if it’s present on a document. You control the anonymization level with the following setting: ```csharp // Default value: settings.AnonymizationMode = IdAnonymizationMode.FieldsOnly; // Sensitive data is additionally covered with black boxes on returned images: settings.AnonymizationMode = IdAnonymizationMode.FieldsAndImages; // Only images are anonymized: settings.AnonymizationMode = IdAnonymizationMode.ImagesOnly; // No anonymization: settings.AnonymizationMode = IdAnonymizationMode.None; ``` ## Document Capture Zones By default, a new instance of [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) creates a single-sided scanner type with no accepted or rejected documents. To change this, set the `Scanner` property on `IdCaptureSettings` to an [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-scanner.html) configured with either a [SingleSideScanner](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-scanner.html#single-side-scanner) or [FullDocumentScanner](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-scanner.html#full-document-scanner). The `FullDocumentScanner` extracts all document information by default. If using the `SingleSideScanner`, you can specify the document zones to extract via its constructor parameters: ```csharp // To extract data from barcodes on IDs settings.Scanner = new IdCaptureScanner(new SingleSideScanner(barcode: true, machineReadableZone: false, visualInspectionZone: false), mobileDocument: null); // To extract data from the visual inspection zone (VIZ) on IDs settings.Scanner = new IdCaptureScanner(new SingleSideScanner(barcode: false, machineReadableZone: false, visualInspectionZone: true), mobileDocument: null); // To extract data from the machine-readable zone (MRZ) on IDs settings.Scanner = new IdCaptureScanner(new SingleSideScanner(barcode: false, machineReadableZone: true, visualInspectionZone: false), mobileDocument: null); ``` ## Configure Accepted and Rejected Documents To configure the documents that should be accepted and/or rejected, set the `AcceptedDocuments` and `RejectedDocuments` properties in `IdCaptureSettings`. These properties take a list of [IIdCaptureDocument](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-document.html) instances (e.g. `Passport`, `DriverLicense`, `IdCard`) combined with the [IdCaptureRegion](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-region.html#enum-scandit.datacapture.id.IdCaptureRegion) enum to enable highly flexible document filtering. For example, to accept only US Driver Licenses: ```csharp settings.AcceptedDocuments = new List { new DriverLicense(IdCaptureRegion.Us) }; ``` Or to accept all Passports *except* those from the US: ```csharp settings.AcceptedDocuments = new List { new Passport(IdCaptureRegion.Any) }; settings.RejectedDocuments = new List { new Passport(IdCaptureRegion.Us) }; ``` ## ID Images Your use can may require that you capture and extract images of the ID document. Use the [IdImageType](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-image-type.html#enum-scandit.datacapture.id.IdImageType) enum to specify the images you want to extract from the `CapturedId` object For the full frame of the document, you can use [`setShouldPassImageTypeToResult`](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-settings.html#method-scandit.datacapture.id.IdCaptureSettings.SetShouldPassImageTypeToResult) when creating the `IdCaptureSettings` object. This will pass the image type to the result, which you can then access in the `CapturedId` object. ## Callbacks and Scanning Workflows The ID Capture Listener provides two callbacks: `onIdCaptured` and `onIdRejected`. The `onIdCaptured` callback is called when an acceptable document is successfully captured, while the `onIdRejected` callback is called when a document is captured but rejected. For a successful capture, the `onIdCaptured` callback provides a `CapturedId` object that contains the extracted information from the document. This object is specific to the type of document scanned. For example, a `CapturedId` object for a US Driver License will contain different fields than a `CapturedId` object for a Passport. For a rejected document, a [RejectionReason](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) is provided in the `onIdRejected` callback to help you understand why the document was rejected and to take appropriate action. These are: * NOT_ACCEPTED_DOCUMENT_TYPE: The document is not in the list of accepted documents. In this scenario, you could direct the user to scan a different document. * INVALID_FORMAT: The document is in the list of accepted documents, but the format is invalid. In this scenario, you could direct the user to scan the document again. * DOCUMENT_VOIDED: The document is in the list of accepted documents, but the document is voided. In this scenario, you could direct the user to scan a different document. * TIMEOUT: The document was not scanned within the specified time. In this scenario, you could direct the user to scan the document again. ## Detect Fake IDs *ID Validate* is a fake ID detection software. It currently supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). Fake ID detection can be performed automatically using the following settings: * [IdCaptureSettings.rejectForgedAamvaBarcodes](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectForgedAamvaBarcodes): Automatically rejects documents whose AAMVA barcode fails authenticity validation. * [IdCaptureSettings.rejectInconsistentData](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectInconsistentData): Automatically rejects documents whose human‑readable data does not match the data encoded in the barcode or MRZ. To enable ID validation for your subscription, please reach out to [Scandit Support](mailto:support@scandit.com). --- ## Get Started # Get Started This page will guide you through the process of adding ID Capture to your .NET application. ID Capture is a mode of the Scandit Data Capture SDK that allows you to capture and extract information from personal identification documents, such as driver's licenses, passports, and ID cards. The general steps are: - Creating a new Data Capture Context instance - Accessing a Camera - Configuring the Capture Settings - Implementing a Listener to Receive Scan Results - Setting up the Capture View and Overlay - Starting the Capture Process :::warning Using ID Capture at the same time as other modes (e.g. Barcode Capture) is not supported. ::: ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](/sdks/net/android/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import IdModuleOverview from '../../../../partials/get-started/_id-module-overview-no-eu-dl.mdx'; ## Create the Data Capture Context The first step to add capture capabilities to your application is to create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext context = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Add the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/camera.html#class-scandit.datacapture.core.Camera): ```csharp camera = Camera.GetDefaultCamera(); if (camera != null) { // Use the settings recommended by id capture. camera.ApplySettingsAsync(IdCapture.RecommendedCameraSettings); context.SetFrameSourceAsync(camera); } ``` ## Create ID Capture Settings Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scanner type and the accepted and rejected documents. Check [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) for all the available options. :::tip By default, [anonymized data](./advanced.md#configure-data-anonymization) is not returned in accordance with local regulations for specific documents. This setting can be disabled for testing purposes, but be sure to comply with local laws and requirements in production. ::: ```csharp IdCaptureSettings settings = new IdCaptureSettings { AcceptedDocuments = new List { new Passport(IdCaptureRegion.Any), new DriverLicense(IdCaptureRegion.Any), }, RejectedDocuments = new List { new IdCard(IdCaptureRegion.Any), }, }; ``` ## Implement the Listener To receive scan results, implement [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener). Capture results are delivered as a [CapturedId](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/captured-id.html#class-scandit.datacapture.id.CapturedId). This class contains data common for all kinds of personal identification documents. For more specific information, use its non-null result properties (e.g. [CapturedId.barcode](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/captured-id.html#property-scandit.datacapture.id.CapturedId.Barcode)). ```csharp public class MyListener : IIdCaptureListener { public void OnIdCaptured(IdCapture capture, CapturedId capturedId) { // The recognized fields of the captured ID can vary based on the type. if (capturedId.Mrz != null) { // Handle the information extracted from the MRZ. } else if (capturedId.Viz != null) { // Handle the information extracted from the VIZ. } else if (capturedId.Barcode != null) { // Handle the information extracted from the barcode. } } public void OnIdRejected(IdCapture capture, CapturedId? capturedId, RejectionReason reason) { // Implement to handle a document rejected by IdCapture. } } ``` Alternatively to register [IIdCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener) interface it is possible to subscribe to corresponding events. For example: ```csharp idCapture.IdCaptured += (object sender, IdCapturedEventArgs args) => { CapturedId capturedId = args.CapturedId; // The recognized fields of the captured ID can vary based on the type. if (capturedId.Mrz != null) { // Handle the information extracted from the MRZ. } else if (capturedId.Viz != null) { // Handle the information extracted from the VIZ. } else if (capturedId.Barcode != null) { // Handle the information extracted from the barcode. } }; ``` Create a new ID Capture mode with the chosen settings. Then register the listener: ```csharp idCapture = IdCapture.Create(context, settings); idCapture.AddListener(new MyListener()) ``` ## Set up Capture View and Overlay When using the built-in camera as [frameSource](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/frame-source.html#interface-scandit.datacapture.core.IFrameSource), you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```csharp DataCaptureView dataCaptureView = DataCaptureView.Create(dataCaptureContext); SetContentView(dataCaptureView); ``` Alternatively you can use a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) from XAML in your MAUI application. For example: ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); // Initialization of DataCaptureView happens on handler changed event. dataCaptureView.HandlerChanged += DataCaptureViewHandlerChanged; } private void DataCaptureViewHandlerChanged(object? sender, EventArgs e) { // Your dataCaptureView configuration goes here, e.g. add overlay } } ``` For MAUI development add the [Scandit.DataCapture.Core.Maui](https://www.nuget.org/packages/Scandit.DataCapture.Core.Maui) NuGet package into your project. Then create an instance of [IdCaptureOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) attached to the view: ```csharp overlay = IdCaptureOverlay.Create(idCapture, dataCaptureView); ``` The overlay chooses the displayed UI automatically, based on the selected [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings). If you prefer to show a different UI or to temporarily hide it, set the appropriate [IdCaptureOverlay.idLayout](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/ui/id-capture-overlay.html#property-scandit.datacapture.id.ui.IdCaptureOverlay.IdLayout). ## Start the Capture Process Finally, turn on the camera to start scanning: ```csharp camera.SwitchToDesiredStateAsync(FrameSourceState.On); ``` And this is it. You can now scan documents. --- ## About ID Capture import AboutIdCapture from '../../../../partials/intro/_about-id-capture.mdx'; --- ## Supported Documents ## ID Scanning Supported Documents Scandit ID Capture provides various [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/dotnet.android/id-capture/api/id-capture-scanner.html#id-capture-scanner) types, each designed for specific scanning workflows. These workflows can involve scanning either specific parts of a document or the entire document, including both the front and back sides. This section details the types of documents supported by each scanner type. import IdDocumentsFull from '../../../../partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from '../../../../partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents import IdValidateDocuments from '../../../../partials/advanced/_id-documents-validate.mdx'; --- ## Advanced Configurations import ValidationFlowHowItWorks from '../../../../partials/advanced/_validation-flow-how-it-works.mdx'; import ValidationFlowCustomButtons from '../../../../partials/advanced/_validation-flow-custom-buttons.mdx'; import ValidationFlowTypingHints from '../../../../partials/advanced/_validation-flow-typing-hints.mdx'; import ValidationFlowCloudVLM from '../../../../partials/advanced/_validation-flow-cloud-vlm.mdx'; import ReceiptScanning from '../../../../partials/advanced/_receipt-scanning.mdx'; import ValidationFlowRequiredOptional from '../../../../partials/advanced/_validation-flow-required-optional.mdx'; import ValidationFlowCustomToasts from '../../../../partials/advanced/_validation-flow-custom-toasts.mdx'; import ValidationFlowCustomField from '../../../../partials/advanced/_validation-flow-custom-field.mdx'; # Advanced Configurations ## Customization of the Overlays ### Basic Overlay To customize the appearance of an overlay you can implement a [ILabelCaptureBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/ui/label-capture-basic-overlay-listener.html#interface-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener) and/or [ILabelCaptureAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/ui/label-capture-advanced-overlay-listener.html) interface, depending on the overlay(s) you are using. The method [BrushForLabel()](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForLabel) is called every time a label is captured, and [BrushForField()](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForField) is called for each of its fields to determine the brush for the label or field. ```csharp public class BasicOverlayListener : ILabelCaptureBasicOverlayListener { private readonly Context context; public BasicOverlayListener(Context context) { this.context = context; } /* * Customize the appearance of the overlay for the individual fields. */ public Brush? BrushForField( LabelCaptureBasicOverlay overlay, LabelField field, CapturedLabel label) { return field.Name switch { "" => new Brush( fillColor: new Color(context.GetColor(Resource.Color.barcode_highlight)), strokeColor: new Color(context.GetColor(Resource.Color.barcode_highlight)), strokeWidth: 1f ), "" => new Brush( fillColor: new Color(context.GetColor(Resource.Color.expiry_date_highlight)), strokeColor: new Color(context.GetColor(Resource.Color.expiry_date_highlight)), strokeWidth: 1f ), _ => null }; } /* * Customize the appearance of the overlay for the full label. * In this example, we disable label overlays by returning null always. */ public Brush? BrushForLabel( LabelCaptureBasicOverlay overlay, CapturedLabel label) { return null; } public void OnLabelTapped( LabelCaptureBasicOverlay overlay, CapturedLabel label) { /* * Handle the user tap gesture on the label. */ } } // Set the listener on the overlay overlay.Listener = new BasicOverlayListener(context); ``` :::tip You can also use `LabelCaptureBasicOverlay.LabelBrush`, `LabelCaptureBasicOverlay.CapturedFieldBrush`, and `LabelCaptureBasicOverlay.PredictedFieldBrush` properties to configure the overlay if you don't need to customize the appearance based on the name or content of the fields. ::: ### Advanced Overlay For more advanced use cases, such as adding custom views or implementing Augmented Reality (AR) features, you can use the `LabelCaptureAdvancedOverlay`. The example below creates an advanced overlay, configuring it to display a styled warning message below expiry date fields when they're close to expiring, while ignoring other fields. ```csharp // Create an advanced overlay that allows for custom views to be added over detected label fields // This is the key component for implementing Augmented Reality features var advancedOverlay = LabelCaptureAdvancedOverlay.Create(labelCapture); // Add the overlay to the data capture view dataCaptureView.AddOverlay(advancedOverlay); // Configure the advanced overlay with a listener that handles AR content creation and positioning advancedOverlay.Listener = new AdvancedOverlayListener(this); public class AdvancedOverlayListener : ILabelCaptureAdvancedOverlayListener { private readonly Context context; public AdvancedOverlayListener(Context context) { this.context = context; } // This method is called when a label is detected - we return null since we're only adding AR elements to specific fields, not the entire label public View? ViewForCapturedLabel( LabelCaptureAdvancedOverlay overlay, CapturedLabel capturedLabel) { return null; } // This defines where on the detected label the AR view would be anchored public Anchor AnchorForCapturedLabel( LabelCaptureAdvancedOverlay overlay, CapturedLabel capturedLabel) { return Anchor.Center; } // This defines the offset from the anchor point for the label's AR view public PointWithUnit OffsetForCapturedLabel( LabelCaptureAdvancedOverlay overlay, CapturedLabel capturedLabel, View view) { return new PointWithUnit(0f, 0f, MeasureUnit.Pixel); } // This method is called when a field is detected in a label public View? ViewForCapturedLabelField( LabelCaptureAdvancedOverlay overlay, LabelField labelField) { // We only want to create AR elements for expiry date fields that are text-based if (labelField.Name.ToLower().Contains("expiry") && labelField.Type == LabelFieldType.Text) { // // data extraction from expiry date field and days until expiry date calculation // // Check if scanned expiry date is too close to actual date var daysUntilExpiry = CalculateDaysUntilExpiry(labelField.Text); var dayLimit = 3; if (daysUntilExpiry ```csharp // Create the validation flow overlay with the label capture mode and data capture view var validationFlowOverlay = LabelCaptureValidationFlowOverlay.Create(labelCapture, dataCaptureView); // Set the listener to receive validation events validationFlowOverlay.Listener = new ValidationFlowListener(); ``` ### Define a Listener When the user has verified that all fields are correctly captured and presses the finish button, the Validation Flow triggers a callback with the final results. To receive these results, implement the [ILabelCaptureValidationFlowListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/ui/label-capture-validation-flow-listener.html) interface: ```csharp public class ValidationFlowListener : ILabelCaptureValidationFlowListener { // This is called by the validation flow overlay when a label has been fully captured and validated public void OnValidationFlowLabelCaptured(IList fields) { string? barcodeData = null; string? expiryDate = null; foreach (var field in fields) { if (field.Name == "") { barcodeData = field.Barcode?.Data; } else if (field.Name == "") { expiryDate = field.Text; } } // Process the captured and validated data } // Called when the user manually submits a value for a field through the validation flow UI public void OnManualInputSubmitted(LabelField field, string? oldValue, string newValue) { // Handle the manual input submission, e.g. for analytics } // Called when the validation flow results are updated (for both sync and async scanning) public void OnValidationFlowResultUpdate(LabelResultUpdateType type, long asyncId, IList fields, IFrameData? frameData) { // Handle intermediate result updates during the validation flow } } ``` ```csharp var validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.Create(); validationFlowOverlaySettings.SetPlaceholderText("MM/DD/YYYY", "Expiry Date"); validationFlowOverlay.ApplySettings(validationFlowOverlaySettings); ``` ```csharp var validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.Create(); validationFlowOverlaySettings.RestartButtonText = "Borrar todo"; validationFlowOverlaySettings.PauseButtonText = "Pausar"; validationFlowOverlaySettings.FinishButtonText = "Finalizar"; validationFlowOverlay.ApplySettings(validationFlowOverlaySettings); ``` ```csharp var validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.Create(); validationFlowOverlaySettings.StandbyHintText = "No label detected, camera paused"; validationFlowOverlaySettings.ValidationHintText = "data fields collected"; // X/Y (X fields out of total Y) is shown in front of this string validationFlowOverlay.ApplySettings(validationFlowOverlaySettings); ``` ```csharp var validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.Create(); validationFlowOverlaySettings.ValidationErrorText = "Incorrect format."; validationFlowOverlaySettings.ScanningText = "Scan in progress"; validationFlowOverlaySettings.AdaptiveScanningText = "Processing"; validationFlowOverlay.ApplySettings(validationFlowOverlaySettings); ``` ```csharp private LabelCaptureSettings BuildLabelCaptureSettings() { var fields = new List(); var customBarcode = CustomBarcode.Builder() .SetSymbologies(new List { Symbology.Ean13Upca, Symbology.Gs1DatabarExpanded, Symbology.Code128 }) .Build(FIELD_BARCODE); fields.Add(customBarcode); var expiryDateText = ExpiryDateText.Builder() .SetLabelDateFormat(new LabelDateFormat(LabelDateComponentFormat.MDY, acceptPartialDates: false)) .Build(FIELD_EXPIRY_DATE); fields.Add(expiryDateText); var labelDefinition = LabelDefinition.Create(LABEL_RETAIL_ITEM, fields); labelDefinition.AdaptiveRecognitionMode = AdaptiveRecognitionMode.Auto; var settings = LabelCaptureSettings.Create(new List { labelDefinition }); return settings; } ``` See [AdaptiveRecognitionMode](https://docs.scandit.com/data-capture-sdk/net/android/label-capture/api/label-definition.html#property-scandit.datacapture.label.LabelDefinition.AdaptiveRecognitionMode) for available options. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Smart Label Capture to your application. The general steps are: - Create a new Data Capture Context instance - Configure the LabelCapture mode - Define a listener to handle captured labels - Visualize the scan process - Start the camera - Provide feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/net/android/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import LabelCaptureModuleOverview from '../../../../partials/get-started/_smart-label-capture-module-overview-dotnet.mdx'; ## Create a Data Capture Context import DataCaptureContextDotNet from '../../../../partials/get-started/_create-data-capture-context-dotnet.mdx'; ## Configure the Label Capture Mode The main entry point for the Label Capture Mode is the [LabelCapture](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/label-capture.html#class-scandit.datacapture.label.LabelCapture) object. It is configured through [LabelCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/label-capture-settings.html#class-scandit.datacapture.label.LabelCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) that get informed whenever a new frame has been processed. :::tip You can use Label Definitions provided in Smart Label Capture to set pre-built label types or define your label using pre-built fields. For more information, see the [Label Definitions](label-definitions.md) section. ::: ```csharp using Scandit.DataCapture.Label.Capture; using Scandit.DataCapture.Label.Data; using Scandit.DataCapture.Barcode.Data; // Build field definitions var fields = new List(); // Add a custom barcode field with the expected symbologies var customBarcode = CustomBarcode.Builder() .SetSymbologies(new List { Symbology.Ean13Upca, Symbology.Gs1DatabarExpanded, Symbology.Code128 }) .Build(""); fields.Add(customBarcode); // Add an expiry date text field var expiryDateText = ExpiryDateText.Builder() .SetLabelDateFormat(new LabelDateFormat(LabelDateComponentFormat.MDY, acceptPartialDates: false)) .Build(""); fields.Add(expiryDateText); // Create the label definition with the fields var labelDefinition = LabelDefinition.Create("", fields); // Create the settings with the label definition var settings = LabelCaptureSettings.Create(new List { labelDefinition }); // Create the label capture mode with the settings and data capture context var labelCapture = LabelCapture.Create(dataCaptureContext, settings); ``` ## Define a Listener to Handle Captured Labels To get informed whenever a new label has been recognized, add a [ILabelCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) through [LabelCapture.AddListener()](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/label-capture.html#method-scandit.datacapture.label.LabelCapture.AddListener) and implement the listener methods to suit your application's needs. First implement the `ILabelCaptureListener` interface. Here is an example of how to implement a listener that processes the captured labels based on the label capture settings defined above: ```csharp public class LabelCaptureRepository : ILabelCaptureListener { public void OnSessionUpdated(LabelCapture labelCapture, LabelCaptureSession session, IFrameData frameData) { /* * The session update callback is called for every processed frame. * Check if the session contains any captured labels; * if not, continue capturing. */ var labels = session.CapturedLabels; if (labels.Count > 0) { var label = labels[0]; /* * Given the label capture settings defined above, * the barcode field would always be present. */ var barcodeData = label.Fields .FirstOrDefault(field => field.Name == "") ?.Barcode?.Data; /* * The expiry date field is optional. * Check for null in your result handling. */ var expiryDate = label.Fields .FirstOrDefault(field => field.Name == "") ?.Text; /* * Disable the label capture mode after a label has been captured * to prevent it from capturing the same label multiple times. */ labelCapture.Enabled = false; /* * Consider handling the results on a background thread to avoid * blocking the main thread when processing data. */ Task.Run(() => { HandleResults(barcodeData, expiryDate); }); } } public void OnObservationStarted(LabelCapture labelCapture) { // Called when the listener is added to LabelCapture } public void OnObservationStopped(LabelCapture labelCapture) { // Called when the listener is removed from LabelCapture } private void HandleResults(string? barcodeData, string? expiryDate) { // Process the captured data } } ``` Then add the listener to the label capture instance: ```csharp var listener = new LabelCaptureRepository(); labelCapture.AddListener(listener); ``` ## Visualize the Scan Process The capture process can be visualized by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy. The view controls what UI elements such as the viewfinder, as well as the overlays that are shown to visualize captured labels. To visualize the results of Label Capture you can use two overlays: - [LabelCaptureBasicOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/ui/label-capture-basic-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureBasicOverlay) - [LabelCaptureAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/ui/label-capture-advanced-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureAdvancedOverlay) :::tip The overlays can be used independently of each other, but you can also use both at the same time as each can serve to extend the functionality of the other. ::: Here is an example of how to add a `LabelCaptureBasicOverlay` to the `DataCaptureView`: ```csharp /* * Create the data capture view and attach it to the data capture context created earlier. */ var dataCaptureView = DataCaptureView.Create(dataCaptureContext); /* * Add the data capture view to your view hierarchy */ var container = /* get your containing view here, e.g. FindViewById */; container.AddView( dataCaptureView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent) ); /* * Create the overlay with the label capture mode. */ var overlay = LabelCaptureBasicOverlay.Create(labelCapture); /* * Add the overlay to the data capture view. */ dataCaptureView.AddOverlay(overlay); /* * Optionally, set a viewfinder to guide the user. */ overlay.Viewfinder = new RectangularViewfinder(RectangularViewfinderStyle.Square); ``` :::tip See the [Advanced Configurations](advanced.md) section for more information about how to customize the appearance of the overlays and how to use the advanced overlay to display arbitrary Android views such as text views, icons or images. ::: ## Start the Camera Next, you need to create a new instance of the [Camera](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/camera.html#class-scandit.datacapture.core.Camera) class to indicate the camera to stream previews and to capture images. When initializing the camera, you can pass the recommended camera settings for Label Capture using the [LabelCapture.RecommendedCameraSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/label-capture.html#property-scandit.datacapture.label.LabelCapture.RecommendedCameraSettings) static property. ```csharp var cameraSettings = LabelCapture.RecommendedCameraSettings; var camera = Camera.GetDefaultCamera(cameraSettings); if (camera == null) { throw new InvalidOperationException("Failed to init camera!"); } dataCaptureContext.SetFrameSourceAsync(camera); ``` Once the Camera, DataCaptureContext, DataCaptureView and LabelCapture are initialized, you can switch on the camera to start capturing labels. Typically, this is done on resuming the view and when the user granted permission to use the camera, or once the user pressed continue scanning after handling a previous scan. ```csharp camera.SwitchToDesiredStateAsync(FrameSourceState.On); ``` ## Provide Feedback Smart Label Capture provides customizable feedback, emitted automatically when a label is recognized and successfully processed, configurable via [`LabelCapture.Feedback`](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/label-capture.html#property-scandit.datacapture.label.LabelCapture.Feedback). You can use the default feedback, or configure your own sound or vibration. :::tip If you already have a [Feedback](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/feedback.html#class-scandit.datacapture.core.Feedback) instance implemented in your application, remove it to avoid double feedback. ::: ```csharp // Use the default feedback (vibration and beep sound) labelCapture.Feedback = LabelCaptureFeedback.Default; // Or customize the feedback var customFeedback = LabelCaptureFeedback.Default; customFeedback.Success = new Feedback(Vibration.DefaultVibration, sound: null); labelCapture.Feedback = customFeedback; ``` :::note Audio feedback is only played if the device is not muted. ::: --- ## About Smart Label Capture import AboutLabelCapture from '../../../../partials/intro/_about-smart-label-capture.mdx'; import ValidationFlow from '../../../../partials/intro/_about_validation_flow.mdx'; See [here](./advanced.md#validation-flow) for more details. --- ## Label Definitions # Label Definitions A **Label Definition** is a configuration that defines the label, and its relevant fields, that Smart Label Capture should recognize and extract during scans. Smart Label Capture provides a [Label Definition](https://docs.scandit.com/data-capture-sdk/dotnet.android/label-capture/api/label-definition.html#label-definition) API, enabling you to configure and extract structured data from predefined and custom labels. This feature provides a flexible way to recognize and decode fields within a specific label layout such as price tags, VIN labels, or packaging stickers without needing to write custom code for each label type. There are two approaches to using label definitions: - [**Pre-built Labels**](#pre-built-labels) - [**Custom Labels**](#custom-labels) ## Pre-built Labels Smart Label Capture includes ready-made label definitions for common use cases. These pre-built options let you recognize and extract information from standard label types without creating custom configurations: ### Example: Price label Use `LabelCaptureSettings` to configure a pre-built label definition for price labels, such as those found in retail environments: ![Price Label Example](/img/slc/price-label.png) ```csharp // Create a pre-built price capture label definition var priceLabel = LabelDefinition.CreatePriceCaptureDefinition("price-label"); // Create the settings with the label definition var settings = LabelCaptureSettings.Create(new List { priceLabel }); ``` ## Custom Labels If Smart Label Capture's pre-built options don't fit your needs, define a custom label instead. Custom labels can combine your own fields with any of the available pre-built ones. :::tip The following characters are recognized: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ()-./:,$¶"`. ::: ### Custom Fields There are two types of custom fields you can define: The following methods are available to configure custom fields: | Method | Optional | Description | |--------|----------|-------------| | `ValueRegexes` | No | The regex patterns that identify the target string in the scanned content. | | `AnchorRegexes` | Yes | Used to specify keywords or phrases that help identify the context of the field. This is particularly useful when the label contains multiple fields that could match the same pattern (e.g., when both packaging and expiry dates are present). | | `Symbologies` | No | The barcode symbologies to match for barcode fields. This is important for ensuring that the field only captures data from specific barcode types, enhancing accuracy and relevance. | | `IsOptional` | Yes | Whether the field is optional or mandatory. This is helpful when certain fields may not be present on every scan. | #### Example: Fish Shipping Box This example shows how to create a custom label definition for a fish shipping box, which includes fields for barcode and batch number. ![Fish Shipping Box Example](/img/slc/fish-shipping-box.png) ```csharp // Build field definitions var fields = new List(); // Add a custom barcode field with the expected symbology var barcodeField = CustomBarcode.Builder() .SetSymbology(Symbology.Code128) .Build("barcode-field"); fields.Add(barcodeField); // Add a custom text field for the batch number var batchNumberField = CustomText.Builder() .SetAnchorRegex("Batch") .SetValueRegex("FZ\\d{5,10}") .IsOptional(true) .Build("batch-number-field"); fields.Add(batchNumberField); // Create the label definition with the fields var labelDefinition = LabelDefinition.Create("shipping-label", fields); // Create the settings with the label definition var settings = LabelCaptureSettings.Create(new List { labelDefinition }); ``` ### Pre-built Fields You can also build your label using pre-built fields. These common fields speed up integration because their `ValueRegexes`, `AnchorRegexes`, and `Symbologies` are already predefined. Customization of pre-built fields is done via the `ValueRegexes`, `AnchorRegexes`, and `IsOptional` methods, which allow you to specify the expected format of the field data. :::tip All pre-built fields come with default `ValueRegexes` and `AnchorRegexes` that are suitable for most use cases. **Using either method is optional and will override the defaults**. The `ResetAnchorRegexes` method can be used to remove the default `AnchorRegexes`, allowing you to rely solely on the `ValueRegexes` for detection. ::: import FeatureList from '@site/src/components/FeatureList'; #### Barcode Fields #### Price and Weight Fields #### Date and Custom Text Fields #### Example: Hard disk drive label This example demonstrates how to configure a label definition for a hard disk drive (HDD) label, which typically includes common fields like serial number and part number. ![Hard Disk Drive Label Example](/img/slc/hdd-label.png) ```csharp // Build field definitions using pre-built barcode fields var fields = new List(); // Add a serial number barcode field var serialNumberField = SerialNumberBarcode.Builder() .Build("serial-number"); fields.Add(serialNumberField); // Add a part number barcode field var partNumberField = PartNumberBarcode.Builder() .Build("part-number"); fields.Add(partNumberField); // Create the label definition with the fields var labelDefinition = LabelDefinition.Create("hdd-label", fields); // Create the settings with the label definition var settings = LabelCaptureSettings.Create(new List { labelDefinition }); ``` --- ## Adding AR Overlays # Adding AR Overlays There are two ways to add advanced AR overlays to a Data Capture View: - Take advantage of the [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) class, which provides a ready-to-use implementation for view-based AR overlays. - Provide your own custom implementation, using the function [IBarcodeBatchListener.OnSessionUpdated()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) to retrieve the barcode’s current screen position for each frame. :::note - The first way is the easiest, as it takes care of adding, removing and animating the overlay’s views whenever needed. It’s also flexible enough to cover the majority of use cases. - You can always handle touch events on the views you create like you normally would. ::: ## Using BarcodeBatchAdvancedOverlay As mentioned above, the advanced overlay combined with its [listener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) offers an easy way of adding augmentations to your [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). In this guide we will add a view above each barcode showing its content. First of all, create a new instance of [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) and add it to the [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). ```csharp BarcodeBatchAdvancedOverlay overlay = BarcodeBatchAdvancedOverlay.Create(barcodeBatch, dataCaptureView); ``` At this point, you have two options. - Add a [IBarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) to the overlay. - Use the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) to specify the view, anchor and offset for each barcode. :::note The second way will take priority over the first one, which means that if a view for a barcode has been set using [BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), the function [IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) won’t be invoked for that specific barcode. ::: Using [IBarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) - You need to implement [IBarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener). This interface’s methods are invoked every time a barcode is newly tracked. - [IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) asks for a view to animate on top of the barcode. Returning _null_ will show no view. - [IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode) asks how to anchor the view to the barcode through [Anchor](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/anchor.html#enum-scandit.datacapture.core.Anchor). Be aware that it anchors the view’s center to the anchor point. To achieve anchoring the top of the view or the bottom etc. you will have to set an offset as explained in the next point. - [IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode) asks for an offset that is applied on the already anchored view. This offset is expressed through a [PointWithUnit](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/common.html#struct-scandit.datacapture.core.PointWithUnit). ```csharp public View ViewForTrackedBarcode(BarcodeBatchAdvancedOverlay overlay, TrackedBarcode trackedBarcode) { // Create and return the view you want to show for this tracked barcode. You can also return null, to have no view for this barcode. TextView textView = new TextView(this); textView.SetBackgroundColor(Color.White); textView.LayoutParameters = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent); textView.Text = trackedBarcode.Barcode.Data; return textView; } public Anchor AnchorForTrackedBarcode( BarcodeBatchAdvancedOverlay overlay, TrackedBarcode trackedBarcode) { // As we want the view to be above the barcode, we anchor the view's center to the top-center of the barcode quadrilateral. // Use the function 'OffsetForTrackedBarcode' below to adjust the position of the view by providing an offset. return Anchor.TopCenter; } public PointWithUnit OffsetForTrackedBarcode( BarcodeBatchAdvancedOverlay overlay, TrackedBarcode trackedBarcode) { // This is the offset that will be applied to the view. // You can use MeasureUnit.Fraction to give a measure relative to the view itself, the sdk will take care of transforming this into pixel size. // We now center horizontally and move up the view to make sure it's centered and above the barcode quadrilateral by half of the view's height. return new PointWithUnit( new FloatWithUnit(0f, MeasureUnit.Fraction), new FloatWithUnit(-1f, MeasureUnit.Fraction)); } ``` Using the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) The function [IBarcodeBatchListener.OnSessionUpdated()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) gives you access to a [session](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession), which contains all added, updated and removed tracked barcodes. From here you can create the view you want to display, and then call [BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), [BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode) and [BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode) ```csharp public void OnSessionUpdated(BarcodeBatch mode, BarcodeBatchSession session, IFrameData data) { // Be careful, this function is not invoked on the main thread! RunOnUiThread(() => { foreach (TrackedBarcode trackedBarcode in session.AddedTrackedBarcodes) { TextView textView = new TextView(this); textView.SetBackgroundColor(Color.White); textView.LayoutParameters = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent); textView.Text = trackedBarcode.Barcode.Data; overlay.SetViewForTrackedBarcode(trackedBarcode, textView); overlay.SetAnchorForTrackedBarcode(trackedBarcode, Anchor.TopCenter); overlay.SetOffsetForTrackedBarcode( trackedBarcode, new PointWithUnit( new FloatWithUnit(0f, MeasureUnit.Fraction), new FloatWithUnit(-1f, MeasureUnit.Fraction) ) ); } }); } ``` ## Provide your own custom implementation If you do not want to use the overlay, it is also possible to add augmented reality features based on the tracking identifier and the [quadrilateral](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/common.html#struct-scandit.datacapture.core.Quadrilateral) coordinates that every tracked barcode has. Below are some pointers. - Set a [IBarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) on the barcode tracking - In the [IBarcodeBatchListener.OnSessionUpdated()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) function fetch the [added](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.AddedTrackedBarcodes) and [removed](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.RemovedTrackedBarcodes) tracked barcodes. - Create and show the views for the added barcodes. - Remove the views for the lost barcodes. - Add a method that is called 60fps when [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) is enabled. In this method, for each [TrackedBarcode](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/tracked-barcode.html#class-scandit.datacapture.barcode.batch.TrackedBarcode) on-screen, update the position based on [TrackedBarcode.Location](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location). Please note that there is no need to animate the change of location, the change of position will happen frequently enough that the view will look as it is animated. :::note The frame coordinates from [TrackedBarcode.Location](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location) need to be mapped to view coordinates, using [DataCaptureView.MapFrameQuadrilateralToView()](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#method-scandit.datacapture.core.ui.DataCaptureView.MapFrameQuadrilateralToView). ::: ```csharp public void OnSessionUpdated(BarcodeBatch mode, BarcodeBatchSession session, IFrameData data) { // Be careful, this function is not invoked on the main thread! RunOnUiThread(() => { foreach (int lostTrackIdentifier in session.RemovedTrackedBarcodes) { // You now know the identifier of the tracked barcode that has been lost. Usually here you would remove the views associated. } foreach (TrackedBarcode trackedBarcode in session.AddedTrackedBarcodes) { // Fixed identifier for the tracked barcode. int trackingIdentifier = trackedBarcode.Identifier; // Current location of the tracked barcode. Quadrilateral location = trackedBarcode.Location; Quadrilateral quadrilateral = dataCaptureView.MapFrameQuadrilateralToView(location); // You now know this new tracking's identifier and location. Usually here you would create and show the views. } }); } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan to your application. The general steps are: - Creating a new Data Capture Context instance - Configuring the MatrixScan mode - Using the built-in camera - Visualizing the scan process - Providing feedback - Disabling barcode tracking ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext context = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Batch Mode The main entry point for the Barcode Batch Mode is the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object. It is configured through [BarcodeBatchSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) that will get informed whenever a new frame has been processed. Most of the times, you will not need to implement a [IBarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener), instead you will add a [BarcodeBatchBasicOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) and implement a [IBarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener). For this tutorial, we will setup Barcode Batch for tracking QR codes. ```csharp BarcodeBatchSettings settings = BarcodeBatchSettings.Create(); settings.EnableSymbology(Symbology.Qr, true); ``` Next, create a [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance with the data capture context and the settings initialized in the previous steps: ```csharp BarcodeBatch barcodeBatch = BarcodeBatch.Create(context, settings); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Permissions in Android](https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/permissions) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```csharp camera = Camera.GetDefaultCamera(); camera?.ApplySettingsAsync(BarcodeBatch.RecommendedCameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.SetFrameSourceAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```csharp context.SetFrameSourceAsync(camera); ``` The camera is off by default and must be turned on. This is done by calling [IFrameSource.SwitchToDesiredStateAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```csharp camera?.SwitchToDesiredStateAsync(FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```csharp DataCaptureView dataCaptureView = DataCaptureView.Create(dataCaptureContext); SetContentView(dataCaptureView); ``` Alternatively you can use a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) from XAML in your MAUI application. For example: ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); // Initialization of DataCaptureView happens on handler changed event. dataCaptureView.HandlerChanged += DataCaptureViewHandlerChanged; } private void DataCaptureViewHandlerChanged(object? sender, EventArgs e) { // Your dataCaptureView configuration goes here, e.g. add overlay } } ``` For MAUI development add [Scandit.DataCapture.Core.Maui](https://www.nuget.org/packages/Scandit.DataCapture.Core.Maui) NuGet package into your project. To visualize the results of Barcode Batch, first you need to add the following [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay): ```csharp BarcodeBatchBasicOverlay overlay = BarcodeBatchBasicOverlay.Create(barcodeBatch, dataCaptureView); ``` Once the overlay has been added, you should implement the [IBarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) interface. The method [IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode) is invoked every time a new tracked barcode appears and it can be used to set a [brush](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/ui/brush.html#class-scandit.datacapture.core.ui.Brush) that will be used to highlight that specific barcode in the [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay). ```csharp public Brush BrushForTrackedBarcode(BarcodeBatchBasicOverlay overlay, TrackedBarcode trackedBarcode) { // Return a custom Brush based on the tracked barcode. } ``` If you would like to make the highlights tappable, you need to implement the [IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped) method. ```csharp public void OnTrackedBarcodeTapped(BarcodeBatchBasicOverlay overlay, TrackedBarcode trackedBarcode) { // A tracked barcode was tapped. } ``` ## Get Barcode Batch Feedback Barcode Batch, unlike Barcode Capture, doesn’t emit feedback (sound or vibration) when a new barcode is recognized. However, you may implement a [IBarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) to provide a similar experience. Below, we use the default [Feedback](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration if you want. ```csharp protected override void OnResume() { base.OnResume(); feedback = Feedback.DefaultFeedback; } protected override void OnPause() { base.OnPause(); feedback.Dispose(); } ``` Next, use this [feedback](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/feedback.html#class-scandit.datacapture.core.Feedback) in a [IBarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener): ```csharp public class FeedbackListener : IBarcodeBatchListener { public void OnObservationStarted(BarcodeBatch barcodeBatch) { // Called when Barcode Batch is started. // We don't use this callback in this guide. } public void OnObservationStopped(BarcodeBatch barcodeBatch) { // Called when Barcode Batch is stopped. // We don't use this callback in this guide. } public void OnSessionUpdated(BarcodeBatch barcodeBatch, BarcodeBatchSession session, IFrameData frameData) { if (session.AddedTrackedBarcodes.Any()) { this.feedback.Emit(); } } } ``` [IBarcodeBatchListener.OnSessionUpdated()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) is invoked for every processed frame. The [session](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession) parameter contains information about the currently tracked barcodes, in particular, the newly recognized ones. We check if there are any and if so, we emit the feedback. As the last step, register the listener responsible for emitting the feedback with the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance. ```csharp barcodeBatch.AddListener(feedbackListener); ``` ## Disabling Barcode Batch To disable barcode tracking set [BarcodeBatch.Enabled](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-batch.html#property-scandit.datacapture.barcode.batch.BarcodeBatch.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off or put it in standby calling [SwitchToDesiredState](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [StandBy](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.Standby). --- ## About MatrixScan Batch # About MatrixScan Batch import AboutMatrixScan from '../../../../partials/intro/_about-matrixscan.mdx' --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan AR to your application. Implementing MatrixScan AR involves two primary elements: - Barcode AR: The data capture mode that is used for scan and check functionality. - A Barcode AR View: The pre-built UI elements used to highlight items to be checked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode AR Mode - Setup the Barcode AR View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/net/android/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Internal Dependencies import InternalDependencies from '../../../../partials/get-started/_internal-deps.mdx'; ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new [Data Capture Context](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode AR Mode The main entry point for the Barcode AR Mode is the `BarcodeAr` object. You can configure the supported Symbologies through its [`BarcodeArSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-ar-settings.html). Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```csharp BarcodeArSettings settings = new BarcodeArSettings(); settings.EnableSymbology(Symbology.Ean13Upca, true); ``` Then create the mode with the previously created settings: ```csharp BarcodeAr barcodeAr = new BarcodeAr(dataCaptureContext, settings); ``` ## Setup the `BarcodeArView` MatrixScan AR’s built-in AR user interface includes buttons and overlays that guide the user through the scan and check process. By adding a [`BarcodeArView`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView), the scanning interface is added automatically to your application. The `BarcodeArView` is where you provide the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider) to supply the highlight and annotation information for the barcodes to be checked. If *null*, a default highlight is used and no annotations are provided. The `BarcodeArView` appearance can be customized through [`BarcodeArViewSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-ar-view-settings.html#class-scandit.datacapture.barcode.check.ui.BarcodeArViewSettings), properties on the`BarcodeArView`, and the corresponding settings for your desired highlights and/or annotations, to match your application’s look and feel. The following settings can be customized: * Audio and haptic feedback * Camera position * Torch button visibility and its position * Switch camera button visibility and its position * Zoom control visibility and its position * The size, colors, and styles of the highlights and annotations ```csharp BarcodeArViewSettings viewSettings = new BarcodeArViewSettings(); viewSettings.HapticEnabled = false; viewSettings.SoundEnabled = false; viewSettings.DefaultCameraPosition = CameraPosition.UserFacing; ``` Next, create a `BarcodeArView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodeArView` is automatically added to the provided parent view. ```csharp BarcodeArView barcodeArView = BarcodeArView.Create(parentView, barcodeAr, dataCaptureContext, viewSettings, cameraSettings: null); barcodeArView.ShouldShowCameraSwitchControl = true; barcodeArView.ShouldShowTorchControl = true; barcodeArView.ShouldShowZoomControl = true; barcodeArView.CameraSwitchControlPosition = Anchor.TopRight; barcodeArView.TorchControlPosition = Anchor.BottomRight; barcodeArView.ZoomControlPosition = Anchor.TopLeft; ``` Configure the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider). ```csharp public class AnnotationProvider : IBarcodeArAnnotationProvider { public Task AnnotationForBarcodeAsync(Barcode barcode) { var annotation = new BarcodeArStatusIconAnnotation(barcode); annotation.Text = "Example annotation"; return Task.FromResult(annotation); } } public class HighlightProvider : IBarcodeArHighlightProvider { public Task HighlightForBarcodeAsync(Barcode barcode) { return Task.FromResult(new BarcodeArRectangleHighlight(barcode)); } } ``` And set them to the view: ```csharp barcodeArView.HighlightProvider = new HighlightProvider(); barcodeArView.AnnotationProvider = new AnnotationProvider(); ``` ## Register the Listener If you want a callback when a highlight is tapped, register a [BarcodeArViewUiListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-ar-view.html#interface-scandit.datacapture.barcode.check.ui.IBarcodeArViewUiListener). ```csharp barcodeArView.HighlightForBarcodeTapped += (object sender, HighlightForBarcodeTappedEventArgs args) => { BarcodeAr barcodeAr = args.BarcodeAr; Barcode barcode = args.Barcode; IBarcodeArHighlight highlight = args.Highlight; // Handle tap }; ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling: ```csharp barcodeArView.Start(); ``` --- ## About MatrixScan AR # About MatrixScan AR import AboutMatrixScanCheck from '../../../../partials/intro/_about-matrixscan-ar.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Count is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Count to best fit your needs. ## Scanning Against A List There is a function to set a list of expected barcodes if you are scanning against a manifest or item list. If this is used, a progress bar is added to the UI, so you can keep track of the process while scanning. When scanning against a list, the UI will also show red icons to mark scanned barcodes that aren’t present on the list. ```csharp List targetBarcodes = new List(); targetBarcodes.Add(TargetBarcode.Create("data", 1)); BarcodeCountCaptureList captureList = BarcodeCountCaptureList.Create(this, targetBarcodes); barcodeCount.SetBarcodeCountCaptureList(captureList); ``` ## Barcode Count Status This feature is used to provide users with more details regarding the items they’re scanning in order to aid effective handling. The icons (available as part of the SDK) appear as an AR overlay after tapping the “Status Mode” button and can be used to highlight the following: - Expired products - Items requiring quality inspection - Items that are low in stock - Wrong items - Fragile items ## Clustering import Clustering from '../../../../partials/count/_clustering.mdx' ## Strap Mode It can be difficult to reach the shutter button if the smart device is attached to the user’s wrist by a strap or similar. In this instance, you can enable a floating shutter button that can be positioned by the end user in a more ergonomically suitable position. ```csharp barcodeCountView.ShouldShowFloatingShutterButton = true; ``` ## Filtering If you have several types of barcodes on your label/package, you may want to scan only one of them. In this case, you can filter the others out. This can be done by symbology, symbol count, or setting a regex. For example, you might want to scan only Code 128 barcodes and no PDF417 ones. ```csharp BarcodeCountSettings settings = new BarcodeCountSettings(); settings.EnableSymbologies(enabledSymbologies); settings.FilterSettings.ExcludedSymbologies = new[] { Symbology.Pdf417 }; ``` Or, you want to exclude all the barcodes starting with 4 numbers: ```csharp BarcodeCountSettings settings = new BarcodeCountSettings(); settings.FilterSettings.ExcludedCodesRegex = "^1234.\*"; ``` By default the filters applied to the relevant barcodes are transparent, but you can use [`BarcodeFilterHighlightSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-filter-highlight-settings.html#barcode-filter-highlight-settings) to change the color and level of transparency. ![Different Filters in MatrixScan Count](/img/matrixscan-count/filtering_styles.png) ## Clear Screen Button There are situations in which the user may find it helpful to clean up their screen (i.e. clear all the AR overlays) but keep the list of barcodes scanned. If this is the case, you can enable the “Clear screen” button. ```csharp barcodeCountView.ShouldShowClearHighlightsButton = true; ``` ## Customize Overlay Colors MatrixScan Count comes with recommended and user-tested AR overlays. However, if you wish to customize the overlay colors, once the overlay has been added, you can conform to the [IBarcodeCountViewListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view-listener.html#interface-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener) interface. The methods [IBarcodeCountViewListener.BrushForRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForRecognizedBarcode) and [IBarcodeCountViewListener.BrushForRecognizedBarcodeNotInList()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForRecognizedBarcodeNotInList) are invoked every time a new recognized or not-in-list barcode appears. These can be used to set a brush that will be used to highlight that specific barcode in the overlay. Keep in mind that these methods are relevant only when using the style [BarcodeCountViewStyle.Dot](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view.html#value-scandit.datacapture.barcode.count.ui.BarcodeCountViewStyle.Dot). ```csharp public Brush? BrushForRecognizedBarcode(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Return a custom brush } public Brush? BrushForRecognizedBarcodeNotInList(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Return a custom brush } ``` ## Notifications If you want to be notified when a user taps on an overlay, you need to implement the [IBarcodeCountViewListener.OnRecognizedBarcodeTapped()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnRecognizedBarcodeTapped) and [IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped) methods. ```csharp public void OnRecognizedBarcodeTapped(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Do something with the tapped barcode } public void OnUnrecognizedBarcodeTapped(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Do something with the tapped barcode } ``` ## Disable UI Elements The UI is an integral part of MatrixScan Count and we do not recommend that you use it without it. However, if you wish to disable UI elements you can do it as follows. Disable buttons: ```csharp barcodeCountView.ShouldShowListButton = false; barcodeCountView.ShouldShowExitButton = false; barcodeCountView.ShouldShowShutterButton = false; ``` Disable feedback and hints: ```csharp barcodeCountView.ShouldShowUserGuidanceView = false; barcodeCountView.ShouldShowHints = false; ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Count to your application. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Count Mode - Obtaining the camera instance and set frame source - Registering the listener to be informed when scan phase is complete - Setting the capture view and AR overlays - Configuring the camera for scanning view - Storing and retrieving the captured barcodes - Resetting the Barcode Count Mode - List and exit callbacks ## Create A New Data Capture Context Instance The first step to add capture capabilities to your application is to create a new [Data Capture Context](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure The Barcode Count Mode The main entry point for the Barcode Count Mode is the [BarcodeCount](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) object. It is configured through [BarcodeCountSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count-settings.html#class-scandit.datacapture.barcode.count.BarcodeCountSettings) and allows you to register one or more listeners that are informed whenever a scan phase has finished. For this tutorial, we will set up Barcode Count for tracking EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```csharp BarcodeCountSettings settings = new BarcodeCountSettings(); settings.EnableSymbology(Symbology.Ean13Upca, true); ``` If you are sure that your environment will only have unique barcodes (i.e. no duplicated values), you can also enable [BarcodeCountSettings.ExpectsOnlyUniqueBarcodes](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count-settings.html#property-scandit.datacapture.barcode.count.BarcodeCountSettings.ExpectsOnlyUniqueBarcodes). This option improves scanning performance as long as you are sure that no duplicates will be present. Next, create a [BarcodeCount](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) instance with the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) and the settings initialized in the previous step: ```csharp BarcodeCount barcodeCount = BarcodeCount.Create(dataCaptureContext, settings); ``` ## Obtain Camera Instance And Set Frame Source Used Our recommended camera settings should be used to achieve the best performance and user experience. The following couple of lines show how to get the recommended settings for MatrixScan Count and create the camera from it: ```csharp CameraSettings cameraSettings = BarcodeCount.RecommendedCameraSettings; Camera camera = Camera.DefaultCamera; camera.ApplySettingsAsync(cameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.SetFrameSourceAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```csharp dataCaptureContext.SetFrameSourceAsync(camera); ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [IBarcodeCountListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) interface and register the listener. ```csharp // Register self as a listener to monitor the barcode count session. barcodeCount.AddListener(this); ``` [IBarcodeCountListener.OnScan()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan) is called when the scan phase has finished and results can be retrieved from [BarcodeCountSession](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession). Alternatively to register [IBarcodeCountListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) interface it is possible to subscribe to corresponding event. For example: ```csharp barcodeCount.Scanned += (object sender, BarcodeCountEventArgs args) => { }; ``` ## Set Capture View And AR Overlays MatrixScan Count’s built-in AR user interface includes buttons and overlays that guide the user through the capturing process. By adding a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) to your view hierarchy: ```csharp BarcodeCountView barcodeCountView = BarcodeCountView.Create(context, dataCaptureContext, barcodeCount); ``` You can use a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) from XAML in your MAUI application. ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MyScanPage : ContentPage { public MyScanPage() { this.InitializeComponent(); // Initialization of BarcodeCountView happens on handler changed event. this.barcodeCountView.HandlerChanged += BarcodeCountViewHandlerChanged; } private void BarcodeCountViewHandlerChanged(object sender, EventArgs e) { // Your BarcodeCountView configuration goes here, e.g. subscribe for buttons tap events } } ``` For MAUI development add [Scandit.DataCapture.Barcode.Maui](https://www.nuget.org/packages/Scandit.DataCapture.Barcode.Maui) NuGet package into your project. ## Set Up The Camera So That It Switches On When You Are In Scanning View The camera is not automatically turned on when you are in a scanning view. You need to set up the camera so that it switches on when needed and it switches off when not needed anymore. Similarly [BarcodeCount](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) should also be enabled and disabled. For instance, you should switch off the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is not visible anymore (including when the app goes in the background), similarly you want to switch on the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is visible (including when the app goes to the foreground). One way to achieve this is the following: ```csharp protected override void OnPause() { camera.SwitchToDesiredStateAsync(FrameSourceState.Off); base.OnPause(); } protected override void OnResume() { camera.SwitchToDesiredStateAsync(FrameSourceState.On); base.OnResume(); } ``` ## Store And Retrieve Scanned Barcodes The values captured as part of the scanning process are part of the [session](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession), and the session is not accessible outside [IBarcodeCountListener.OnScan()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan). Therefore, we recommend that you store the values to present a list, for example when the user taps the list icon. To do this, make a copy of [BarcodeCountSession.RecognizedBarcodes](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count-session.html#property-scandit.datacapture.barcode.count.BarcodeCountSession.RecognizedBarcodes): ## Reset Barcode Count Mode When the scanning process is over, you need to reset the mode to make it ready for the next process. This clears the list of barcodes scanned and all the AR overlays. To reset Barcode Count’s scanning process, you need to call the [BarcodeCount.Reset()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-count.html#method-scandit.datacapture.barcode.count.BarcodeCount.Reset) method. ```csharp barcodeCount.Reset(); ``` ## List And Exit Callbacks The UI includes two icons (buttons) named “List” and “Exit”. The SDK provides events so you can add the desired action when those icons are tapped by the user. ```csharp barcodeCountView.ListButtonTapped += (object sender, ListButtonTappedEventArgs args) => { // Show the current progress but the order is not completed }; barcodeCountView.ExitButtonTapped += (object sender, ExitButtonTappedEventArgs args) => { // The order is completed }; ``` --- ## About MatrixScan Count # About MatrixScan Count import AboutMatrixScanCount from '../../../../partials/intro/_about-matrixscan-count.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Find is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Find to best fit your needs. ## BarcodeFind Listener You may want more fine-grained knowledge over the different events happening during the life of the BarcodeFind mode, such as when the search starts, pauses and stops. To do this, you can directly register a [IBarcodeFindListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-find-listener.html#interface-scandit.datacapture.barcode.find.IBarcodeFindListener) on the mode itself. Be aware that these listeners will be called from a background thread. ```csharp public class BarcodeFindListener : IBarcodeFindListener { public void OnSearchPaused(ICollection foundItems) { // The mode was paused } public void OnSearchStarted() { // The mode was started } public void OnSearchStopped(ICollection foundItems) { // The mode was stopped after the finish button was clicked } } private void Initialize() { barcodeFind.AddListener(new BarcodeFindListener()) } ``` Alternatively it is possible to subscribe to corresponding events [BarcodeFind.SearchPaused](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-find.html#property-scandit.datacapture.barcode.find.BarcodeFind.SearchPaused), [BarcodeFind.SearchStarted](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-find.html#property-scandit.datacapture.barcode.find.BarcodeFind.SearchStarted) or [BarcodeFind.SearchStopped](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-find.html#property-scandit.datacapture.barcode.find.BarcodeFind.SearchStopped). For example: ```csharp barcodeFind.SearchStarted += (object? sender, EventArgs args) => { // The mode was started }; barcodeFind.SearchPaused += (object? sender, BarcodeFindEventArgs args) => { // The mode was paused }; barcodeFind.SearchStopped += (object? sender, BarcodeFindEventArgs args) => { // The mode was stopped after the finish button was clicked }; ``` ## UI configuration The [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) will by default show a set of UI elements, which can be optionally hidden: - A play/pause button - A finish button - A searched items carousel - Guidance hints There is also a progress bar but this is hidden by default. Each of these elements can be shown or hidden at will. ```csharp barcodeFindView.ShouldShowCarousel = false; barcodeFindView.ShouldShowProgressBar = true; // … ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Find to your application. Implementing MatrixScan Find involves two primary elements: - Barcode Find: The data capture mode that is used for search and find functionality. - A Barcode Find View: The pre-built UI elements used to highlight found items. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Find Mode - Setup the Barcode Find View - Registering the Listener to notify about found items ## Create a Data Capture Context The first step to add find capabilities to your application is to create a new [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Find Mode The main entry point for the Barcode Find Mode is the [BarcodeFind](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind) object. You can configure the supported Symbologies through its [BarcodeFindSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-find-settings.html#class-scandit.datacapture.barcode.find.BarcodeFindSettings), and set up the list of items that you want MatrixScan Find to highlight (e.g. a list of products). For this tutorial, we will set up Barcode Find for tracking EAN13 codes. Change this to the correct symbologies for your use case (e.g. Code 128, Code 39…). First create the settings: ```csharp BarcodeFindSettings settings = new BarcodeFindSettings(); settings.EnableSymbology(Symbology.Ean13Upca, true); ``` Then you have to create the list of items that will be actively searched for. In this tutorial, let’s look up two items based on their EAN13 codes. We will attach to the first item some optional information that can be used by the BarcodeFindView to display extra information. ```csharp ICollection items = new HashSet() { new BarcodeFindItem( new BarcodeFindItemSearchOptions("9783598215438"), new BarcodeFindItemContent("Mini Screwdriver Set", "(6-Piece)", null)), new BarcodeFindItem( new BarcodeFindItemSearchOptions("9783598215414"), null) // Item information is optional, used for display only }; ``` Create the mode with the previously created settings and set the items: ```csharp BarcodeFind barcodeFind = new BarcodeFind(settings); barcodeFind.SetItemList(items); ``` ## Setup the BarcodeFindView MatrixScan Find’s built-in AR user interface includes buttons and overlays that guide the user through the searching process. By adding a [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView), the scanning interface (camera preview and searching UI elements) will be added automatically to your application. The BarcodeFindView appearance can be customized through [BarcodeFindViewSettings](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-find-view-settings.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindViewSettings): - Colors of dots in augmented reality overlay - Enable sound and haptic alerts ```csharp BarcodeFindViewSettings viewSettings = new BarcodeFindViewSettings(); ``` Construct a new BarcodeFindView. The BarcodeFindView is automatically added to the provided parent view. (The parent view can be any subclass of ViewGroup, such as FrameLayout, …) ```csharp BarcodeFindView barcodeFindView = BarcodeFindView.Create(parentView, dataCaptureContext, barcodeFind, viewSettings); ``` Connect the BarcodeFindView to the Android lifecycle. The view is dependent on calling onPause and onResume to set up the camera and its overlays properly. ```csharp public override void OnResume() { base.OnResume(); barcodeFindView.OnResume(); } public override void OnPause() { base.OnPause(); barcodeFindView.OnPause(); } ``` ## Subscribe to view events to be notified with found items The BarcodeFindView displays next to its shutter button a handy “finish” button. Subscribe to a [BarcodeFindView.FinishButtonTapped](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-find-view.html#property-scandit.datacapture.barcode.find.ui.BarcodeFindView.FinishButtonTapped) event to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```csharp barcodeFindView.FinishButtonTapped += (object? sender, FinishButtonTappedEventArgs e) => { RequireActivity().OnBackPressed(); }; ``` ## Start searching As soon as everything is set up, control the [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) to start the search. ```csharp barcodeFindView.StartSearching(); ``` This is the equivalent of pressing the “Play” button programmatically. It will start the search process, turn on the camera and hide the item carousel. ## Samples The best way to start working with the Scandit Data Capture SDK is to run one of our sample apps. [See the full list of available samples](https://github.com/Scandit/datacapture-dotnet-samples/tree/master). --- ## About MatrixScan Find # About MatrixScan Find import AboutFind from '../../../../partials/intro/_about-matrixscan-find.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Pick is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Pick to best fit your needs. ## BarcodePick Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodePick` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodePickListener`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-pick-listener.html#interface-scandit.datacapture.barcode.pick.IBarcodePickListener) on the mode itself, keeping in mind that these listeners are called from a background thread. ```csharp public class MyBarcodePickListener : IBarcodePickListener { public void OnSessionUpdated(BarcodePick barcodePick, BarcodePickSession session) { // Handle session update } } private void Initialize() { barcodePick.AddListener(new MyBarcodePickListener()); } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Pick to your application. Implementing MatrixScan Pick involves two primary elements: - Barcode Pick: The data capture mode that is used for scan and pick functionality. - A Barcode Pick View: The pre-built UI elements used to highlight items to be picked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Pick Mode - Setup the Barcode Pick View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new Data Capture Context. The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Pick Mode The main entry point for the Barcode Pick Mode is the `BarcodePick` object. You can configure the supported Symbologies through its [`BarcodePickSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-pick-settings.html), and set up the list of items that you want MatrixScan Pick to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```csharp BarcodePickSettings settings = new BarcodePickSettings(); settings.EnableSymbology(Symbology.Ean13Upca, true); ``` Then you have to create the list of items that will be picked and quantity to be picked for each item. ```csharp ICollection productsToPick = new List() { new BarcodePickProduct("9783598215438", 3), new BarcodePickProduct("9783598215414", 3) }; ``` Create a product provider that maps scanned barcodes to your product list, and then the mode with the previously created settings: ```csharp // 'this' must implement IBarcodePickAsyncMapperProductProviderCallback IBarcodePickProductProvider productProvider = new BarcodePickAsyncMapperProductProvider(productsToPick, callback: this); BarcodePick barcodePick = new BarcodePick(dataCaptureContext, settings, productProvider); ``` ## Setup the `BarcodePickView` MatrixScan Pick’s built-in AR user interface includes buttons and overlays that guide the user through the scan and pick process. By adding a [`BarcodePickView`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-pick-view.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickView), the scanning interface is added automatically to your application. The `BarcodePickView` appearance can be customized through [`BarcodePickViewSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/barcode-pick-view-settings.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickViewSettings) to match your application’s look and feel. The following settings can be customized: * Colors of dots in augmented reality overlay * Enable sound and haptic alerts * Guidelines text * Showing hints * Finish button * Pause button * Zoom button * Loading Dialog ```csharp BarcodePickViewSettings viewSettings = new BarcodePickViewSettings(); // ... ``` (The parent view can be any subclass of ViewGroup, such as FrameLayout, …) Construct a new `BarcodePickView`. The `BarcodePickView` is automatically added to the provided parent view. ```csharp BarcodePickView barcodePickView = BarcodePickView.Create(parentView, dataCaptureContext, barcodePick, viewSettings); ``` You can use a `BarcodePickView` from XAML in your MAUI application. ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MyFindBarcodePage : ContentPage { public MyFindBarcodePage() { this.InitializeComponent(); // Initialization of BarcodePickView happens on handler changed event. this.BarcodePickView.HandlerChanged += SetupBarcodePickView; } private void SetupBarcodePickView(object? sender, EventArgs args) { // Your BarcodePickView configuration goes here, e.g. subscribe for button tap events } } ``` :::important For MAUI development add the [`Scandit.DataCapture.Barcode.Maui`](https://www.nuget.org/packages/Scandit.DataCapture.Barcode.Maui) NuGet package into your project. ::: Connect the `BarcodePickView` to the Android lifecycle. The view is dependent on calling `BarcodePickView.onPause()` and `BarcodePickView.onResume()` to set up the camera and its overlays properly. ```csharp public override void OnResume() { base.OnResume(); barcodePickView.OnResume(); } public override void OnPause() { base.OnPause(); barcodePickView.OnPause(); } ``` If your are developing on MAUI then connect the BarcodePickView to the MAUI page lifecycle. In particular, make sure to call `BarcodePickView.OnResume` on your [`Element.HandlerChanged`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.maui.controls.element.handlerchanged) event and `BarcodePickView.OnPause` on your [`Page.OnDisappearing`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.maui.controls.page.ondisappearing). ```csharp public FindBarcodePage() { this.BarcodePickView.HandlerChanged += SetupBarcodePickView; } private void SetupBarcodePickView(object? sender, EventArgs args) { #if __ANDROID__ this.BarcodePickView.OnResume(); #endif } protected override void OnDisappearing() { base.OnDisappearing(); this.BarcodePickView.Stop(); this.BarcodePickView.OnPause(); } ``` ## Subscribe to View Events The `BarcodePickView` displays a **Finish** button next to its shutter button. Subscribe to a `BarcodePickView.onFinishButtonTapped` event to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```csharp BarcodePickView.FinishButtonTapped += (object? sender, FinishButtonTappedEventArgs e) => { RequireActivity().OnBackPressed(); }; ``` However, this convenient “finish” button is not supported with MAUI development. You can create the button manually and invoke `BarcodePickView.StopSearching` to achieve the same functionality. The following code snippet demonstrates how to do this: `FindBarcodePage.xaml`: ```csharp (...) ``` `FindBarcodePage.xaml.cs`: ```csharp private void FinishButtonClicked(object? sender, EventArgs args) { if (Application.Current?.MainPage is NavigationPage navigation) { BarcodePickView.Stop(); navigation.PopToRootAsync(animated: true); } } ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `BarcodePickView.Start()`. ```csharp barcodePickView.Start(); ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Pick # About MatrixScan Pick MatrixScan Pick is a pre-built UI that uses augmented reality overlays to highlight specific items that need to be picked. Whereas MatrixScan AR is fully customizable, MatrixScan Pick is a pre-built solution that allows you to add a scan and pick experience with augmented reality to an existing native app, with just a few lines of code. MatrixScan Pick is implemented through functionality provided by [`BarcodePick`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/barcode-pick.html). ## UI Overview * MatrixScan Pick is inspired by the familiar paradigm of a camera, including a shutter button that the user operates in order start and pause the scanning view. The Finish button is used at any time to exit the workflow. * It highlights items with obvious and colorful visual dots on screen. * When paused, MatrixScan Pick freezes the display at the last view, even if the device is moved. The Play button transitions back to the live view. * Textual guidance is displayed from the beginning of the session and as the workflow progresses, informing of the user of changes in item status (i.e. Detected, Ignored, To-Pick, or Picked). * Status icons can be defined to provide further information to users for a given barcode. In the live view, the icons are displayed but not tappable. In the frozen view, the status icons can be tapped and expanded to provide additional textual information. * The Quick Start Guide takes you through the process to install the full UI. However, you can then customize it by choosing to remove any elements on the screen except for the AR overlays. This allows you to create custom UIs suitable for your own workflows. ## Supported Symbologies MatrixScan Find supports all [symbologies](../barcode-symbologies.mdx) **except** DotCode, MaxiCode and postal codes (KIX, RM4SCC). If you are not familiar with the symbologies that are relevant for your use case, you can use capture presets that are tailored for different verticals (e.g. retail, logistics, etc.). --- ## Get Started # Get Started The parser parses data strings, e.g. as found in barcodes, into a set of key-value mappings. In this guide, you will know briefly how to use a parser and what types of parser are currently supported by Scandit. These data formats are supported: [Health Industry Bar Code (HIBC)](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/hibc.html), [GS1 Application Identifier (https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/AI) system](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/gs1ai.html) and [Swiss QR Codes](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/swissqr.html), [VIN Vehicle Identification Number](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/vin.html), [IATA Bar Coded Boarding Pass (BCBP)](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/iata-bcbp.html) More data formats will be added in future releases. Please contact us if the data format you are using is not yet supported, or you want to use the parser on a currently unsupported platform. ## Format-Specific Documentation - [Supported Data Formats](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/formats.html) - [HIBC](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/hibc.html) - [GS1 AI](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/gs1ai.html) - [GS1 Digital Link](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/gs1-digital-link.html) - [Swiss QR](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/swissqr.html) - [VIN](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/vin.html) - [IATA BCBP](https://docs.scandit.com/data-capture-sdk/dotnet.android/parser/iata-bcbp.html) --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### New Features #### Barcode * Added the SelectionMode API to replace the SparkScan target-mode APIs and `ScanIntention.smartSelection`: Set `selectionMode` (off/on/auto) in the `BarcodeCaptureSettings` and `SparkScanSettings` to control whether an aimed-at barcode is scanned automatically or requires explicit selection. #### Id * Added Irish Garda Age Card as `RegionSpecificSubtype.IrelandAgeCard`. * Added double-sided support for the Oman residence card. * Added single-sided support for extraction of issue date and birth date from the 2025 NYC Municipal ID. #### Smart Label Capture * Extended VIN label capture to also scan Code 128 barcodes (in addition to QR, Code 39, and Data Matrix) via `createVinLabelDefinition()`. * Extended LabelCapture to accept label definitions where both "barcode" and "text" field types use the "semantics" feature simultaneously; previously this was restricted to only one field type at a time. ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Smart Label Capture * Improved Receipt Scanning efficiency by optimizing receipt image processing before extraction. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. * Updated `SymbologyDescription.forIdentifier` to return `null` for unrecognized identifiers (e.g. `"EAN-8"` instead of `"ean8"`); previously such input was silently mapped to `Codabar`. ### Bug Fixes #### Barcode * Fixed a crash in `BarcodeArView` on iOS (.NET MAUI) where an `ApplicationException` was thrown when no `CameraSettings` was supplied; `CameraSettings` is optional, so the view now falls back to default camera settings on iOS instead of throwing, matching Android behavior. * Fixed a memory leak in item-based scanning. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Id * Fixed an issue where cropped document images were rotated when Frame Image was also enabled. * Corrected the orientation of cropped Visa document images that were being rotated incorrectly when scanned using a single-frame image source. * Fixed parser handling of non-standard Surrey BC AAMVA barcodes that were incorrectly returning "Invalid Format". #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a crash when the `DataCaptureContext` singleton was initialized more than once. ### Deprecations #### Barcode * The SparkScan target-mode APIs and `ScanIntention.smartSelection` are deprecated in favour of selectionMode. ## 8.4.1 **Released**: June 23, 2026 ### Bug Fixes #### Barcode * Fixed a memory leak in SparkScan when using the item-based API. #### Id * Fixed an issue where cropped document images were rotated when they are recovered using the getFrame API. ## 8.4.0 **Released**: May 18, 2026 ### New Features #### Barcode * Added `dotRadius` property to `BarcodeBatchBasicOverlay` to allow customizing the size of dots when using the Dot overlay style. #### Id * Added support for reading the vehicle table on the back of New Zealand driving licences, with the latest expiry date returned; supported vehicle classes are 1–6, including L=learner and R=restricted variants. * Added support for new versions of USA, California – Driver's License; USA, North Carolina – Driver's License; USA, Texas – Driver's License; and USA, Oklahoma – Driver's License. #### Core * Redesigned `ZoomSwitchControl` to support multiple configurable zoom levels; the control now displays as a compact button that expands to show all available zoom levels, automatically filtered to those supported by the device hardware. * Added a new `PinchToZoom` gesture. * Enhanced `CameraSettings` to support `ZoomLevels` for the .NET API. * Added Camera Switch Control component to .NET. * `DataCaptureView.DataCaptureContext` can now be reassigned at runtime in MAUI, both via code-behind and XAML data binding. Previously, the context could only be set once during view initialization. ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. #### Core * Updated mbedtls from version 3.6.5 to 3.6.6. ### Bug Fixes #### Barcode * Fixed an issue in `BarcodeCount` where the floating shutter button was not visible after setting `shouldShowFloatingShutterButton` to `true`. * Fixed an issue preventing `BarcodeFind` from finding binary barcodes. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed an issue where the Smart Scan Selection aimer would become too small when scan-area margins restricted the visible scan area; the aimer is now sized relative to the view, keeping a consistent on-screen size regardless of margins. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. #### Id * Fixed an issue where the US Permanent Residence Card was not processed through the VizMrz flow. * Fixed an issue where AAMVA verification was being performed even when no AAMVA document types were enabled in the accepted documents. #### Smart Label Capture * Fixed a memory leak in LabelCapture * Fixed an issue where the validation flow viewfinder was not displayed. * Fixed a race condition in the validation flow. * Fixed a bug that caused error messages in `DataCaptureView` to be rendered partially out-of-view. * Fixed a rare race condition in Label Capture. * Added `.asDate()` support to `ExpiryDate` and `PackingDate` label fields when the text is provided as manual input or as an Adaptive-Recognition-Engine response. * Fixed a bug where the receipt scanning overlay and validation flow overlay could not be used on the same LabelCapture mode instance. #### Core * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. * Fixed a rare crash when opening the camera. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed custom sound not working in Barcode Find on Android. * Fixed a rare crash when starting camera capture while under memory pressure. ### Deprecations #### Core * Added `PinchToZoom` class for the .NET API; deprecated the `ZoomGesture` property in favor of `ZoomGestures`. ## 8.3.1 **Released**: April 14, 2026 ### Bug Fixes #### Smart Label Capture * Fixed the validation flow to accept dates in more formats when manually entered * Fixed a race condition in the validation flow ## 8.3.0 **Released**: March 26, 2026 ### New Features #### Barcode * Added support for composite codes in SparkScan * Added the `LabelCaptureButtonVisible` property and `LabelCaptureButtonTapped` event to `SparkScanView`, allowing users to navigate from SparkScan to Smart Label Capture #### Id * Added support for OCR scanning of the 2026 version of Victoria mobile driver licenses * Added IdCaptureSettings.anonymizeDefaultFields setting that controls whether the SDK applies default anonymization rules for specific document types and regions #### Smart Label Capture * Fixed a rare race condition #### Core * Introduced .NET 10 support on Scandit SDK for .NET * Added LabelCapture Validation Flow Manual input support for allowing developers to receive a callback when the users trigger the manual input, as well as placeholder support for the overlay’s text fields. Existing users of the Validation Flow must implement the new interface when upgrading to this version. ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Improved speed of MatrixScan Count scanning phase for mid- and high-end devices ### Bug Fixes #### Barcode * Fixed an issue in BarcodeCount where the floating shutter button was not visible after setting shouldShowFloatingShutterButton to true. * Fixed a bug that was causing BarcodeFind to render barcodes filtered out by the Transformer as if they were valid targets. #### Id * Fixed support for UAE Esaad card * Sanitized name fields on ACT driver license to split FullName and populate first and last name properties * Added support for scanning MRZ from the back of Argentinian DN when using `FullDocumentScanner` #### Smart Label Capture * Fixed an issue in the `LabelCaptureValidationFlowOverlay` when using it with Jetpack Compose that caused focus loss when opening the keyboard * Added `LabelCaptureValidationFlowOverlay.ShouldHandleKeyboardInsetsInternally` for cases when customers don't want to follow official Android edge-to-edge and inset guidelines #### Core * Fixed issue where Camera now always returns a valid instance (backed by NoOpCamera when no native camera is available) * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. ## 8.2.1 **Released**: March 5, 2026 ### Bug Fixes #### Id * Sanitized name fields on ACT DL. Splits FullName to populate first and last name properties #### Smart Label Capture * Fixed LabelCaptureValidationFlowOverlay possible issue with Jetpack Compose that caused focus loss when opening the keyboard * Added LabelCaptureValidationFlowOverlay::ShouldHandleKeyboardInsetsInternally in case customers don't want to follow official Android guidelines for edge-to-edge and insets * Fixed a rare race condition ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Smart Label Capture * The Validation Flow, our ready‑to‑use workflow in Smart Label Capture for capturing and validating label data with minimal code, now features a completely redesigned user interface. The update improves ergonomics through a simplified API and highly requested customization options, making Smart Label Capture more intuitive and significantly reducing integration and customization effort across a wider range of use cases ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. * Fixed an issue where the successful hint in BarcodeFind is not displayed #### Id * Fixed an issue affecting MRZ scanning performance when using the user facing camera in portrait mode on Android * Fixed a memory issue leading to a persistent black screen during ID Capture startup * Treated Puerto Rico driver licenses as AAMVA to enforce barcode capture with FullScanner * Fixed a bug that would cause Canada Northwest Territories driver license scans to be incomplete #### Core * Fixed SparkScanView crash on Android when hiding the trigger button or changing certain UI properties in specific layout configurations, where the view now correctly handles dimension calculations during layout changes * Fixed an issue where the camera would not restart when opened from another app * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed an issue where some LabelCapture fields were being returned incorrectly on TS frameworks ### Deprecations #### Smart Label Capture * Deprecated some LabelCaptureValidationFlowSetting APIs: requiredFieldErrorText, missingFieldsHintText, manualInputButtonText, as those don't make sense anymore with the redesign of Validation Flow in 8.2 ## 8.1.5 **Released**: June 10, 2026 ### New Features #### Barcode * Added an option to configure the duration of BarcodeSequence's idle timeout. ### Bug Fixes #### Barcode * Fixed a memory leak in item-based scanning. #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a rare native crash (SIGABRT in BitTube::recvObjects) that could occur on Android during camera preview rendering. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. #### Core * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed crashes caused by RuntimeExceptions thrown by OEM camera code that are not part of the standard Android Camera API contract; these exceptions are now caught and logged instead of crashing. ## 8.1.3 **Released**: March 25, 2026 ### Bug Fixes #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. ## 8.1.2 **Released**: March 9, 2026 ### Bug Fixes #### Smart Label Capture * Fixed a rare race condition ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Id * Fixed a memory issue leading to a persistent black screen during ID Capture startup #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed a bug that could in rare cases produce a black screen when starting the camera ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Smart Scan Selection is now available in Barcode Capture. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. * Added, in `BarcodeAr`, a new annotation type (`BarcodeArResponsiveAnnotation`), which automatically switches between close-up and far-away info annotations based on the barcode's size on screen #### Id * Added NationalityISO property that maps results from Nationality field to country ISO code * Added RejectionDiagnosticJSON property to CapturedId to report debug info during Timeout rejections * Added support for new California DL, new South Carolina DL, Arizona Medical Marijuana Card, Kuwait Civil card, and new Texas DL * Our SDK can now scan the following documents both in single-side and double-side mode: - All Mexican DLs - Mexican Voter Cards #### Smart Label Capture * [Smart Label Capture](/sdks/net/android/label-capture/intro.md) is now available on .NET for Android. It enables multi-modal data capture, extracting barcode and text data from labels simultaneously and making complex data entry up to 7 times faster. Ideal for labels containing serial numbers, weights, or expiry dates, it improves accuracy, reduces errors, and prevents revenue loss from incorrect information. ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the ["strict" symbology extension](../symbology-properties#symbology-extension-descriptions) ### Behavioral Changes #### Barcode * Enabling the ["ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 ("Missing Resource") #### Core * Added the `CodeDuplicate` class to simplify setting special sentinel values for the CodeDuplicateFilter property across barcode scanning modes. ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Fixed a bug in the default color of BarcodeCapture highlights * Fixed an issue where popover annotations with HIGHLIGHT_TAP_AND_BARCODE_SCAN trigger could not be opened again * Fixed an issue in BarcodeSequence where camera would not be ON in portrait * Fixed an issue where SparkScan mini preview would sometimes stay in regular when entering target mode * Fixed the app becoming unresponsive after being in the background for extended periods * Fixed an issue where the successful notification in BarcodeFind was not displayed #### Id * Fixed a bug concerning return complete instead of cropped images on the back of EU driving licenses #### Core * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only ## 8.0.1 **Released**: January 14, 2026 ### Bug Fixes #### Barcode * Fixed an issue where the successful hint in BarcodeFind was not displayed * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. #### Core * We've fundamentally redesigned our .NET SDK's architecture to better align with the modern .NET ecosystem! * **Platform-Agnostic .net8.0 and net9.0 Targets**: The SDK now includes generic net8.0 and .net9.0 targets. This allows you to reference `Scandit.DataCapture.Core` and related packages directly from non-UI projects, such as class libraries or unit test projects. This makes it significantly easier to build modular, testable applications following principles like Clean Architecture. * **Mandatory SDK Initialization**: Due to the architectural changes, the SDK now requires explicit initialization at application startup. The public API has not changed, but you must add the corresponding initialization code to your application for the SDK to function correctly. #### ID * Added `ElementsToRetain` to `MobileDocumentScanner`: The set of data elements that the application intends to retain from scanned mobile documents. This information is used to set the `IntentToRetain` flag in ISO 18013-5 mdoc requests, which is required for legal compliance with data protection standards. An empty set indicates no elements will be retained, and `IntentToRetain` will be set to `false` for all fields. * ID Capture now supports full-frame anonymization. * The result of `decodeMobileDriverLicenseViz`, which is currently returned as part of the `VizResult` within `CapturedId`, will now be provided through a new field named `mobileDocumentOcr`. * Added `CapturedId::isCitizenPassport`, which indicates whether the passport was issued to a citizen of the issuing country. Returns `false` for travel documents such as refugee, stateless, or alien passports, and for any passports issued by organizations rather than states. * The following Chinese travel permits now extract VIZ + MIZ data during double-sided scanning flows: * CT - Taiwan Residents Mainland Travel Permit * W - Mainland Residents Exit-Entry Permit to and from Hong Kong and Macao * CD - Mainland Residents Entry-Exit Permit to and from Taiwan ### Behavioral Changes #### Barcode * Symbology `RM4SCC` has been renamed to `ROYAL_MAIL_4STATE`. * Changed the default highlight brush in SparkScan and Barcode Capture. #### ID * The configuration for the following documents has been changed as detailed below: * Australian mobile driver licenses (mDL) are now treated as normal documents, with no separate mode. * US Green Cards are now treated as residence permits. * Removed the deprecated API `DateResult::toDate`. Use `DateResult::toLocalDate` or `DateResult::toUtcDate` instead. * `fullName` now an optional field on all `IdCapture` result types and `capturedMrz` now an optional field on `MrzResult`. ### Bug Fixes #### ID * Fixed a bug that could get the scanner stuck when scanning a US passport card. ### Deprecations #### Core * `VideoResolution::Auto` is now deprecated. Please use the capture mode's `recommendedCameraSettings` for the best results. #### Barcode * All previously deprecated APIs have been removed in this release. ## 7.6.7 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/net/android/release-notes) --- ## Advanced Configurations # Advanced Configurations SparkScan is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are some cases where you might want to customize the behavior of SparkScan. This guide will show you how to add additional capabilities and further customize SparkScan to best fit your needs. ## Advanced Capabilities ### Hardware Button Control Allowing the end user to control the scanner with hardware buttons can be useful if your users typically wear gloves. It can also improve ergonomics in some workflows. SparkScan offers a built-in API to let you do this via [scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled). 10s) typically requires the users to interact with the UI to start scanning again. This is a good choice when you want to interrupt the scanning workflow (e.g. because a wrong barcode is scanned and some actions need to be performed). A small timeout (\ { if (isValidBarcode(barcode)) { return new SparkScanBarcodeSuccessFeedback(); } else { return new SparkScanBarcodeErrorFeedback( 'This code should not have been scanned', 60 * 1000, Color.fromHex('#FF0000'), new Brush(Color.fromHex('#FF0000'), Color.fromHex('#FF0000'), 1), ); } }, }; ``` You can have different error states triggered by different logic conditions. For example you can trigger an error state when a wrong barcode is scanned, and another one when a duplicate barcode is scanned. These errors can show different colors and have different timeouts. This error state for a code that should not have been scanned. This error state for a code that has been scanned more than once. --> ### Reject Barcodes To prevent scanning unwanted barcodes (like those already listed or from incorrect lots), use SparkScan’s built-in error state. Setting the [SDCSparkScanBarcodeErrorFeedback.resumeCapturingDelay](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/spark-scan-barcode-feedback.html#property-scandit.datacapture.barcode.spark.feedback.Error.ResumeCapturingDelay) parameter to `0` allows the user to continue scanning immediately without pausing on rejected codes. ## UI Customization :::tip Please refer to [SparkScanView](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) for the full list of parameters. ::: import Customization from '../../../../partials/advanced/_sparkscan-customization.mdx'; ## Workflow Options This section explains all the available options to configure SparkScan to best fit your case, in case you found something that didn't work well in the default configuration (that remains our recommended option). Developers can set a combination of scanning mode, scanning behavior and camera preview behavior - defining the initial state of the scanner. This can be done by setting the default scanning mode (SDCSparkScanViewSettings.DefaultScanningMode). This combination allows for flexible configurations to suit different scanning needs. ### Scanning Mode The scanning mode determines the programmatic presence of an aimer in the preview to help with precision scanning. | Mode | Description | | ----------- | --------------------------------------------------- | | **Default** | Generally recommended. This mode will display a small camera preview to aid with aiming. The preview size and zoom level can be adjusted as needed. User can aim easily at the intended barcode. | | **Target** | This mode will always add an aimer to the camera preview to precisely select the barcode to scan. This is recommended only when selecting among many close barcodes is the common task. | :::tip Even in the *Default* mode, SparkScan will automatically show an aimer when multiple barcodes are present in the view and no clear intention from the user to scan a single one is recorded ([`SDCSparkScanSettings.ScanIntention`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/spark-scan-settings.html#property-scandit.datacapture.barcode.spark.SparkScanSettings.ScanIntention)). Enabling the *Target* mode will simply force this "precision selection" state to be on at all time. ::: ### Scanning Behavior The scanning behavior determines how barcodes are scanned - one at a time or continuously. | Behavior | Description | | ------------------- | ---------------------------------------------------------- | | **Single scan** | Scan one barcode at a time. The user needs to trigger the scanner every time to scan a barcode. This allows for a more controlled scanning and lower battery consumption. | | **Continuous scan** | Scan barcodes consecutively. The user needs to trigger the scanner once and barcodes will be scanned without any further interaction before each scan. This allows for a smoother experience when multiple barcodes need to be scanned consecutively. | :::tip Users can enable continuous scanning by holding down the trigger button. This gesture can be disabled (`SDCSparkScanViewSettings.HoldToScanEnabled`). ::: ### Preview Behavior The preview behavior determines how the camera preview behaves when the scanner is not actively scanning. | Behavior | Description | | -------------- | -------------------------- | | **Default** | Preview fades away when the scanner is off. This lets the user check important information displayed by the app and reduces battery consumption. | | **Persistent** | Preview remains visible, but darkened, even when the scanner is off. This is useful for scenarios where you want to select a barcode (among many) or need to look through the preview at all times (to ensure the right scan) - especially if used in conjunction with the target mode. | --- ## Get Started # Get Started In this guide you will learn step-by-step how to add SparkScan to your application by: - Create a new Data Capture Context instance. - Configure the Spark Scan Mode. - Create the SparkScanView with the desired settings and bind it to the application’s lifecycle. - Register the listener to be informed when new barcodes are scanned and update your data whenever this event occurs. ## Create a New Data Capture Context Instance The first step to add capture capabilities to your application is to create a new [Data Capture Context](https://docs.scandit.com/data-capture-sdk/dotnet.android/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the SparkScan Mode The SparkScan Mode is configured through SparkScanSettings and allows you to register one or more listeners that are informed whenever a new barcode is scanned. For this tutorial, we will set up SparkScan for scanning EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```csharp SparkScanSettings settings = new SparkScanSettings(); HashSet symbologies = new HashSet() { Symbology.Ean13Upca }; settings.EnableSymbologies(symbologies); ``` Next, create a SparkScan instance with the settings initialized in the previous step: ```csharp SparkScan sparkScan = new SparkScan(settings); ``` ## Setup the Spark Scan View The SparkScan built-in user interface includes the camera preview and scanning UI elements. These guide the user through the scanning process. The [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/spark-scan-view.html) appearance can be customized through [`SparkScanViewSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/spark-scan-view-settings.html). ```csharp SparkScanViewSettings viewSettings = new SparkScanViewSettings(); // setup the desired appearance settings by updating the fields in the object above ``` See the [SparkScan Workflow Options](./advanced.md#workflow-options) section for more information. By adding a [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/spark-scan-view.html), the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/spark-scan-view.html) to your view hierarchy: Construct a new SparkScan view. The SparkScan view is automatically added to the provided parentView (preferably an instance of [SparkScanCoordinatorLayout](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanCoordinatorLayout)): ```csharp SparkScanView sparkScanView = SparkScanView.Create(parentView, dataCaptureContext, sparkScan, viewSettings); ``` When developing on MAUI the SparkScan view should be added as the last item to [AbsoluteLayout](https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/absolutelayout) or [RelativeLayout](https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/relativelayout), to make sure other UI components are visible. ```xml ``` When developing on MAUI, make sure to call SparkScanView.OnAppearing and SparkScanView.OnDisappearing in your [Page.OnAppearing](https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.page.onappearing) and [Page.OnDisappearing](https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.page.ondisappearing) callbacks, to make sure that start up time is optimal and scanning is stopped when the app is going in the background. ```csharp protected override void OnAppearing() { base.OnAppearing(); this.SparkScanView.OnAppearing(); } protected override void OnDisappearing() { base.OnDisappearing(); this.SparkScanView.OnDisappearing(); } ``` Additionally, make sure to call sparkScanView.onPause() and sparkScanView.onResume() in your Fragment/Activity onPause and onResume callbacks. You have to call these for the correct functioning of the SparkScanView. ```csharp protected override void OnPause() { sparkScanView.OnPause(); base.OnPause(); } protected override void OnResume() { sparkScanView.OnResume(); base.OnResume(); } ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [ISparkScanListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface and register the listener to the SparkScan mode. ```csharp // Register self as a listener to monitor the spark scan session. sparkScan.AddListener(this); ``` [ISparkScanListener.OnBarcodeScanned()](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/spark-scan-listener.html#method-scandit.datacapture.barcode.spark.ISparkScanListener.OnBarcodeScanned) is called when a new barcode has been scanned. This result can be retrieved from [SparkScanSession.NewlyRecognizedBarcode](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/spark-scan-session.html#property-scandit.datacapture.barcode.spark.SparkScanSession.NewlyRecognizedBarcode). ```csharp public void OnBarcodeScanned(SparkScan sparkScan, SparkScanSession session, IFrameData? data) { Barcode? barcode = session.NewlyRecognizedBarcode; if (barcode == null) { return; } // This method is invoked from a recognition internal thread. // Run the specified action in the UI thread to update the internal barcode list. RunOnUiThread(() => { // Update the internal list and the UI with the barcode retrieved above this.latestBarcode = barcode; }); } ``` Alternatively to register [ISparkScanListener](https://docs.scandit.com/data-capture-sdk/dotnet.android/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface it is possible to subscribe to corresponding events. For example: ```csharp sparkScan.BarcodeScanned += (object sender, SparkScanEventArgs args) => { Barcode? barcode = args.Session.NewlyRecognizedBarcode; if (barcode == null) { return; } // This method is invoked from a recognition internal thread. // Run the specified action in the UI thread to update the internal barcode list. RunOnUiThread(() => { // Update the internal list and the UI with the barcode retrieved above this.latestBarcode = barcode; }); }; ``` ## Scan Some Barcodes Now that you’re up and running, go find some barcodes to scan. Don’t feel like getting up from your desk? Here’s a [handy pdf of barcodes](https://github.com/Scandit/.github/blob/main/images/PrintTheseBarcodes.pdf) you can print out. --- ## About SparkScan # About SparkScan SparkScan is our pre-built smartphone scanning interface designed for high-performance barcode scanning. It fits on top of any smartphone application, providing an intuitive user interface for simple, fast and ergonomic scanning in scan-intensive workflows such as inventory management in retail, or goods receiving in logistics. SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs. ## UI Overview The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience. Two main elements compose the UI: ![SparkScan UI](/img/sparkscan/features_web.png) - **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc). - **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space. There are additional UI elements available for displaying additional scanning modes, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section. ## Workflow Description When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use. To start scanning, the user can simply tap on it. When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app). In the default configuration: - Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away. - Tapping on the trigger button or the mini preview will restart immediately the scanner. Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state. If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released. List building use case using SparkScan. The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field. But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more. ## Supported Symbologies SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx). ## AI-Powered Features SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide. --- ## Installation import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Installation This guide shows you how to add the Scandit Data Capture SDK to current existing project. ## Prerequisites - The latest stable version of [Visual Studio](https://visualstudio.microsoft.com/). - A [.NET SDK](https://dotnet.microsoft.com/en-us/download/dotnet/6.0). - A .NET for iOS project with minimum iOS deployment target of 15.0 or higher. :::note ID Capture requires a minimum iOS deployment target of 15.0. ::: - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). :::tip Android devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ### Internal Dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps-no-label-capture.mdx'; ## Get a License Key 1. [Sign up](https://ssl.scandit.com/dashboard/sign-up?p=test) or [Sign in](https://ssl.scandit.com/dashboard/sign-in) to your Scandit account 2. Create a project 3. Create a license key If you have a paid subscription, please reach out to [Scandit Support](mailto:support@scandit.com) if you need a new license key. ## Add the SDK The Scandit Data Capture SDK is distributed as [NuGet packages](https://www.nuget.org/packages?q=scandit). You will always need to add the `Scandit.DataCapture.Core` package, which contains the core functionality used by the other data capture packages. When developing MAUI applications you will also need to add the `Scandit.DataCapture.Core.Maui` package. In addition, depending on the data capture task, you will need a reference to: | Functionality | Description | Required Module(s) | | --- | --- | --- | | Barcode Capture | [ScanditBarcodeCapture API](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api.html) if you want to use barcode-related functionality, such as barcode capture or MatrixScan. | _com.scandit.datacapture:barcode_ | | Parser | [ScanditParser API](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/api.html) if you want to parse data strings, for instance, as found in barcodes, into a set of key-value mappings. | _com.scandit.datacapture:parser_ | | ID Capture | [ScanditIdCapture API](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api.html) if you want to scan personal identification documents, such as identity cards, passports or visas. | _com.scandit.datacapture:id_ | :::tip You can safely remove `Scandit.DataCapture.Barcode`, `Scandit.DataCapture.Parser`, or `Scandit.DataCapture.IdCapture` dependencies if you are not going to use their features. ::: ## Additional Information ### Camera Permissions When using the Scandit Data Capture SDK you will want to set the camera as the frame source for various capture modes. On .NET for iOS, you have to set the “Privacy - Camera Usage Description” field in the Info.plist file. When using the Scandit Data Capture SDK in MAUI application additionally you have to request camera permissions in your own application before starting scanning. To see how you can achieve this, take a look at our [samples](https://github.com/Scandit/datacapture-dotnet-samples/tree/master). import OSSLicense from '../../../partials/_third-party-licenses-csharp.mdx'; --- ## Agent Skills import SkillsPage from '@site/src/components/SkillsPage'; # Agent Skills for .NET iOS --- ## Configure Barcode Symbologies # Configure Barcode Symbologies import Intro from '../../../../partials/configure-symbologies/_intro.mdx' ## Enable the Symbologies You Want to Read import EnableSymbologies from '../../../../partials/configure-symbologies/_enable-symbologies.mdx' The following code shows how to enable scanning Code 128 codes for Barcode Capture: ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); settings.EnableSymbology(Symbology.Code128, true); ``` import CapturePresents from '../../../../partials/configure-symbologies/_capture-presents.mdx' ## Configure the Active Symbol Count Barcode symbologies (such as Code 128, Code 39, Code 93, or Interleaved Two of Five) can store variable-length data. For example, Code 39 can be used to store a string from 1 to 40-50 symbols. There is no fixed upper limit, though there are practical limitations to the code’s length for it to still be conveniently readable by barcode scanners. For performance reasons, the Scandit Data Capture SDK limits the [possible symbol range](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.ActiveSymbolCounts) for variable-length symbologies. If you want to read codes that are shorter/longer than the specified default range or you want to tailor your app to only read codes of a certain length, you need to change the active symbol count of the symbology to accommodate the data length you want to use in your application. The below lines of code show how to change the active symbol count for Code 128 to read codes with 6, 7 and 8 symbols. ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); SymbologySettings symbologySettings = settings.GetSymbologySettings(Symbology.Code128); HashSet activeSymbolCounts = new HashSet(new short[] { 6, 7, 8 }); symbologySettings.ActiveSymbolCounts = activeSymbolCounts; ``` import CalculateSymbolCount from '../../../../partials/configure-symbologies/_calculate-symbol-count.mdx' ## Read Bright-on-Dark Barcodes Most barcodes are printed using dark ink on a bright background. Some symbologies allow the colors to be inverted and can also be printed using bright ink on a dark background. This is not possible for all symbologies as it could lead to false reads when the symbology is not designed for this use case. See [symbology properties](../symbology-properties.mdx) to learn which symbologies allow color inversion. When you also want to read bright-on-dark codes, color-inverted reading for that symbology must also be enabled (see [SymbologySettings.ColorInvertedEnabled](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.IsColorInvertedEnabled)): ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); SymbologySettings symbologySettings = settings.GetSymbologySettings(Symbology.Code128); symbologySettings.ColorInvertedEnabled = true; ``` ## Enforce Checksums Some symbologies have a mandatory checksum that will always be enforced while others only have optional [checksums](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/checksum.html#enum-scandit.datacapture.barcode.Checksum). Enforcing an optional checksum will reduce false positives as an additional check can be performed. When enabling a checksum you have to make sure that the data of your codes contains the calculated checksum otherwise the codes get discarded as the checksum doesn’t match. All available checksums per symbology can be found in [symbology properties](../symbology-properties.mdx). You can enforce a specific checksum by setting it through [SymbologySettings.Checksums](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.Checksums): ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); SymbologySettings symbologySettings = settings.GetSymbologySettings(Symbology.Code39); symbologySettings.Checksums = Checksum.Mod43; ``` ## Enable Symbology-Specific Extensions Some symbologies allow further configuration. These configuration options are available as symbology extensions that can be enabled/disabled for each symbology individually. Some extensions affect how the data in the code is formatted, others allow for more relaxed recognition modes that are disabled by default to eliminate false reads. All available extensions per symbology and a description of what they do can be found in the documentation on [symbology properties](../symbology-properties.mdx). To enable/disable a symbology extension, use [SymbologySettings.SetExtensionEnabled()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/symbology-settings.html#method-scandit.datacapture.barcode.SymbologySettings.SetExtensionEnabled). The following code shows how to enable the full ASCII extension for Code 39. ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); SymbologySettings symbologySettings = settings.GetSymbologySettings(Symbology.Code39); symbologySettings.SetExtensionEnabled("full_ascii", true); ``` This extension allows Code 39 to encode all 128 ASCII characters instead of only the 43 characters defined in the standard. The extension is disabled by default as it can lead to false reads when enabled. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Barcode Capture to your application. The general steps are: - Creating a new Data Capture Context instance - Create your barcode capture settings and enable the barcode symbologies you want to read - Create a new barcode capture mode instance and initialize it - Register a barcode capture listener to receive scan events - Process successful scans according to your application’s needs and decide whether more codes will be scanned or the scanning process should be stopped - Obtain a camera instance and set it as the frame source on the data capture context - Display the camera preview by creating a data capture view - If displaying a preview, optionally create a new overlay and add it to data capture view for better visual feedback ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext context = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Scanning Behavior Barcode scanning is orchestrated by the [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) [data capture mode](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). This class is the main entry point for scanning barcodes. It is configured through [BarcodeCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) that will get informed whenever new codes have been recognized. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```csharp BarcodeCaptureSettings settings = BarcodeCaptureSettings.Create(); HashSet symbologies = new HashSet() { Symbology.Code128, Symbology.Code39, Symbology.Qr, Symbology.Ean8, Symbology.Upce, Symbology.Ean13Upca }; settings.EnableSymbologies(symbologies); ``` If you are not disabling barcode capture immediately after having scanned the first code, consider setting the [BarcodeCaptureSettings.CodeDuplicateFilter](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture-settings.html#property-scandit.datacapture.barcode.BarcodeCaptureSettings.CodeDuplicateFilter) to `TimeSpan.FromMilliseconds(500)` or even `CodeDuplicate.ReportDataAndSymbologyOnlyOnce` (equivalent to `TimeSpan.FromSeconds(-1)`) if you do not want codes to be scanned more than once. Next, create a [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance with the settings initialized in the previous step: ```csharp barcodeCapture = BarcodeCapture.Create(context, settings); ``` ## Register the Barcode Capture Listener To get informed whenever a new code has been recognized, add a [IBarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) through [BarcodeCapture.AddListener()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.AddListener) and implement the listener methods to suit your application’s needs. First implement the [IBarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) interface. For example: ```csharp public void OnBarcodeScanned(BarcodeCapture barcodeCapture, BarcodeCaptureSession session, IFrameData frameData) { Barcode? barcode = session.NewlyRecognizedBarcode; // Do something with the barcode // Dispose the frame when you have finished processing it. If the frame is not properly disposed, // different issues could arise, e.g. a frozen, non-responsive, or "severely stuttering" video feed. frameData.Dispose(); } ``` Then add the listener: ```csharp barcodeCapture.AddListener(this); ``` Alternatively to register [IBarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) interface it is possible to subscribe to corresponding events. For example: ```csharp barcodeCapture.BarcodeScanned += (object sender, BarcodeCaptureEventArgs args) => { Barcode? barcode = args.Session.NewlyRecognizedBarcode; // Do something with the barcode }; ``` ### Rejecting Barcodes To prevent scanning unwanted codes, you can reject them by adding the desired logic to the `didScan` method. This will prevent the barcode from being added to the session and will not trigger the `didUpdateSession` method. The example below will only scan barcodes beginning with the digits `09` and ignore all others, using a transparent brush to distinguish a rejected barcode from a recognized one: ```csharp ... if (barcode.Data?.StartsWith("09:") == false) { this.overlay.Brush = Brush.TransparentBrush; return; } ... ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/security-privacy?tabs=macos#:~:text=NSCameraUsageDescription) key in your app’s Info.plist file. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```csharp camera = Camera.GetDefaultCamera(); camera?.ApplySettingsAsync(BarcodeCapture.RecommendedCameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.SetFrameSourceAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```csharp context.SetFrameSourceAsync(camera); ``` The camera is off by default and must be turned on. This is done by calling [IFrameSource.SwitchToDesiredStateAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```csharp camera?.SwitchToDesiredStateAsync(FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```csharp DataCaptureView dataCaptureView = DataCaptureView.Create(dataCaptureContext, View.Bounds); View.AddSubview(dataCaptureView); ``` Alternatively you can use a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) from XAML in your MAUI application. For example: ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); // Initialization of DataCaptureView happens on handler changed event. dataCaptureView.HandlerChanged += DataCaptureViewHandlerChanged; } private void DataCaptureViewHandlerChanged(object? sender, EventArgs e) { // Your dataCaptureView configuration goes here, e.g. add overlay } } ``` For MAUI development add [Scandit.DataCapture.Core.Maui](https://www.nuget.org/packages/Scandit.DataCapture.Core.Maui) NuGet package into your project. To visualize the results of barcode scanning, the following [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) can be added: ```csharp BarcodeCaptureOverlay overlay = BarcodeCaptureOverlay.Create(barcodeCapture, dataCaptureView); ``` ## Disabling Barcode Capture To disable barcode capture, for instance as a consequence of a barcode being recognized, set [BarcodeCapture.Enabled](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-capture.html#property-scandit.datacapture.barcode.BarcodeCapture.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## Barcode Generator is not available on .NET for iOS # Barcode Generator is not available on .NET for iOS The Barcode Generator module is not available for the .NET for iOS SDK. To view documentation for a platform that supports Barcode Generator, use the framework switcher at the top of the page. --- ## Get Started # Get Started :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/net/ios/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: In this guide you will learn step-by-step how to add Barcode Selection to your application. The general steps are: - Create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) instance, initialized with your license key. - Create a [barcode selection settings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and choose the right configuration. - Create a new [barcode selection mode](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance and initialize it with the settings created above. - Register a [barcode selection listener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-selection-basic-overlay.html#class-scandit.datacapture.barcode.selection.ui.BarcodeSelectionBasicOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## Create the Data Capture Context The first step to add capture capabilities to your application is to create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext context = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Selection Behavior _Symbologies_ Barcode selection is orchestrated by the [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) [data capture mode](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). It is configured through [BarcodeSelectionSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) that will get informed whenever new codes have been selected. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```csharp BarcodeSelectionSettings settings = BarcodeSelectionSettings.Create(); HashSet symbologies = new HashSet() { Symbology.Qr, Symbology.Ean8, Symbology.Upce, Symbology.Ean13Upca }; settings.EnableSymbologies(symbologies); ``` _Selection Types_ The behavior of Barcode Selection can be changed by using a different [selection type](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-type.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionType). This defines the method used by [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) to select codes. Currently there are two types. If you want the user to select barcodes with a tap, then use [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection). This selection type can automatically freeze the camera preview to make the selection easier. You can configure the freezing behavior via [BarcodeSelectionTapSelection.FreezeBehavior](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.FreezeBehavior). With [BarcodeSelectionTapSelection.TapBehavior](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.TapBehavior) you can decide if a second tap on a barcode means that the barcode is unselected or if it is selected another time (increasing the counter). :::note Using [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection) requires the MatrixScan add-on. ::: If you want the selection to happen automatically based on where the user points the camera, then use [BarcodeSelectionAimerSelection](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-aimer-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAimerSelection). It is possible to choose between two different [selection strategies](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-strategy.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionStrategy). Use [BarcodeSelectionAutoSelectionStrategy](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAutoSelectionStrategy) if you want the barcodes to be selected automatically when aiming at them as soon as the intention is understood by our internal algorithms. Use [BarcodeSelectionManualSelectionStrategy](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionManualSelectionStrategy) if you want the barcodes to be selected when aiming at them and tapping anywhere on the screen. _Single Barcode Auto Detection_ If you want to automatically select a barcode when it is the only one on screen, turn on [BarcodeSelectionSettings.SingleBarcodeAutoDetection](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-settings.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionSettings.SingleBarcodeAutoDetection). _Creating the mode_ Next, create a [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance with the settings initialized in the previous step: ```csharp barcodeSelection = BarcodeSelection.Create(context, settings); ``` ## Register the Barcode Selection Listener To get informed whenever a new code has been recognized, add a [IBarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) through [BarcodeSelection.AddListener()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection.html#method-scandit.datacapture.barcode.selection.BarcodeSelection.AddListener) and implement the listener methods to suit your application’s needs. First implement the [IBarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) interface. For example: ```csharp public class MyBarcodeSelectionListener : IBarcodeSelectionListener { public void OnObservationStarted(BarcodeSelection barcodeSelection) { // Called when Barcode Selection is started. // We don't use this callback in this guide. } public void OnObservationStopped(BarcodeSelection barcodeSelection) { // Called when Barcode Selection is stopped. // We don't use this callback in this guide. } public void OnSessionUpdated( BarcodeSelection barcodeSelection, BarcodeSelectionSession session, IFrameData? frameData) { // Called every new frame. // We don't use this callback in this guide. // Dispose the frame when you have finished processing it. If the frame is not properly disposed, // different issues could arise, e.g. a frozen, non-responsive, or "severely stuttering" video feed. frameData?.Dispose(); } public void OnSelectionUpdated( BarcodeSelection barcodeSelection, BarcodeSelectionSession session, IFrameData? frameData) { IList newlySelectedBarcodes = session.NewlySelectedBarcodes; IList selectedBarcodes = session.SelectedBarcodes; IList newlyUnselectedBarcodes = session.NewlyUnselectedBarcodes; // Do something with the retrieved barcodes. // Dispose the frame when you have finished processing it. If the frame is not properly disposed, // different issues could arise, e.g. a frozen, non-responsive, or "severely stuttering" video feed. frameData?.Dispose(); } } ``` Then add the listener: ```csharp barcodeSelection.AddListener(new MyBarcodeSelectionListener()); ``` Alternatively to register [IBarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) interface it is possible to subscribe to corresponding events. For example: ```csharp barcodeSelection.SelectionUpdated += (object sender, BarcodeSelectionEventArgs args) => { IList newlySelectedBarcodes = args.Session.NewlySelectedBarcodes; IList selectedBarcodes = args.Session.SelectedBarcodes; IList newlyUnselectedBarcodes = args.Session.NewlyUnselectedBarcodes; // Do something with the retrieved barcodes. }; ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/security-privacy?tabs=macos#:~:text=NSCameraUsageDescription) key in your app’s Info.plist file. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```csharp var cameraSettings = BarcodeSelection.RecommendedCameraSettings; // Depending on the use case further camera settings adjustments can be made here. camera = Camera.GetDefaultCamera(); camera?.ApplySettingsAsync(cameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.SetFrameSourceAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```csharp context.SetFrameSourceAsync(camera); ``` The camera is off by default and must be turned on. This is done by calling [IFrameSource.SwitchToDesiredStateAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```csharp camera?.SwitchToDesiredStateAsync(FrameSourceState.On); ``` ## Disabling Barcode Selection To disable barcode selection, for instance when the selection is complete, set [BarcodeSelection.Enabled](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelection.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## About Barcode Selection # About Barcode Selection :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/net/ios/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: Barcode Selection enables you to increase scanning accuracy and prevent users from scanning the wrong code in scenarios where there are multiple barcodes present, such as a crowded shelf, an order catalog with barcodes printed closely together, or a label with multiple barcodes. Barcode Selection provides two key capabilities: - **Aim to Select** allows users to select one code at a time. This is especially useful for one-handed operation. - **Tap to Select** is a quick way for users to select several codes from the same view. Selection is done by tapping on highlighted barcodes in the live camera preview or on a frozen screen. :::warning Barcode Selection does not support handling of duplicate codes. If a code appears twice in the visible preview both instances will be marked as selected even if only one of them was selected. ::: --- ## Advanced Configurations # Advanced Configurations There are several advanced configurations that can be used to customize the behavior of the ID Capture SDK and enable additional features. ## Configure Data Anonymization By default, data extracted from documents is anonymized according to local regulations. See [Anonymized Documents](/sdks/net/ios/id-capture/supported-documents.md#anonymized-documents) for more information. That means certain data from certain fields won’t be returned, even if it’s present on a document. You control the anonymization level with the following setting: ```csharp // Default value: settings.AnonymizationMode = IdAnonymizationMode.FieldsOnly; // Sensitive data is additionally covered with black boxes on returned images: settings.AnonymizationMode = IdAnonymizationMode.FieldsAndImages; // Only images are anonymized: settings.AnonymizationMode = IdAnonymizationMode.ImagesOnly; // No anonymization: settings.AnonymizationMode = IdAnonymizationMode.None; ``` ## Document Capture Zones By default, a new instance of [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) creates a single-sided scanner type with no accepted or rejected documents. To change this, set the `Scanner` property on `IdCaptureSettings` to an [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-scanner.html) configured with either a [SingleSideScanner](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-scanner.html#single-side-scanner) or [FullDocumentScanner](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-scanner.html#full-document-scanner). The `FullDocumentScanner` extracts all document information by default. If using the `SingleSideScanner`, you can specify the document zones to extract via its constructor parameters: ```csharp // To extract data from barcodes on IDs settings.Scanner = new IdCaptureScanner(new SingleSideScanner(barcode: true, machineReadableZone: false, visualInspectionZone: false), mobileDocument: null); // To extract data from the visual inspection zone (VIZ) on IDs settings.Scanner = new IdCaptureScanner(new SingleSideScanner(barcode: false, machineReadableZone: false, visualInspectionZone: true), mobileDocument: null); // To extract data from the machine-readable zone (MRZ) on IDs settings.Scanner = new IdCaptureScanner(new SingleSideScanner(barcode: false, machineReadableZone: true, visualInspectionZone: false), mobileDocument: null); ``` ## Configure Accepted and Rejected Documents To configure the documents that should be accepted and/or rejected, set the `AcceptedDocuments` and `RejectedDocuments` properties in `IdCaptureSettings`. These properties take a list of [IIdCaptureDocument](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-document.html) instances (e.g. `Passport`, `DriverLicense`, `IdCard`) combined with the [IdCaptureRegion](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-region.html#enum-scandit.datacapture.id.IdCaptureRegion) enum to enable highly flexible document filtering. For example, to accept only US Driver Licenses: ```csharp settings.AcceptedDocuments = new List { new DriverLicense(IdCaptureRegion.Us) }; ``` Or to accept all Passports *except* those from the US: ```csharp settings.AcceptedDocuments = new List { new Passport(IdCaptureRegion.Any) }; settings.RejectedDocuments = new List { new Passport(IdCaptureRegion.Us) }; ``` ## ID Images Your use can may require that you capture and extract images of the ID document. Use the [IdImageType](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-image-type.html#enum-scandit.datacapture.id.IdImageType) enum to specify the images you want to extract from the `CapturedId` object For the full frame of the document, you can use [`setShouldPassImageTypeToResult`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-settings.html#method-scandit.datacapture.id.IdCaptureSettings.SetShouldPassImageTypeToResult) when creating the `IdCaptureSettings` object. This will pass the image type to the result, which you can then access in the `CapturedId` object. ## Callbacks and Scanning Workflows The ID Capture Listener provides two callbacks: `onIdCaptured` and `onIdRejected`. The `onIdCaptured` callback is called when an acceptable document is successfully captured, while the `onIdRejected` callback is called when a document is captured but rejected. For a successful capture, the `onIdCaptured` callback provides a `CapturedId` object that contains the extracted information from the document. This object is specific to the type of document scanned. For example, a `CapturedId` object for a US Driver License will contain different fields than a `CapturedId` object for a Passport. For a rejected document, a [RejectionReason](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) is provided in the `onIdRejected` callback to help you understand why the document was rejected and to take appropriate action. These are: * NOT_ACCEPTED_DOCUMENT_TYPE: The document is not in the list of accepted documents. In this scenario, you could direct the user to scan a different document. * INVALID_FORMAT: The document is in the list of accepted documents, but the format is invalid. In this scenario, you could direct the user to scan the document again. * DOCUMENT_VOIDED: The document is in the list of accepted documents, but the document is voided. In this scenario, you could direct the user to scan a different document. * TIMEOUT: The document was not scanned within the specified time. In this scenario, you could direct the user to scan the document again. ## Detect Fake IDs *ID Validate* is a fake ID detection software. It currently supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). Fake ID detection can be performed automatically using the following settings: * [IdCaptureSettings.rejectForgedAamvaBarcodes](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectForgedAamvaBarcodes): Automatically rejects documents whose AAMVA barcode fails authenticity validation. * [IdCaptureSettings.rejectInconsistentData](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectInconsistentData): Automatically rejects documents whose human‑readable data does not match the data encoded in the barcode or MRZ. To enable ID validation for your subscription, please reach out to [Scandit Support](mailto:support@scandit.com). --- ## Get Started # Get Started This page will guide you through the process of adding ID Capture to your .NET application. ID Capture is a mode of the Scandit Data Capture SDK that allows you to capture and extract information from personal identification documents, such as driver's licenses, passports, and ID cards. The general steps are: - Creating a new Data Capture Context instance - Accessing a Camera - Configuring the Capture Settings - Implementing a Listener to Receive Scan Results - Setting up the Capture View and Overlay - Starting the Capture Process :::warning Using ID Capture at the same time as other modes (e.g. Barcode Capture) is not supported. ::: ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](/sdks/net/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import IdModuleOverview from '../../../../partials/get-started/_id-module-overview.mdx'; ## Create the Data Capture Context The first step to add capture capabilities to your application is to create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext context = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Add the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/camera.html#class-scandit.datacapture.core.Camera): ```csharp camera = Camera.GetDefaultCamera(); if (camera != null) { // Use the settings recommended by id capture. camera.ApplySettingsAsync(IdCapture.RecommendedCameraSettings); context.SetFrameSourceAsync(camera); } ``` ## Create ID Capture Settings Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scanner type and the accepted and rejected documents. Check [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) for all the available options. :::tip By default, [anonymized data](./advanced.md#configure-data-anonymization) is not returned in accordance with local regulations for specific documents. This setting can be disabled for testing purposes, but be sure to comply with local laws and requirements in production. ::: ```csharp IdCaptureSettings settings = new IdCaptureSettings { AcceptedDocuments = new List { new Passport(IdCaptureRegion.Any), new DriverLicense(IdCaptureRegion.Any), }, RejectedDocuments = new List { new IdCard(IdCaptureRegion.Any), }, }; ``` ## Implement the Listener To receive scan results, implement [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener). Capture results are delivered as a [CapturedId](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/captured-id.html#class-scandit.datacapture.id.CapturedId). This class contains data common for all kinds of personal identification documents. For more specific information, use its non-null result properties (e.g. [CapturedId.barcode](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/captured-id.html#property-scandit.datacapture.id.CapturedId.Barcode)). ```csharp public class MyListener : IIdCaptureListener { public void OnIdCaptured(IdCapture capture, CapturedId capturedId) { // The recognized fields of the captured ID can vary based on the type. if (capturedId.Mrz != null) { // Handle the information extracted from the MRZ. } else if (capturedId.Viz != null) { // Handle the information extracted from the VIZ. } else if (capturedId.Barcode != null) { // Handle the information extracted from the barcode. } } public void OnIdRejected(IdCapture capture, CapturedId? capturedId, RejectionReason reason) { // Implement to handle a document rejected by IdCapture. } } ``` Alternatively to register [IIdCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener) interface it is possible to subscribe to corresponding events. For example: ```csharp idCapture.IdCaptured += (object sender, IdCapturedEventArgs args) => { CapturedId capturedId = args.CapturedId; // The recognized fields of the captured ID can vary based on the type. if (capturedId.Mrz != null) { // Handle the information extracted from the MRZ. } else if (capturedId.Viz != null) { // Handle the information extracted from the VIZ. } else if (capturedId.Barcode != null) { // Handle the information extracted from the barcode. } }; ``` Create a new ID Capture mode with the chosen settings. Then register the listener: ```csharp idCapture = IdCapture.Create(context, settings); idCapture.AddListener(new MyListener()) ``` ## Set up Capture View and Overlay When using the built-in camera as [frameSource](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/frame-source.html#interface-scandit.datacapture.core.IFrameSource), you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```csharp DataCaptureView dataCaptureView = DataCaptureView.Create(dataCaptureContext, View.Bounds); View.AddSubview(dataCaptureView); ``` Alternatively you can use a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) from XAML in your MAUI application. For example: ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); // Initialization of DataCaptureView happens on handler changed event. dataCaptureView.HandlerChanged += DataCaptureViewHandlerChanged; } private void DataCaptureViewHandlerChanged(object? sender, EventArgs e) { // Your dataCaptureView configuration goes here, e.g. add overlay } } ``` For MAUI development add the [Scandit.DataCapture.Core.Maui](https://www.nuget.org/packages/Scandit.DataCapture.Core.Maui) NuGet package into your project. Then create an instance of [IdCaptureOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) attached to the view: ```csharp overlay = IdCaptureOverlay.Create(idCapture, dataCaptureView); ``` The overlay chooses the displayed UI automatically, based on the selected [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings). If you prefer to show a different UI or to temporarily hide it, set the appropriate [IdCaptureOverlay.idLayout](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/ui/id-capture-overlay.html#property-scandit.datacapture.id.ui.IdCaptureOverlay.IdLayout). ## Start the Capture Process Finally, turn on the camera to start scanning: ```csharp camera.SwitchToDesiredStateAsync(FrameSourceState.On); ``` And this is it. You can now scan documents. --- ## About ID Capture import AboutIdCapture from '../../../../partials/intro/_about-id-capture.mdx'; --- ## Supported Documents ## ID Scanning Supported Documents Scandit ID Capture provides various [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/dotnet.ios/id-capture/api/id-capture-scanner.html#id-capture-scanner) types, each designed for specific scanning workflows. These workflows can involve scanning either specific parts of a document or the entire document, including both the front and back sides. This section details the types of documents supported by each scanner type. import IdDocumentsFull from '../../../../partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from '../../../../partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents import IdValidateDocuments from '../../../../partials/advanced/_id-documents-validate.mdx'; --- ## Advanced Configurations import ValidationFlowHowItWorks from '../../../../partials/advanced/_validation-flow-how-it-works.mdx'; import ValidationFlowCustomButtons from '../../../../partials/advanced/_validation-flow-custom-buttons.mdx'; import ValidationFlowTypingHints from '../../../../partials/advanced/_validation-flow-typing-hints.mdx'; import ValidationFlowCloudVLM from '../../../../partials/advanced/_validation-flow-cloud-vlm.mdx'; import ReceiptScanning from '../../../../partials/advanced/_receipt-scanning.mdx'; import ValidationFlowRequiredOptional from '../../../../partials/advanced/_validation-flow-required-optional.mdx'; import ValidationFlowCustomToasts from '../../../../partials/advanced/_validation-flow-custom-toasts.mdx'; import ValidationFlowCustomField from '../../../../partials/advanced/_validation-flow-custom-field.mdx'; # Advanced Configurations ## Customization of the Overlays ### Basic Overlay To customize the appearance of an overlay you can implement a [ILabelCaptureBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/ui/label-capture-basic-overlay-listener.html#interface-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener) and/or [ILabelCaptureAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/ui/label-capture-advanced-overlay-listener.html) interface, depending on the overlay(s) you are using. The method [BrushForLabel()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForLabel) is called every time a label is captured, and [BrushForField()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForField) is called for each of its fields to determine the brush for the label or field. ```csharp public class BasicOverlayListener : ILabelCaptureBasicOverlayListener { private readonly Brush upcBrush = new( fillColor: UIColor.FromRGB(46, 193, 206), // #2EC1CE strokeColor: UIColor.FromRGB(46, 193, 206), strokeWidth: 1f); private readonly Brush expiryDateBrush = new( fillColor: UIColor.FromRGB(250, 68, 70), // #FA4446 strokeColor: UIColor.FromRGB(250, 68, 70), strokeWidth: 1f); private readonly Brush transparentBrush = Brush.TransparentBrush; /* * Customize the appearance of the overlay for the individual fields. */ public Brush? BrushForField( LabelCaptureBasicOverlay overlay, LabelField field, CapturedLabel label) { return field.Name switch { "" => this.upcBrush, "" => this.expiryDateBrush, _ => null }; } /* * Customize the appearance of the overlay for the full label. * In this example, we disable label overlays by returning a transparent brush. */ public Brush? BrushForLabel( LabelCaptureBasicOverlay overlay, CapturedLabel label) { return this.transparentBrush; } public void OnLabelTapped( LabelCaptureBasicOverlay overlay, CapturedLabel label) { /* * Handle the user tap gesture on the label. */ } } // Set the listener on the overlay overlay.Listener = new BasicOverlayListener(); ``` :::tip You can also use `LabelCaptureBasicOverlay.LabelBrush`, `LabelCaptureBasicOverlay.CapturedFieldBrush`, and `LabelCaptureBasicOverlay.PredictedFieldBrush` properties to configure the overlay if you don't need to customize the appearance based on the name or content of the fields. ::: ### Advanced Overlay For more advanced use cases, such as adding custom views or implementing Augmented Reality (AR) features, you can use the `LabelCaptureAdvancedOverlay`. The example below creates an advanced overlay, configuring it to display a styled warning message below expiry date fields when they're close to expiring, while ignoring other fields. ```csharp // Create an advanced overlay that allows for custom views to be added over detected label fields // This is the key component for implementing Augmented Reality features var advancedOverlay = LabelCaptureAdvancedOverlay.Create(labelCapture); // Add the overlay to the data capture view dataCaptureView.AddOverlay(advancedOverlay); // Configure the advanced overlay with a listener that handles AR content creation and positioning advancedOverlay.Listener = new AdvancedOverlayListener(); public class AdvancedOverlayListener : ILabelCaptureAdvancedOverlayListener { // This method is called when a label is detected - we return null since we're only adding AR elements to specific fields, not the entire label public UIView? ViewForCapturedLabel( LabelCaptureAdvancedOverlay overlay, CapturedLabel capturedLabel) { return null; } // This defines where on the detected label the AR view would be anchored public Anchor AnchorForCapturedLabel( LabelCaptureAdvancedOverlay overlay, CapturedLabel capturedLabel) { return Anchor.Center; } // This defines the offset from the anchor point for the label's AR view public PointWithUnit OffsetForCapturedLabel( LabelCaptureAdvancedOverlay overlay, CapturedLabel capturedLabel, UIView view) { return new PointWithUnit(0f, 0f, MeasureUnit.Pixel); } // This method is called when a field is detected in a label public UIView? ViewForCapturedLabelField( LabelCaptureAdvancedOverlay overlay, LabelField labelField) { // We only want to create AR elements for expiry date fields that are text-based if (labelField.Name.ToLower().Contains("expiry") && labelField.Type == LabelFieldType.Text) { // // data extraction from expiry date field and days until expiry date calculation // // Check if scanned expiry date is too close to actual date var daysUntilExpiry = CalculateDaysUntilExpiry(labelField.Text); var dayLimit = 3; if (daysUntilExpiry ```csharp // Create the overlay var validationFlowOverlay = LabelCaptureValidationFlowOverlay.Create( labelCapture, dataCaptureView ); // Set the listener to receive validation events validationFlowOverlay.Listener = new ValidationFlowListener(); ``` ### Define a Listener When the user has verified that all fields are correctly captured and presses the finish button, the Validation Flow triggers a callback with the final results. To receive these results, implement the [ILabelCaptureValidationFlowListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/ui/label-capture-validation-flow-listener.html) interface: ```csharp public class ValidationFlowListener : ILabelCaptureValidationFlowListener { // This is called by the validation flow overlay when a label has been fully captured and validated public void OnValidationFlowLabelCaptured(IList fields) { string? barcodeData = null; string? expiryDate = null; foreach (var field in fields) { if (field.Name == "") { barcodeData = field.Barcode?.Data; } else if (field.Name == "") { expiryDate = field.Text; } } // Process the captured and validated data } } ``` ```csharp var validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.Create(); validationFlowOverlaySettings.SetPlaceholderText("MM/DD/YYYY", "Expiry Date"); validationFlowOverlay.ApplySettings(validationFlowOverlaySettings); ``` ```csharp var validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.Create(); validationFlowOverlaySettings.RestartButtonText = "Borrar todo"; validationFlowOverlaySettings.PauseButtonText = "Pausar"; validationFlowOverlaySettings.FinishButtonText = "Finalizar"; validationFlowOverlay.ApplySettings(validationFlowOverlaySettings); ``` ```csharp var validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.Create(); validationFlowOverlaySettings.StandbyHintText = "No label detected, camera paused"; validationFlowOverlaySettings.ValidationHintText = "data fields collected"; // X/Y (X fields out of total Y) is shown in front of this string validationFlowOverlay.ApplySettings(validationFlowOverlaySettings); ``` ```csharp var validationFlowOverlaySettings = LabelCaptureValidationFlowSettings.Create(); validationFlowOverlaySettings.ValidationErrorText = "Incorrect format."; validationFlowOverlaySettings.ScanningText = "Scan in progress"; validationFlowOverlaySettings.AdaptiveScanningText = "Processing"; validationFlowOverlay.ApplySettings(validationFlowOverlaySettings); ``` ```csharp private LabelCaptureSettings BuildLabelCaptureSettings() { var fields = new List(); var customBarcode = CustomBarcode.Builder() .SetSymbologies(new List { Symbology.Ean13Upca, Symbology.Gs1DatabarExpanded, Symbology.Code128 }) .Build(FIELD_BARCODE); fields.Add(customBarcode); var expiryDateText = ExpiryDateText.Builder() .SetLabelDateFormat(new LabelDateFormat(LabelDateComponentFormat.MDY, acceptPartialDates: false)) .Build(FIELD_EXPIRY_DATE); fields.Add(expiryDateText); var labelDefinition = LabelDefinition.Create(LABEL_RETAIL_ITEM, fields); labelDefinition.AdaptiveRecognitionMode = AdaptiveRecognitionMode.Auto; var settings = LabelCaptureSettings.Create(new List { labelDefinition }); return settings; } ``` See [AdaptiveRecognitionMode](https://docs.scandit.com/data-capture-sdk/net/ios/label-capture/api/label-definition.html#property-scandit.datacapture.label.LabelDefinition.AdaptiveRecognitionMode) for available options. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Smart Label Capture to your application. The general steps are: - Create a new Data Capture Context instance - Configure the LabelCapture mode - Define a listener to handle captured labels - Visualize the scan process - Start the camera - Provide feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/net/ios/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import LabelCaptureModuleOverview from '../../../../partials/get-started/_smart-label-capture-module-overview-dotnet.mdx'; ## Create a Data Capture Context import DataCaptureContextDotNet from '../../../../partials/get-started/_create-data-capture-context-dotnet.mdx'; ## Configure the Label Capture Mode The main entry point for the Label Capture Mode is the [LabelCapture](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/label-capture.html#class-scandit.datacapture.label.LabelCapture) object. It is configured through [LabelCaptureSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/label-capture-settings.html#class-scandit.datacapture.label.LabelCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) that get informed whenever a new frame has been processed. :::tip You can use Label Definitions provided in Smart Label Capture to set pre-built label types or define your label using pre-built fields. For more information, see the [Label Definitions](label-definitions.md) section. ::: ```csharp using Scandit.DataCapture.Label.Capture; using Scandit.DataCapture.Label.Data; using Scandit.DataCapture.Barcode.Data; // Build field definitions var fields = new List(); // Add a custom barcode field with the expected symbologies var customBarcode = CustomBarcode.Builder() .SetSymbologies(new List { Symbology.Ean13Upca, Symbology.Gs1DatabarExpanded, Symbology.Code128 }) .Build(""); fields.Add(customBarcode); // Add an expiry date text field var expiryDateText = ExpiryDateText.Builder() .SetLabelDateFormat(new LabelDateFormat(LabelDateComponentFormat.MDY, acceptPartialDates: false)) .Build(""); fields.Add(expiryDateText); // Create the label definition with the fields var labelDefinition = LabelDefinition.Create("", fields); // Create the settings with the label definition var settings = LabelCaptureSettings.Create(new List { labelDefinition }); // Create the label capture mode with the settings and data capture context var labelCapture = LabelCapture.Create(dataCaptureContext, settings); ``` ## Define a Listener to Handle Captured Labels To get informed whenever a new label has been recognized, add a [ILabelCaptureListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) through [LabelCapture.AddListener()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/label-capture.html#method-scandit.datacapture.label.LabelCapture.AddListener) and implement the listener methods to suit your application's needs. First implement the `ILabelCaptureListener` interface. Here is an example of how to implement a listener that processes the captured labels based on the label capture settings defined above: ```csharp public class LabelCaptureRepository : ILabelCaptureListener { public void OnSessionUpdated(LabelCapture labelCapture, LabelCaptureSession session, IFrameData frameData) { /* * The session update callback is called for every processed frame. * Check if the session contains any captured labels; * if not, continue capturing. */ var labels = session.CapturedLabels; if (labels.Count > 0) { var label = labels[0]; /* * Given the label capture settings defined above, * the barcode field would always be present. */ var barcodeData = label.Fields .FirstOrDefault(field => field.Name == "") ?.Barcode?.Data; /* * The expiry date field is optional. * Check for null in your result handling. */ var expiryDate = label.Fields .FirstOrDefault(field => field.Name == "") ?.Text; /* * Disable the label capture mode after a label has been captured * to prevent it from capturing the same label multiple times. */ labelCapture.Enabled = false; /* * Consider handling the results on a background thread to avoid * blocking the main thread when processing data. */ Task.Run(() => { HandleResults(barcodeData, expiryDate); }); } } public void OnObservationStarted(LabelCapture labelCapture) { // Called when the listener is added to LabelCapture } public void OnObservationStopped(LabelCapture labelCapture) { // Called when the listener is removed from LabelCapture } private void HandleResults(string? barcodeData, string? expiryDate) { // Process the captured data } } ``` Then add the listener to the label capture instance: ```csharp var listener = new LabelCaptureRepository(); labelCapture.AddListener(listener); ``` ## Visualize the Scan Process The capture process can be visualized by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy. The view controls what UI elements such as the viewfinder, as well as the overlays that are shown to visualize captured labels. To visualize the results of Label Capture you can use two overlays: - [LabelCaptureBasicOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/ui/label-capture-basic-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureBasicOverlay) - [LabelCaptureAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/ui/label-capture-advanced-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureAdvancedOverlay) :::tip The overlays can be used independently of each other, but you can also use both at the same time as each can serve to extend the functionality of the other. ::: Here is an example of how to add a `LabelCaptureBasicOverlay` to the `DataCaptureView`: ```csharp /* * Create the data capture view and attach it to the data capture context created earlier. */ var dataCaptureView = DataCaptureView.Create(dataCaptureContext, View.Bounds); /* * Add the data capture view to your view hierarchy */ View.AddSubview(dataCaptureView); dataCaptureView.TranslatesAutoresizingMaskIntoConstraints = false; NSLayoutConstraint.ActivateConstraints(new[] { dataCaptureView.TopAnchor.ConstraintEqualTo(View.TopAnchor), dataCaptureView.BottomAnchor.ConstraintEqualTo(View.BottomAnchor), dataCaptureView.LeadingAnchor.ConstraintEqualTo(View.LeadingAnchor), dataCaptureView.TrailingAnchor.ConstraintEqualTo(View.TrailingAnchor) }); /* * Create the overlay with the label capture mode. */ var overlay = LabelCaptureBasicOverlay.Create(labelCapture); /* * Add the overlay to the data capture view. */ dataCaptureView.AddOverlay(overlay); /* * Optionally, set a viewfinder to guide the user. */ overlay.Viewfinder = new RectangularViewfinder(RectangularViewfinderStyle.Square); ``` :::tip See the [Advanced Configurations](advanced.md) section for more information about how to customize the appearance of the overlays and how to use the advanced overlay to display arbitrary iOS views such as text views, icons or images. ::: ## Start the Camera Next, you need to create a new instance of the [Camera](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/camera.html#class-scandit.datacapture.core.Camera) class to indicate the camera to stream previews and to capture images. When initializing the camera, you can pass the recommended camera settings for Label Capture using the [LabelCapture.RecommendedCameraSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/label-capture.html#property-scandit.datacapture.label.LabelCapture.RecommendedCameraSettings) static property. ```csharp var cameraSettings = LabelCapture.RecommendedCameraSettings; var camera = Camera.GetDefaultCamera(cameraSettings); if (camera == null) { throw new InvalidOperationException("Failed to init camera!"); } dataCaptureContext.SetFrameSourceAsync(camera); ``` Once the Camera, DataCaptureContext, DataCaptureView and LabelCapture are initialized, you can switch on the camera to start capturing labels. Typically, this is done on resuming the view and when the user granted permission to use the camera, or once the user pressed continue scanning after handling a previous scan. ```csharp camera.SwitchToDesiredStateAsync(FrameSourceState.On); ``` ## Provide Feedback Smart Label Capture provides customizable feedback, emitted automatically when a label is recognized and successfully processed, configurable via [`LabelCapture.Feedback`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/label-capture.html#property-scandit.datacapture.label.LabelCapture.Feedback). You can use the default feedback, or configure your own sound or vibration. :::tip If you already have a [Feedback](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/feedback.html#class-scandit.datacapture.core.Feedback) instance implemented in your application, remove it to avoid double feedback. ::: ```csharp // Use the default feedback (vibration and beep sound) labelCapture.Feedback = LabelCaptureFeedback.Default; // Or customize the feedback var customFeedback = LabelCaptureFeedback.Default; customFeedback.Success = new Feedback(Vibration.DefaultVibration, sound: null); labelCapture.Feedback = customFeedback; ``` :::note Audio feedback is only played if the device is not muted. ::: --- ## About Smart Label Capture import AboutLabelCapture from '../../../../partials/intro/_about-smart-label-capture.mdx'; import ValidationFlow from '../../../../partials/intro/_about_validation_flow.mdx'; See [here](./advanced.md#validation-flow) for more details. --- ## Label Definitions # Label Definitions A **Label Definition** is a configuration that defines the label, and its relevant fields, that Smart Label Capture should recognize and extract during scans. Smart Label Capture provides a [Label Definition](https://docs.scandit.com/data-capture-sdk/dotnet.ios/label-capture/api/label-definition.html#label-definition) API, enabling you to configure and extract structured data from predefined and custom labels. This feature provides a flexible way to recognize and decode fields within a specific label layout such as price tags, VIN labels, or packaging stickers without needing to write custom code for each label type. There are two approaches to using label definitions: - [**Pre-built Labels**](#pre-built-labels) - [**Custom Labels**](#custom-labels) ## Pre-built Labels Smart Label Capture includes ready-made label definitions for common use cases. These pre-built options let you recognize and extract information from standard label types without creating custom configurations: ### Example: Price label Use `LabelCaptureSettings` to configure a pre-built label definition for price labels, such as those found in retail environments: ![Price Label Example](/img/slc/price-label.png) ```csharp // Create a pre-built price capture label definition var priceLabel = LabelDefinition.CreatePriceCaptureDefinition("price-label"); // Create the settings with the label definition var settings = LabelCaptureSettings.Create(new List { priceLabel }); ``` ## Custom Labels If Smart Label Capture's pre-built options don't fit your needs, define a custom label instead. Custom labels can combine your own fields with any of the available pre-built ones. :::tip The following characters are recognized: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ()-./:,$¶"`. ::: ### Custom Fields There are two types of custom fields you can define: The following methods are available to configure custom fields: | Method | Optional | Description | |--------|----------|-------------| | `ValueRegexes` | No | The regex patterns that identify the target string in the scanned content. | | `AnchorRegexes` | Yes | Used to specify keywords or phrases that help identify the context of the field. This is particularly useful when the label contains multiple fields that could match the same pattern (e.g., when both packaging and expiry dates are present). | | `Symbologies` | No | The barcode symbologies to match for barcode fields. This is important for ensuring that the field only captures data from specific barcode types, enhancing accuracy and relevance. | | `IsOptional` | Yes | Whether the field is optional or mandatory. This is helpful when certain fields may not be present on every scan. | #### Example: Fish Shipping Box This example shows how to create a custom label definition for a fish shipping box, which includes fields for barcode and batch number. ![Fish Shipping Box Example](/img/slc/fish-shipping-box.png) ```csharp // Build field definitions var fields = new List(); // Add a custom barcode field with the expected symbology var barcodeField = CustomBarcode.Builder() .SetSymbology(Symbology.Code128) .Build("barcode-field"); fields.Add(barcodeField); // Add a custom text field for the batch number var batchNumberField = CustomText.Builder() .SetAnchorRegex("Batch") .SetValueRegex("FZ\\d{5,10}") .IsOptional(true) .Build("batch-number-field"); fields.Add(batchNumberField); // Create the label definition with the fields var labelDefinition = LabelDefinition.Create("shipping-label", fields); // Create the settings with the label definition var settings = LabelCaptureSettings.Create(new List { labelDefinition }); ``` ### Pre-built Fields You can also build your label using pre-built fields. These common fields speed up integration because their `ValueRegexes`, `AnchorRegexes`, and `Symbologies` are already predefined. Customization of pre-built fields is done via the `ValueRegexes`, `AnchorRegexes`, and `IsOptional` methods, which allow you to specify the expected format of the field data. :::tip All pre-built fields come with default `ValueRegexes` and `AnchorRegexes` that are suitable for most use cases. **Using either method is optional and will override the defaults**. The `ResetAnchorRegexes` method can be used to remove the default `AnchorRegexes`, allowing you to rely solely on the `ValueRegexes` for detection. ::: import FeatureList from '@site/src/components/FeatureList'; #### Barcode Fields #### Price and Weight Fields #### Date and Custom Text Fields #### Example: Hard disk drive label This example demonstrates how to configure a label definition for a hard disk drive (HDD) label, which typically includes common fields like serial number and part number. ![Hard Disk Drive Label Example](/img/slc/hdd-label.png) ```csharp // Build field definitions using pre-built barcode fields var fields = new List(); // Add a serial number barcode field var serialNumberField = SerialNumberBarcode.Builder() .Build("serial-number"); fields.Add(serialNumberField); // Add a part number barcode field var partNumberField = PartNumberBarcode.Builder() .Build("part-number"); fields.Add(partNumberField); // Create the label definition with the fields var labelDefinition = LabelDefinition.Create("hdd-label", fields); // Create the settings with the label definition var settings = LabelCaptureSettings.Create(new List { labelDefinition }); ``` --- ## Adding AR Overlays # Adding AR Overlays There are two ways to add advanced AR overlays to a Data Capture View: - Take advantage of the [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) class, which provides a ready-to-use implementation for view-based AR overlays. - Provide your own custom implementation, using the function [IBarcodeBatchListener.OnSessionUpdated()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) to retrieve the barcode’s current screen position for each frame. :::note - The first way is the easiest, as it takes care of adding, removing and animating the overlay’s views whenever needed. It’s also flexible enough to cover the majority of use cases. - You can always handle touch events on the views you create like you normally would. ::: ## Using BarcodeBatchAdvancedOverlay As mentioned above, the advanced overlay combined with its [listener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) offers an easy way of adding augmentations to your [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). In this guide we will add a view above each barcode showing its content. First of all, create a new instance of [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) and add it to the [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). ```csharp BarcodeBatchAdvancedOverlay overlay = BarcodeBatchAdvancedOverlay.Create(barcodeBatch, dataCaptureView); ``` At this point, you have two options. - Add a [IBarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) to the overlay. - Use the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) to specify the view, anchor and offset for each barcode. :::note The second way will take priority over the first one, which means that if a view for a barcode has been set using [BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), the function [IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) won’t be invoked for that specific barcode. ::: Using [IBarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) - You need to implement [IBarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener). This interface’s methods are invoked every time a barcode is newly tracked. - [IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) asks for a view to animate on top of the barcode. Returning _null_ will show no view. - [IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode) asks how to anchor the view to the barcode through [Anchor](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/anchor.html#enum-scandit.datacapture.core.Anchor). Be aware that it anchors the view’s center to the anchor point. To achieve anchoring the top of the view or the bottom etc. you will have to set an offset as explained in the next point. - [IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode) asks for an offset that is applied on the already anchored view. This offset is expressed through a [PointWithUnit](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/common.html#struct-scandit.datacapture.core.PointWithUnit). ```csharp public View ViewForTrackedBarcode(BarcodeBatchAdvancedOverlay overlay, TrackedBarcode trackedBarcode) { // Create and return the view you want to show for this tracked barcode. You can also return null, to have no view for this barcode. UITextView textView = new UITextView(new CGRect(0, 0, 200, 50)); textView.BackgroundColor = UIColor.White; textView.Text = trackedBarcode.Barcode.Data; return textView; } public Anchor AnchorForTrackedBarcode( BarcodeBatchAdvancedOverlay overlay, TrackedBarcode trackedBarcode) { // As we want the view to be above the barcode, we anchor the view's center to the top-center of the barcode quadrilateral. // Use the function 'OffsetForTrackedBarcode' below to adjust the position of the view by providing an offset. return Anchor.TopCenter; } public PointWithUnit OffsetForTrackedBarcode( BarcodeBatchAdvancedOverlay overlay, TrackedBarcode trackedBarcode) { // This is the offset that will be applied to the view. // You can use MeasureUnit.Fraction to give a measure relative to the view itself, the sdk will take care of transforming this into pixel size. // We now center horizontally and move up the view to make sure it's centered and above the barcode quadrilateral by half of the view's height. return new PointWithUnit( new FloatWithUnit(0f, MeasureUnit.Fraction), new FloatWithUnit(-1f, MeasureUnit.Fraction)); } ``` Using the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) The function [IBarcodeBatchListener.OnSessionUpdated()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) gives you access to a [session](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession), which contains all added, updated and removed tracked barcodes. From here you can create the view you want to display, and then call [BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), [BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode) and [BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode) ```csharp public void OnSessionUpdated(BarcodeBatch barcodeBatch, BarcodeBatchSession session, IFrameData frameData) { // Be careful, this method is not necessarily invoked on the main thread! DispatchQueue.MainQueue.DispatchAsync(() => { foreach (TrackedBarcode trackedBarcode in session.AddedTrackedBarcodes) { UITextView textView = new UITextView(new CGRect(0, 0, 200, 50)); textView.BackgroundColor = UIColor.White; textView.Text = trackedBarcode.Barcode.Data; overlay.SetViewForTrackedBarcode(trackedBarcode, textView); overlay.SetAnchorForTrackedBarcode(trackedBarcode, Anchor.TopCenter); overlay.SetOffsetForTrackedBarcode( trackedBarcode, new PointWithUnit( new FloatWithUnit(0f, MeasureUnit.Fraction), new FloatWithUnit(-1f, MeasureUnit.Fraction) ) ); } }); // Dispose the frame when you have finished processing it. If the frame is not properly disposed, // different issues could arise, e.g. a frozen, non-responsive, or "severely stuttering" video feed. frameData.Dispose(); } ``` ## Provide your own custom implementation If you do not want to use the overlay, it is also possible to add augmented reality features based on the tracking identifier and the [quadrilateral](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/common.html#struct-scandit.datacapture.core.Quadrilateral) coordinates that every tracked barcode has. Below are some pointers. - Set a [IBarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) on the barcode tracking - In the [IBarcodeBatchListener.OnSessionUpdated()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) function fetch the [added](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.AddedTrackedBarcodes) and [removed](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.RemovedTrackedBarcodes) tracked barcodes. - Create and show the views for the added barcodes. - Remove the views for the lost barcodes. - Add a method that is called 60fps when [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) is enabled. In this method, for each [TrackedBarcode](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/tracked-barcode.html#class-scandit.datacapture.barcode.batch.TrackedBarcode) on-screen, update the position based on [TrackedBarcode.Location](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location). Please note that there is no need to animate the change of location, the change of position will happen frequently enough that the view will look as it is animated. :::note The frame coordinates from [TrackedBarcode.Location](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location) need to be mapped to view coordinates, using [DataCaptureView.MapFrameQuadrilateralToView()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#method-scandit.datacapture.core.ui.DataCaptureView.MapFrameQuadrilateralToView). ::: ```csharp public void OnSessionUpdated(BarcodeBatch mode, BarcodeBatchSession session, IFrameData frameData) { // Be careful, this function is not invoked on the main thread! DispatchQueue.MainQueue.DispatchAsync(() => { foreach (int lostTrackIdentifier in session.RemovedTrackedBarcodes) { // You now know the identifier of the tracked barcode that has been lost. Usually here you would remove the views associated. } foreach (TrackedBarcode trackedBarcode in session.AddedTrackedBarcodes) { // Fixed identifier for the tracked barcode. int trackingIdentifier = trackedBarcode.Identifier; // Current location of the tracked barcode. Quadrilateral location = trackedBarcode.Location; Quadrilateral quadrilateral = dataCaptureView.MapFrameQuadrilateralToView(location); // You now know this new tracking's identifier and location. Usually here you would create and show the views. } }); // Dispose the frame when you have finished processing it. If the frame is not properly disposed, // different issues could arise, e.g. a frozen, non-responsive, or "severely stuttering" video feed. frameData.Dispose(); } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan to your application. The general steps are: - Creating a new Data Capture Context instance - Configuring the MatrixScan mode - Using the built-in camera - Visualizing the scan process - Providing feedback - Disabling barcode tracking ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new [data capture context](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext context = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Batch Mode The main entry point for the Barcode Batch Mode is the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object. It is configured through [BarcodeBatchSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) that will get informed whenever a new frame has been processed. Most of the times, you will not need to implement a [IBarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener), instead you will add a [BarcodeBatchBasicOverlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) and implement a [IBarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener). For this tutorial, we will setup Barcode Batch for tracking QR codes. ```csharp BarcodeBatchSettings settings = BarcodeBatchSettings.Create(); settings.EnableSymbology(Symbology.Qr, true); ``` Next, create a [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance with the data capture context and the settings initialized in the previous steps: ```csharp BarcodeBatch barcodeBatch = BarcodeBatch.Create(context, settings); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/security-privacy?tabs=macos#:~:text=NSCameraUsageDescription) key in your app’s Info.plist file. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```csharp camera = Camera.GetDefaultCamera(); camera?.ApplySettingsAsync(BarcodeBatch.RecommendedCameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.SetFrameSourceAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```csharp context.SetFrameSourceAsync(camera); ``` The camera is off by default and must be turned on. This is done by calling [IFrameSource.SwitchToDesiredStateAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```csharp camera?.SwitchToDesiredStateAsync(FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```csharp DataCaptureView dataCaptureView = DataCaptureView.Create(dataCaptureContext, View.Bounds); View.AddSubview(dataCaptureView); ``` Alternatively you can use a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) from XAML in your MAUI application. For example: ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); // Initialization of DataCaptureView happens on handler changed event. dataCaptureView.HandlerChanged += DataCaptureViewHandlerChanged; } private void DataCaptureViewHandlerChanged(object? sender, EventArgs e) { // Your dataCaptureView configuration goes here, e.g. add overlay } } ``` For MAUI development add [Scandit.DataCapture.Core.Maui](https://www.nuget.org/packages/Scandit.DataCapture.Core.Maui) NuGet package into your project. To visualize the results of Barcode Batch, first you need to add the following [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay): ```csharp BarcodeBatchBasicOverlay overlay = BarcodeBatchBasicOverlay.Create(barcodeBatch, dataCaptureView); ``` Once the overlay has been added, you should implement the [IBarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) interface. The method [IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode) is invoked every time a new tracked barcode appears and it can be used to set a [brush](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/ui/brush.html#class-scandit.datacapture.core.ui.Brush) that will be used to highlight that specific barcode in the [overlay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay). ```csharp public Brush BrushForTrackedBarcode(BarcodeBatchBasicOverlay overlay, TrackedBarcode trackedBarcode) { // Return a custom Brush based on the tracked barcode. } ``` If you would like to make the highlights tappable, you need to implement the [IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped) method. ```csharp public void OnTrackedBarcodeTapped(BarcodeBatchBasicOverlay overlay, TrackedBarcode trackedBarcode) { // A tracked barcode was tapped. } ``` ## Get Barcode Batch Feedback Barcode Batch, unlike Barcode Capture, doesn’t emit feedback (sound or vibration) when a new barcode is recognized. However, you may implement a [IBarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) to provide a similar experience. Below, we use the default [Feedback](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration if you want. ```csharp public override void ViewDidLoad() { base.ViewDidLoad(); feedback = Feedback.DefaultFeedback; } ``` Next, use this [feedback](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/feedback.html#class-scandit.datacapture.core.Feedback) in a [IBarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener): ```csharp public class FeedbackListener : IBarcodeBatchListener { public void OnObservationStarted(BarcodeBatch barcodeBatch) { // Called when Barcode Batch is started. // We don't use this callback in this guide. } public void OnObservationStopped(BarcodeBatch barcodeBatch) { // Called when Barcode Batch is stopped. // We don't use this callback in this guide. } public void OnSessionUpdated(BarcodeBatch barcodeBatch, BarcodeBatchSession session, IFrameData frameData) { if (session.AddedTrackedBarcodes.Any()) { this.feedback.Emit(); } } } ``` [IBarcodeBatchListener.OnSessionUpdated()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) is invoked for every processed frame. The [session](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession) parameter contains information about the currently tracked barcodes, in particular, the newly recognized ones. We check if there are any and if so, we emit the feedback. As the last step, register the listener responsible for emitting the feedback with the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance. ```csharp barcodeBatch.AddListener(feedbackListener); ``` ## Disabling Barcode Batch To disable barcode tracking set [BarcodeBatch.Enabled](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-batch.html#property-scandit.datacapture.barcode.batch.BarcodeBatch.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off or put it in standby calling [SwitchToDesiredState](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [StandBy](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.Standby). --- ## About MatrixScan Batch # About MatrixScan Batch import AboutMatrixScan from '../../../../partials/intro/_about-matrixscan.mdx' --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan AR to your application. Implementing MatrixScan AR involves two primary elements: - Barcode AR: The data capture mode that is used for scan and check functionality. - A Barcode AR View: The pre-built UI elements used to highlight items to be checked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode AR Mode - Setup the Barcode AR View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/net/ios/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Internal Dependencies import InternalDependencies from '../../../../partials/get-started/_internal-deps.mdx'; ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new [Data Capture Context](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode AR Mode The main entry point for the Barcode AR Mode is the `BarcodeAr` object. You can configure the supported Symbologies through its [`BarcodeArSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-ar-settings.html). Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```csharp BarcodeArSettings settings = new BarcodeArSettings(); settings.EnableSymbology(Symbology.Ean13Upca, true); ``` Then create the mode with the previously created settings: ```csharp BarcodeAr barcodeAr = new BarcodeAr(dataCaptureContext, settings); ``` ## Setup the `BarcodeArView` MatrixScan AR’s built-in AR user interface includes buttons and overlays that guide the user through the scan and check process. By adding a [`BarcodeArView`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView), the scanning interface is added automatically to your application. The `BarcodeArView` is where you provide the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider) to supply the highlight and annotation information for the barcodes to be checked. If *null*, a default highlight is used and no annotations are provided. The `BarcodeArView` appearance can be customized through [`BarcodeArViewSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-ar-view-settings.html#class-scandit.datacapture.barcode.check.ui.BarcodeArViewSettings), properties on the`BarcodeArView`, and the corresponding settings for your desired highlights and/or annotations, to match your application’s look and feel. The following settings can be customized: * Audio and haptic feedback * Camera position * Torch button visibility and its position * Switch camera button visibility and its position * Zoom control visibility and its position * The size, colors, and styles of the highlights and annotations ```csharp BarcodeArViewSettings viewSettings = new BarcodeArViewSettings(); viewSettings.HapticEnabled = false; viewSettings.SoundEnabled = false; viewSettings.DefaultCameraPosition = CameraPosition.UserFacing; ``` Next, create a `BarcodeArView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodeArView` is automatically added to the provided parent view. ```csharp BarcodeArView barcodeArView = BarcodeArView.Create(parentView, barcodeAr, dataCaptureContext, viewSettings, cameraSettings: null); barcodeArView.ShouldShowCameraSwitchControl = true; barcodeArView.ShouldShowTorchControl = true; barcodeArView.ShouldShowZoomControl = true; barcodeArView.CameraSwitchControlPosition = Anchor.TopRight; barcodeArView.TorchControlPosition = Anchor.BottomRight; barcodeArView.ZoomControlPosition = Anchor.TopLeft; ``` Configure the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider). ```csharp public class AnnotationProvider : IBarcodeArAnnotationProvider { public Task AnnotationForBarcodeAsync(Barcode barcode) { var annotation = new BarcodeArStatusIconAnnotation(barcode); annotation.Text = "Example annotation"; return Task.FromResult(annotation); } } public class HighlightProvider : IBarcodeArHighlightProvider { public Task HighlightForBarcodeAsync(Barcode barcode) { return Task.FromResult(new BarcodeArRectangleHighlight(barcode)); } } ``` And set them to the view: ```csharp barcodeArView.HighlightProvider = new HighlightProvider(); barcodeArView.AnnotationProvider = new AnnotationProvider(); ``` ## Register the Listener If you want a callback when a highlight is tapped, register a [BarcodeArViewUiListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-ar-view.html#interface-scandit.datacapture.barcode.check.ui.IBarcodeArViewUiListener). ```csharp barcodeArView.HighlightForBarcodeTapped += (object sender, HighlightForBarcodeTappedEventArgs args) => { BarcodeAr barcodeAr = args.BarcodeAr; Barcode barcode = args.Barcode; IBarcodeArHighlight highlight = args.Highlight; // Handle tap }; ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling: ```csharp barcodeArView.Start(); ``` --- ## About MatrixScan AR # About MatrixScan AR import AboutMatrixScanCheck from '../../../../partials/intro/_about-matrixscan-ar.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Count is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Count to best fit your needs. ## Scanning Against A List There is a function to set a list of expected barcodes if you are scanning against a manifest or item list. If this is used, a progress bar is added to the UI, so you can keep track of the process while scanning. When scanning against a list, the UI will also show red icons to mark scanned barcodes that aren’t present on the list. ```csharp List targetBarcodes = new List(); targetBarcodes.Add(TargetBarcode.Create("data", 1)); BarcodeCountCaptureList captureList = BarcodeCountCaptureList.Create(this, targetBarcodes); barcodeCount.SetBarcodeCountCaptureList(captureList); ``` ## Barcode Count Status This feature is used to provide users with more details regarding the items they’re scanning in order to aid effective handling. The icons (available as part of the SDK) appear as an AR overlay after tapping the “Status Mode” button and can be used to highlight the following: - Expired products - Items requiring quality inspection - Items that are low in stock - Wrong items - Fragile items ## Clustering import Clustering from '../../../../partials/count/_clustering.mdx' ## Strap Mode It can be difficult to reach the shutter button if the smart device is attached to the user’s wrist by a strap or similar. In this instance, you can enable a floating shutter button that can be positioned by the end user in a more ergonomically suitable position. ```csharp barcodeCountView.ShouldShowFloatingShutterButton = true; ``` ## Filtering If you have several types of barcodes on your label/package, you may want to scan only one of them. In this case, you can filter the others out. This can be done by symbology, symbol count, or setting a regex. For example, you might want to scan only Code 128 barcodes and no PDF417 ones. ```csharp BarcodeCountSettings settings = new BarcodeCountSettings(); barcodeCountSettings.EnableSymbologies(enabledSymbologies); settings.FilterSettings.ExcludedSymbologies = new[] { Symbology.Pdf417 }; ``` Or, you want to exclude all the barcodes starting with 4 numbers: ```csharp BarcodeCountSettings settings = new BarcodeCountSettings(); settings.FilterSettings.ExcludedCodesRegex = "^1234.*"; ``` By default the filters applied to the relevant barcodes are transparent, but you can use [`BarcodeFilterHighlightSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-filter-highlight-settings.html#barcode-filter-highlight-settings) to change the color and level of transparency. ![Different Filters in MatrixScan Count](/img/matrixscan-count/filtering_styles.png) ## Clear Screen Button There are situations in which the user may find it helpful to clean up their screen (i.e. clear all the AR overlays) but keep the list of barcodes scanned. If this is the case, you can enable the “Clear screen” button. ```csharp barcodeCountView.ShouldShowClearHighlightsButton = true; ``` ## Customize Overlay Colors MatrixScan Count comes with recommended and user-tested AR overlays. However, if you wish to customize the overlay colors, once the overlay has been added, you can conform to the [IBarcodeCountViewListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view-listener.html#interface-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener) interface. The methods [IBarcodeCountViewListener.BrushForRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForRecognizedBarcode) and [IBarcodeCountViewListener.BrushForUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForUnrecognizedBarcode) are invoked every time a new recognized or unrecognized barcode appears. These can be used to set a brush that will be used to highlight that specific barcode in the overlay. Keep in mind that these methods are relevant only when using the style [BarcodeCountViewStyle.Dot](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view.html#value-scandit.datacapture.barcode.count.ui.BarcodeCountViewStyle.Dot). ```csharp public Brush BrushForRecognizedBarcode(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Return a custom brush } public Brush BrushForUnrecognizedBarcode(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Return a custom brush } ``` ## Notifications If you want to be notified when a user taps on an overlay, you need to implement the [IBarcodeCountViewListener.OnRecognizedBarcodeTapped()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnRecognizedBarcodeTapped) and [IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped) methods. ```csharp public void OnRecognizedBarcodeTapped(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Do something with the tapped barcode } public void OnUnrecognizedBarcodeTapped(BarcodeCountView view, TrackedBarcode trackedBarcode) { // Do something with the tapped barcode } ``` ## Disable UI Elements The UI is an integral part of MatrixScan Count and we do not recommend that you use it without it. However, if you wish to disable UI elements you can do it as follows. Disable buttons: ```csharp barcodeCountView.ShouldShowListButton = false; barcodeCountView.ShouldShowExitButton = false; barcodeCountView.ShouldShowShutterButton = false; ``` Disable feedback and hints: ```csharp barcodeCountView.ShouldShowUserGuidanceView = false; barcodeCountView.ShouldShowHints = false; ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Count to your application. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Count Mode - Obtaining the camera instance and set frame source - Registering the listener to be informed when scan phase is complete - Setting the capture view and AR overlays - Configuring the camera for scanning view - Storing and retrieving the captured barcodes - Resetting the Barcode Count Mode - List and exit callbacks ## Create A New Data Capture Context Instance The first step to add capture capabilities to your application is to create a new [Data Capture Context](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure The Barcode Count Mode The main entry point for the Barcode Count Mode is the [BarcodeCount](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) object. It is configured through [BarcodeCountSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count-settings.html#class-scandit.datacapture.barcode.count.BarcodeCountSettings) and allows you to register one or more listeners that are informed whenever a scan phase has finished. For this tutorial, we will set up Barcode Count for tracking EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```csharp BarcodeCountSettings settings = new BarcodeCountSettings(); settings.EnableSymbology(Symbology.Ean13Upca, true); ``` If you are sure that your environment will only have unique barcodes (i.e. no duplicated values), you can also enable [BarcodeCountSettings.ExpectsOnlyUniqueBarcodes](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count-settings.html#property-scandit.datacapture.barcode.count.BarcodeCountSettings.ExpectsOnlyUniqueBarcodes). This option improves scanning performance as long as you are sure that no duplicates will be present. Next, create a [BarcodeCount](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) instance with the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) and the settings initialized in the previous step: ```csharp BarcodeCount barcodeCount = BarcodeCount.Create(dataCaptureContext, settings); ``` ## Obtain Camera Instance And Set Frame Source Used Our recommended camera settings should be used to achieve the best performance and user experience. The following couple of lines show how to get the recommended settings for MatrixScan Count and create the camera from it: ```csharp CameraSettings cameraSettings = BarcodeCount.RecommendedCameraSettings; Camera camera = Camera.DefaultCamera; camera.ApplySettingsAsync(cameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.SetFrameSourceAsync()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```csharp dataCaptureContext.SetFrameSourceAsync(camera); ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [IBarcodeCountListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) interface and register the listener. ```csharp // Register self as a listener to monitor the barcode count session. barcodeCount.AddListener(this); ``` [IBarcodeCountListener.OnScan()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan) is called when the scan phase has finished and results can be retrieved from [BarcodeCountSession](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession). Alternatively to register [IBarcodeCountListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) interface it is possible to subscribe to corresponding event. For example: ```csharp barcodeCount.Scanned += (object sender, BarcodeCountEventArgs args) => { }; ``` ## Set Capture View And AR Overlays MatrixScan Count’s built-in AR user interface includes buttons and overlays that guide the user through the capturing process. By adding a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) to your view hierarchy: ```csharp BarcodeCountView barcodeCountView = BarcodeCountView.Create(View.Bounds, dataCaptureContext, barcodeCount); ``` You can use a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) from XAML in your MAUI application. ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MyScanPage : ContentPage { public MyScanPage() { this.InitializeComponent(); // Initialization of BarcodeCountView happens on handler changed event. this.barcodeCountView.HandlerChanged += BarcodeCountViewHandlerChanged; } private void BarcodeCountViewHandlerChanged(object sender, EventArgs e) { // Your BarcodeCountView configuration goes here, e.g. subscribe for buttons tap events } } ``` For MAUI development add [Scandit.DataCapture.Barcode.Maui](https://www.nuget.org/packages/Scandit.DataCapture.Barcode.Maui) NuGet package into your project. ## Set Up The Camera So That It Switches On When You Are In Scanning View The camera is not automatically turned on when you are in a scanning view. You need to set up the camera so that it switches on when needed and it switches off when not needed anymore. Similarly [BarcodeCount](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) should also be enabled and disabled. For instance, you should switch off the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is not visible anymore (including when the app goes in the background), similarly you want to switch on the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is visible (including when the app goes to the foreground). One way to achieve this is the following: ```csharp public override void ViewWillDisappear(bool animated) { camera.SwitchToDesiredStateAsync(FrameSourceState.Off); base.ViewWillDisappear(animated); } public override void ViewWillAppear(bool animated) { camera.SwitchToDesiredStateAsync(FrameSourceState.On); base.ViewWillAppear(animated); } ``` ## Store And Retrieve Scanned Barcodes The values captured as part of the scanning process are part of the [session](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession), and the session is not accessible outside [IBarcodeCountListener.OnScan()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan). Therefore, we recommend that you store the values to present a list, for example when the user taps the list icon. To do this, make a copy of [BarcodeCountSession.RecognizedBarcodes](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count-session.html#property-scandit.datacapture.barcode.count.BarcodeCountSession.RecognizedBarcodes). ## Reset Barcode Count Mode When the scanning process is over, you need to reset the mode to make it ready for the next process. This clears the list of barcodes scanned and all the AR overlays. To reset Barcode Count’s scanning process, you need to call the [BarcodeCount.Reset()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-count.html#method-scandit.datacapture.barcode.count.BarcodeCount.Reset) method. ```csharp barcodeCount.Reset(); ``` ## List And Exit Callbacks The UI includes two icons (buttons) named “List” and “Exit”. The SDK provides events so you can add the desired action when those icons are tapped by the user. ```csharp barcodeCountView.ListButtonTapped += (object sender, ListButtonTappedEventArgs args) => { // Show the current progress but the order is not completed }; barcodeCountView.ExitButtonTapped += (object sender, ExitButtonTappedEventArgs args) => { // The order is completed }; ``` --- ## About MatrixScan Count # About MatrixScan Count import AboutMatrixScanCount from '../../../../partials/intro/_about-matrixscan-count.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Find is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Find to best fit your needs. ## BarcodeFind Listener You may want more fine-grained knowledge over the different events happening during the life of the BarcodeFind mode, such as when the search starts, pauses and stops. To do this, you can directly register a [IBarcodeFindListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-find-listener.html#interface-scandit.datacapture.barcode.find.IBarcodeFindListener) on the mode itself. Be aware that these listeners will be called from a background thread. ```csharp public class BarcodeFindListener : IBarcodeFindListener { public void OnSearchPaused(ICollection foundItems) { // The mode was paused } public void OnSearchStarted() { // The mode was started } public void OnSearchStopped(ICollection foundItems) { // The mode was stopped after the finish button was clicked } } private void Initialize() { barcodeFind.AddListener(new BarcodeFindListener()) } ``` Alternatively it is possible to subscribe to corresponding events [BarcodeFind.SearchPaused](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-find.html#property-scandit.datacapture.barcode.find.BarcodeFind.SearchPaused), [BarcodeFind.SearchStarted](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-find.html#property-scandit.datacapture.barcode.find.BarcodeFind.SearchStarted) or [BarcodeFind.SearchStopped](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-find.html#property-scandit.datacapture.barcode.find.BarcodeFind.SearchStopped). For example: ```csharp barcodeFind.SearchStarted += (object? sender, EventArgs args) => { // The mode was started }; barcodeFind.SearchPaused += (object? sender, BarcodeFindEventArgs args) => { // The mode was paused }; barcodeFind.SearchStopped += (object? sender, BarcodeFindEventArgs args) => { // The mode was stopped after the finish button was clicked }; ``` ## UI configuration The [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) will by default show a set of UI elements, which can be optionally hidden: - A play/pause button - A finish button - A searched items carousel - Guidance hints There is also a progress bar but this is hidden by default. Each of these elements can be shown or hidden at will. ```csharp barcodeFindView.ShouldShowCarousel = false; barcodeFindView.ShouldShowProgressBar = true; // … ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Find to your application. Implementing MatrixScan Find involves two primary elements: - Barcode Find: The data capture mode that is used for search and find functionality. - A Barcode Find View: The pre-built UI elements used to highlight found items. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Find Mode - Setup the Barcode Find View - Registering the Listener to notify about found items ## Create a Data Capture Context The first step to add find capabilities to your application is to create a new [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Find Mode The main entry point for the Barcode Find Mode is the [BarcodeFind](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind) object. You can configure the supported Symbologies through its [BarcodeFindSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-find-settings.html#class-scandit.datacapture.barcode.find.BarcodeFindSettings), and set up the list of items that you want MatrixScan Find to highlight (e.g. a list of products). For this tutorial, we will set up Barcode Find for tracking EAN13 codes. Change this to the correct symbologies for your use case (e.g. Code 128, Code 39…). First create the settings: ```csharp BarcodeFindSettings settings = new BarcodeFindSettings(); settings.EnableSymbology(Symbology.Ean13Upca, true); ``` Then you have to create the list of items that will be actively searched for. In this tutorial, let’s look up two items based on their EAN13 codes. We will attach to the first item some optional information that can be used by the BarcodeFindView to display extra information. ```csharp ICollection items = new HashSet() { new BarcodeFindItem( new BarcodeFindItemSearchOptions("9783598215438"), new BarcodeFindItemContent("Mini Screwdriver Set", "(6-Piece)", null)), new BarcodeFindItem( new BarcodeFindItemSearchOptions("9783598215414"), null) // Item information is optional, used for display only }; ``` Create the mode with the previously created settings and set the items: ```csharp BarcodeFind barcodeFind = new BarcodeFind(settings); barcodeFind.SetItemList(items); ``` ## Setup the BarcodeFindView MatrixScan Find’s built-in AR user interface includes buttons and overlays that guide the user through the searching process. By adding a [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView), the scanning interface (camera preview and searching UI elements) will be added automatically to your application. The BarcodeFindView appearance can be customized through [BarcodeFindViewSettings](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-find-view-settings.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindViewSettings): - Colors of dots in augmented reality overlay - Enable sound and haptic alerts ```csharp BarcodeFindViewSettings viewSettings = new BarcodeFindViewSettings(); ``` Construct a new BarcodeFindView. The BarcodeFindView is automatically added to the provided parent view. ```csharp BarcodeFindView barcodeFindView = BarcodeFindView.Create(parentView, dataCaptureContext, barcodeFind, viewSettings); ``` Connect the BarcodeFindView to the iOS view controller lifecycle. In particular, make sure to call BarcodeFindView.PrepareSearching() on your UIViewController’s [ViewWillAppear](https://learn.microsoft.com/en-us/dotnet/api/uikit.uiviewcontroller.viewwillappear) method to make sure that start up time is optimal. ```csharp public override void ViewWillAppear(bool animated) { base.ViewWillAppear(animated); barcodeFindView.PrepareSearching(); } public override void ViewWillDisappear(bool animated) { base.ViewWillDisappear(animated); barcodeFindView.StopSearching(); } ``` ## Subscribe to view events to be notified with found items The BarcodeFindView displays next to its shutter button a handy “finish” button. Subscribe to a [BarcodeFindView.FinishButtonTapped](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-find-view.html#property-scandit.datacapture.barcode.find.ui.BarcodeFindView.FinishButtonTapped) event to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```csharp barcodeFindView.FinishButtonTapped += (object? sender, FinishButtonTappedEventArgs e) => { RequireActivity().OnBackPressed(); }; ``` ## Start searching As soon as everything is set up, control the [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) to start the search. ```csharp barcodeFindView.StartSearching(); ``` This is the equivalent of pressing the “Play” button programmatically. It will start the search process, turn on the camera and hide the item carousel. --- ## About MatrixScan Find # About MatrixScan Find import AboutFind from '../../../../partials/intro/_about-matrixscan-find.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Pick is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Pick to best fit your needs. ## BarcodePick Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodePick` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodePickListener`](https://docs.scandit.com/data-capture-sdk/android/barcode-capture/api/barcode-pick-listener.html#interface-scandit.datacapture.barcode.pick.IBarcodePickListener) on the mode itself, keeping in mind that these listeners are called from a background thread. ```csharp public class MyBarcodePickListener : IBarcodePickListener { public void OnSessionUpdated(BarcodePick barcodePick, BarcodePickSession session) { // Handle session update } } private void Initialize() { barcodePick.AddListener(new MyBarcodePickListener()); } ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Pick to your application. Implementing MatrixScan Pick involves two primary elements: - Barcode Pick: The data capture mode that is used for scan and pick functionality. - A Barcode Pick View: The pre-built UI elements used to highlight items to be picked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Pick Mode - Setup the Barcode Pick View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new Data Capture Context. The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the Barcode Pick Mode The main entry point for the Barcode Pick Mode is the `BarcodePick` object. You can configure the supported Symbologies through its [`BarcodePickSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-pick-settings.html), and set up the list of items that you want MatrixScan Pick to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```csharp BarcodePickSettings settings = new BarcodePickSettings(); settings.EnableSymbology(Symbology.Ean13Upca, true); ``` Then you have to create the list of items that will be picked and quantity to be picked for each item. ```csharp ICollection productsToPick = new List() { new BarcodePickProduct("9783598215438", 3), new BarcodePickProduct("9783598215414", 3) }; ``` Create a product provider that maps scanned barcodes to your product list, and then the mode with the previously created settings: ```csharp // 'this' must implement IBarcodePickAsyncMapperProductProviderCallback IBarcodePickProductProvider productProvider = new BarcodePickAsyncMapperProductProvider(productsToPick, callback: this); BarcodePick barcodePick = new BarcodePick(dataCaptureContext, settings, productProvider); ``` ## Setup the `BarcodePickView` MatrixScan Pick’s built-in AR user interface includes buttons and overlays that guide the user through the scan and pick process. By adding a [`BarcodePickView`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-pick-view.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickView), the scanning interface is added automatically to your application. The `BarcodePickView` appearance can be customized through [`BarcodePickViewSettings`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/barcode-pick-view-settings.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickViewSettings) to match your application’s look and feel. The following settings can be customized: * Colors of dots in augmented reality overlay * Enable sound and haptic alerts * Guidelines text * Showing hints * Finish button * Pause button * Zoom button * Loading Dialog ```csharp BarcodePickViewSettings viewSettings = new BarcodePickViewSettings(); // ... ``` (The parent view can be any subclass of ViewGroup, such as FrameLayout, …) Construct a new `BarcodePickView`. The `BarcodePickView` is automatically added to the provided parent view. ```csharp BarcodePickView barcodePickView = BarcodePickView.Create(parentView, dataCaptureContext, barcodePick, viewSettings); ``` You can use a `BarcodePickView` from XAML in your MAUI application. ```xml ``` You can configure your view in the code behind class. For example: ```csharp public partial class MyFindBarcodePage : ContentPage { public MyFindBarcodePage() { this.InitializeComponent(); // Initialization of BarcodePickView happens on handler changed event. this.BarcodePickView.HandlerChanged += SetupBarcodePickView; } private void SetupBarcodePickView(object? sender, EventArgs args) { // Your BarcodePickView configuration goes here, e.g. subscribe for button tap events } } ``` :::important For MAUI development add the [`Scandit.DataCapture.Barcode.Maui`](https://www.nuget.org/packages/Scandit.DataCapture.Barcode.Maui) NuGet package into your project. ::: Connect the `BarcodePickView` to the iOS view controller lifecycle. In particular, make sure to call `BarcodePickView.prepareSearching()` on your UIViewController’s [`viewWillAppear`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621510-viewwillappear) method to make sure that start up time is optimal. ```csharp public override void ViewWillAppear(bool animated) { base.ViewWillAppear(animated); BarcodePickView.PrepareSearching(); } public override void ViewWillDisappear(bool animated) { base.ViewWillDisappear(animated); BarcodePickView.StopSearching(); } ``` If your are developing on MAUI then connect the BarcodePickView to the MAUI page lifecycle. In particular, make sure to call `BarcodePickView.OnResume` on your [`Element.HandlerChanged`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.maui.controls.element.handlerchanged) event and `BarcodePickView.OnPause` on your [`Page.OnDisappearing`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.maui.controls.page.ondisappearing). ```csharp public FindBarcodePage() { this.BarcodePickView.HandlerChanged += SetupBarcodePickView; } private void SetupBarcodePickView(object? sender, EventArgs args) { #if __IOS__ this.BarcodePickView.PrepareSearching(); #endif } protected override void OnDisappearing() { base.OnDisappearing(); this.BarcodePickView.StopSearching(); } ``` ## Subscribe to View Events The `BarcodePickView` displays a **Finish** button next to its shutter button. Subscribe to a `BarcodePickView.onFinishButtonTapped` event to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```csharp BarcodePickView.FinishButtonTapped += (object? sender, FinishButtonTappedEventArgs e) => { NavigationController?.PopViewController(animated: true); }; ``` However, this convenient “finish” button is not supported with MAUI development. You can create the button manually and invoke `BarcodePickView.StopSearching` to achieve the same functionality. The following code snippet demonstrates how to do this: `FindBarcodePage.xaml`: ```csharp (...) ``` `FindBarcodePage.xaml.cs`: ```csharp private void FinishButtonClicked(object? sender, EventArgs args) { if (Application.Current?.MainPage is NavigationPage navigation) { BarcodePickView.StopSearching(); navigation.PopToRootAsync(animated: true); } } ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `BarcodePickView.start()`. ```csharp barcodePickView.Start(); ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Pick # About MatrixScan Pick MatrixScan Pick is a pre-built UI that uses augmented reality overlays to highlight specific items that need to be picked. Whereas MatrixScan AR is fully customizable, MatrixScan Pick is a pre-built solution that allows you to add a scan and pick experience with augmented reality to an existing native app, with just a few lines of code. MatrixScan Pick is implemented through functionality provided by [`BarcodePick`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/barcode-pick.html). ## UI Overview * MatrixScan Pick is inspired by the familiar paradigm of a camera, including a shutter button that the user operates in order start and pause the scanning view. The Finish button is used at any time to exit the workflow. * It highlights items with obvious and colorful visual dots on screen. * When paused, MatrixScan Pick freezes the display at the last view, even if the device is moved. The Play button transitions back to the live view. * Textual guidance is displayed from the beginning of the session and as the workflow progresses, informing of the user of changes in item status (i.e. Detected, Ignored, To-Pick, or Picked). * Status icons can be defined to provide further information to users for a given barcode. In the live view, the icons are displayed but not tappable. In the frozen view, the status icons can be tapped and expanded to provide additional textual information. * The Quick Start Guide takes you through the process to install the full UI. However, you can then customize it by choosing to remove any elements on the screen except for the AR overlays. This allows you to create custom UIs suitable for your own workflows. ## Supported Symbologies MatrixScan Find supports all [symbologies](../barcode-symbologies.mdx) **except** DotCode, MaxiCode and postal codes (KIX, RM4SCC). If you are not familiar with the symbologies that are relevant for your use case, you can use capture presets that are tailored for different verticals (e.g. retail, logistics, etc.). --- ## Get Started # Get Started The parser parses data strings, e.g. as found in barcodes, into a set of key-value mappings. In this guide, you will know briefly how to use a parser and what types of parser are currently supported by Scandit. These data formats are supported: [Health Industry Bar Code (HIBC)](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/hibc.html), [GS1 Application Identifier (https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/AI) system](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/gs1ai.html) and [Swiss QR Codes](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/swissqr.html), [VIN Vehicle Identification Number](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/vin.html), [IATA Bar Coded Boarding Pass (BCBP)](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/iata-bcbp.html) More data formats will be added in future releases. Please contact us if the data format you are using is not yet supported, or you want to use the parser on a currently unsupported platform. ## Format-Specific Documentation - [Supported Data Formats](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/formats.html) - [HIBC](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/hibc.html) - [GS1 AI](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/gs1ai.html) - [GS1 Digital Link](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/gs1-digital-link.html) - [Swiss QR](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/swissqr.html) - [VIN](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/vin.html) - [IATA BCBP](https://docs.scandit.com/data-capture-sdk/dotnet.ios/parser/iata-bcbp.html) --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### New Features #### Barcode * Added the SelectionMode API to replace the SparkScan target-mode APIs and `ScanIntention.smartSelection`: Set `selectionMode` (off/on/auto) in the `BarcodeCaptureSettings` and `SparkScanSettings` to control whether an aimed-at barcode is scanned automatically or requires explicit selection. #### Id * Added Irish Garda Age Card as `RegionSpecificSubtype.IrelandAgeCard`. * Added double-sided support for the Oman residence card. * Added single-sided support for extraction of issue date and birth date from the 2025 NYC Municipal ID. #### Smart Label Capture * Extended VIN label capture to also scan Code 128 barcodes (in addition to QR, Code 39, and Data Matrix) via `createVinLabelDefinition()`. * Extended LabelCapture to accept label definitions where both "barcode" and "text" field types use the "semantics" feature simultaneously; previously this was restricted to only one field type at a time. ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Smart Label Capture * Improved Receipt Scanning efficiency by optimizing receipt image processing before extraction. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. * Updated `SymbologyDescription.forIdentifier` to return `null` for unrecognized identifiers (e.g. `"EAN-8"` instead of `"ean8"`); previously such input was silently mapped to `Codabar`. ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a crash in `BarcodeArView` on iOS (.NET MAUI) where an `ApplicationException` was thrown when no `CameraSettings` was supplied; `CameraSettings` is optional, so the view now falls back to default camera settings on iOS instead of throwing, matching Android behavior. * Fixed a memory leak in item-based scanning. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Id * Fixed an issue where cropped document images were rotated when Frame Image was also enabled. * Corrected the orientation of cropped Visa document images that were being rotated incorrectly when scanned using a single-frame image source. * Fixed parser handling of non-standard Surrey BC AAMVA barcodes that were incorrectly returning "Invalid Format". #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed a crash when the `DataCaptureContext` singleton was initialized more than once. ### Deprecations #### Barcode * The SparkScan target-mode APIs and `ScanIntention.smartSelection` are deprecated in favour of selectionMode. ## 8.4.1 **Released**: June 23, 2026 ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in SparkScan when using the item-based API. #### Id * Fixed an issue where cropped document images were rotated when they are recovered using the getFrame API. * Resolved a duplicate Objective-C class registration that could trigger spurious casting failures or crashes when an app links both ScanditCaptureCore and ScanditIdCapture. ## 8.4.0 **Released**: May 18, 2026 ### New Features #### Barcode * Added `dotRadius` property to `BarcodeBatchBasicOverlay` to allow customizing the size of dots when using the Dot overlay style. #### Id * Added support for reading the vehicle table on the back of New Zealand driving licences, with the latest expiry date returned; supported vehicle classes are 1–6, including L=learner and R=restricted variants. * Added support for new versions of USA, California – Driver's License; USA, North Carolina – Driver's License; USA, Texas – Driver's License; and USA, Oklahoma – Driver's License. #### Core * Redesigned `ZoomSwitchControl` to support multiple configurable zoom levels; the control now displays as a compact button that expands to show all available zoom levels, automatically filtered to those supported by the device hardware. * Added a new `PinchToZoom` gesture. * Enhanced `CameraSettings` to support `ZoomLevels` for the .NET API. * Added Camera Switch Control component to .NET. * `DataCaptureView.DataCaptureContext` can now be reassigned at runtime in MAUI, both via code-behind and XAML data binding. Previously, the context could only be set once during view initialization. ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. #### Core * Updated mbedtls from version 3.6.5 to 3.6.6. ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. * Fixed an issue where `BarcodeCountView` would display incorrectly after rotating the device when a sibling view was present in the same parent view. * Fixed an unnecessary second scan callback that occurs after freezing barcode recognition. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed an issue where the Smart Scan Selection aimer would become too small when scan-area margins restricted the visible scan area; the aimer is now sized relative to the view, keeping a consistent on-screen size regardless of margins. #### Id * Fixed an issue where the US Permanent Residence Card was not processed through the VizMrz flow. * Fixed an issue where AAMVA verification was being performed even when no AAMVA document types were enabled in the accepted documents. #### Smart Label Capture * Fixed a memory leak in LabelCapture * Fixed an issue where the validation flow viewfinder was not displayed. * Fixed a race condition in the validation flow. * Fixed a bug where the label capture validation flow overlay sometimes did not reflect label capture settings when reused. * Fixed a bug that caused error messages in `DataCaptureView` to be rendered partially out-of-view. * Fixed a rare race condition in Label Capture. * Added `.asDate()` support to `ExpiryDate` and `PackingDate` label fields when the text is provided as manual input or as an Adaptive-Recognition-Engine response. * Fixed a bug where the receipt scanning overlay and validation flow overlay could not be used on the same LabelCapture mode instance. #### Core * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ### Deprecations #### Core * Added `PinchToZoom` class for the .NET API; deprecated the `ZoomGesture` property in favor of `ZoomGestures`. ## 8.3.1 **Released**: April 14, 2026 ### Bug Fixes #### Smart Label Capture * Fixed the validation flow to accept dates in more formats when manually entered * Fixed a race condition in the validation flow ## 8.3.0 **Released**: March 26, 2026 ### New Features #### Barcode * Added support for composite codes in SparkScan * Added the `LabelCaptureButtonVisible` property and `LabelCaptureButtonTapped` event to `SparkScanView`, allowing users to navigate from SparkScan to Smart Label Capture #### Id * Added support for OCR scanning of the 2026 version of Victoria mobile driver licenses * Added IdCaptureSettings.anonymizeDefaultFields setting that controls whether the SDK applies default anonymization rules for specific document types and regions #### Smart Label Capture * Fixed a rare race condition #### Core * Introduced .NET 10 support on Scandit SDK for .NET * Added LabelCapture Validation Flow Manual input support for allowing developers to receive a callback when the users trigger the manual input, as well as placeholder support for the overlay’s text fields. Existing users of the Validation Flow must implement the new interface when upgrading to this version. ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Improved speed of MatrixScan Count scanning phase for mid- and high-end devices ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. #### Id * Fixed BarcodeDictionary anonymization setting for iOS and Web * Fixed support for UAE Esaad card * Sanitized name fields on ACT driver license to split FullName and populate first and last name properties * Added support for scanning MRZ from the back of Argentinian DN when using `FullDocumentScanner` * Fixed misplaced MRZ anonymization on FullFrame images. #### Core * Fixed issue where Camera now always returns a valid instance (backed by NoOpCamera when no native camera is available) * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.2.1 **Released**: March 5, 2026 ### Bug Fixes #### Id * Sanitized name fields on ACT DL. Splits FullName to populate first and last name properties #### Smart Label Capture * Fixed a rare race condition ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Smart Label Capture * [Smart Label Capture](/sdks/net/ios/label-capture/intro.md) is now available on .NET for Android. It enables multi-modal data capture, extracting barcode and text data from labels simultaneously and making complex data entry up to 7 times faster. Ideal for labels containing serial numbers, weights, or expiry dates, it improves accuracy, reduces errors, and prevents revenue loss from incorrect information. ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed BarcodeCount Scan Preview issues including: fixed an issue where preview barcodes were used to populate the scanning list, the correct feedback is played when a barcode not in list is scanned, fixed an issue where scanning was not possible after the app was put in background, and corrected highlight orientation in landscape * Fixed an issue where MatrixScan AR circle highlights stopped pulsing when the app was restored from the background * Added cameraStateOnStop property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed the missing found item icon in the MatrixScan Find carousel #### Id * Treated Puerto Rico driver licenses as AAMVA to enforce barcode capture with FullScanner * Fixed a bug that would cause Canada Northwest Territories driver license scans to be incomplete #### Core * Fixed an issue where the interface and video feed could have different visual orientations * Fixed an issue where some LabelCapture fields were being returned incorrectly on TS frameworks * Fixed `BarcodeBatchBasicOverlayStyle.Frame` such that it now correctly displays as a frame on iOS and MAUI iOS platforms, where previously setting the style to `Frame` would incorrectly render as a dot due to an enum value mismatch in the iOS binding layer ## 8.1.5 **Released**: June 10, 2026 ### New Features #### Barcode * Added an option to configure the duration of BarcodeSequence's idle timeout. ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in item-based scanning. #### Smart Label Capture * Fixed a memory leak in LabelCapture. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. #### Core * Fixed a rare issue that was causing a crash when the app moved to the background. ## 8.1.3 **Released**: March 25, 2026 ### Bug Fixes #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.1.2 **Released**: March 9, 2026 ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session #### Smart Label Capture * Fixed a rare race condition ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Core * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed an issue where the interface and video feed could have different visual orientations ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Smart Scan Selection is now available in Barcode Capture. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. * Added, in `BarcodeAr`, a new annotation type (`BarcodeArResponsiveAnnotation`), which automatically switches between close-up and far-away info annotations based on the barcode's size on screen #### Id * Added NationalityISO property that maps results from Nationality field to country ISO code * Added RejectionDiagnosticJSON property to CapturedId to report debug info during Timeout rejections * Added support for new California DL, new South Carolina DL, Arizona Medical Marijuana Card, Kuwait Civil card, and new Texas DL * Our SDK can now scan the following documents both in single-side and double-side mode: - All Mexican DLs - Mexican Voter Cards ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the ["strict" symbology extension](../symbology-properties#symbology-extension-descriptions) ### Behavioral Changes #### Barcode * Enabling the ["ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 ("Missing Resource") #### Core * Added the `CodeDuplicate` class to simplify setting special sentinel values for the CodeDuplicateFilter property across barcode scanning modes. ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Added the `cameraStateOnStop` property to BarcodeFindView to optimize camera transitions when switching between modes #### Id * Fixed an issue where front expiry date anonymization rectangle is erroneously drawn on front and back * Fixed a bug that prevented VizResult anonymization of the following fields: additionalAddressInformation, bloodType, employer, fathersName, issuingAuthority, maritalStatus, mothersName, placeOfBirth, profession, race, residentialStatus * Fixed a bug concerning return complete instead of cropped images on the back of EU driving licenses #### Core * Fixed a small memory leak that affected fresh install runs only * Fixed an issue where barcode scanning would permanently stop after the app returned from background, particularly when camera permission dialogs were shown during initialization ## 8.0.1 **Released**: January 14, 2026 ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance #### Core * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a small memory leak that affected fresh install runs only ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. #### Core * We've fundamentally redesigned our .NET SDK's architecture to better align with the modern .NET ecosystem! * **Platform-Agnostic .net8.0 and net9.0 Targets**: The SDK now includes generic net8.0 and .net9.0 targets. This allows you to reference `Scandit.DataCapture.Core` and related packages directly from non-UI projects, such as class libraries or unit test projects. This makes it significantly easier to build modular, testable applications following principles like Clean Architecture. * **Mandatory SDK Initialization**: Due to the architectural changes, the SDK now requires explicit initialization at application startup. The public API has not changed, but you must add the corresponding initialization code to your application for the SDK to function correctly. #### ID * Added `ElementsToRetain` to `MobileDocumentScanner`: The set of data elements that the application intends to retain from scanned mobile documents. This information is used to set the `IntentToRetain` flag in ISO 18013-5 mdoc requests, which is required for legal compliance with data protection standards. An empty set indicates no elements will be retained, and `IntentToRetain` will be set to `false` for all fields. * ID Capture now supports full-frame anonymization. * The result of `decodeMobileDriverLicenseViz`, which is currently returned as part of the `VizResult` within `CapturedId`, will now be provided through a new field named `mobileDocumentOcr`. * Added `CapturedId::isCitizenPassport`, which indicates whether the passport was issued to a citizen of the issuing country. Returns `false` for travel documents such as refugee, stateless, or alien passports, and for any passports issued by organizations rather than states. * The following Chinese travel permits now extract VIZ + MIZ data during double-sided scanning flows: * CT - Taiwan Residents Mainland Travel Permit * W - Mainland Residents Exit-Entry Permit to and from Hong Kong and Macao * CD - Mainland Residents Entry-Exit Permit to and from Taiwan ### Behavioral Changes #### Barcode * Symbology `RM4SCC` has been renamed to `ROYAL_MAIL_4STATE`. * Changed the default highlight brush in SparkScan and Barcode Capture. #### ID * The configuration for the following documents has been changed as detailed below: * Australian mobile driver licenses (mDL) are now treated as normal documents, with no separate mode. * US Green Cards are now treated as residence permits. * Removed the deprecated API `DateResult::toDate`. Use `DateResult::toLocalDate` or `DateResult::toUtcDate` instead. * `fullName` now an optional field on all `IdCapture` result types and `capturedMrz` now an optional field on `MrzResult`. ### Bug Fixes #### ID * Fixed a bug that could get the scanner stuck when scanning a US passport card. ### Deprecations #### Core * `VideoResolution::Auto` is now deprecated. Please use the capture mode's `recommendedCameraSettings` for the best results. #### Barcode * All previously deprecated APIs have been removed in this release. ## 7.6.7 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/net/ios/release-notes) --- ## Advanced Configurations # Advanced Configurations SparkScan is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are some cases where you might want to customize the behavior of SparkScan. This guide will show you how to add additional capabilities and further customize SparkScan to best fit your needs. ## Advanced Capabilities ### Hardware Button Control Allowing the end user to control the scanner with hardware buttons can be useful if your users typically wear gloves. It can also improve ergonomics in some workflows. SparkScan offers a built-in API to let you do this via [scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled). 10s) typically requires the users to interact with the UI to start scanning again. This is a good choice when you want to interrupt the scanning workflow (e.g. because a wrong barcode is scanned and some actions need to be performed). A small timeout (\ { if (isValidBarcode(barcode)) { return new SparkScanBarcodeSuccessFeedback(); } else { return new SparkScanBarcodeErrorFeedback( 'This code should not have been scanned', 60 * 1000, Color.fromHex('#FF0000'), new Brush(Color.fromHex('#FF0000'), Color.fromHex('#FF0000'), 1), ); } }, }; ``` You can have different error states triggered by different logic conditions. For example you can trigger an error state when a wrong barcode is scanned, and another one when a duplicate barcode is scanned. These errors can show different colors and have different timeouts. This error state for a code that should not have been scanned. This error state for a code that has been scanned more than once. --> ### Reject Barcodes To prevent scanning unwanted barcodes (like those already listed or from incorrect lots), use SparkScan’s built-in error state. Setting the [SDCSparkScanBarcodeErrorFeedback.resumeCapturingDelay](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/spark-scan-barcode-feedback.html#property-scandit.datacapture.barcode.spark.feedback.Error.ResumeCapturingDelay) parameter to `0` allows the user to continue scanning immediately without pausing on rejected codes. ## UI Customization :::tip Please refer to [SparkScanView](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) for the full list of parameters. ::: import Customization from '../../../../partials/advanced/_sparkscan-customization.mdx'; ## Workflow Options This section explains all the available options to configure SparkScan to best fit your case, in case you found something that didn't work well in the default configuration (that remains our recommended option). Developers can set a combination of scanning mode, scanning behavior and camera preview behavior - defining the initial state of the scanner. This can be done by setting the default scanning mode (SDCSparkScanViewSettings.DefaultScanningMode). This combination allows for flexible configurations to suit different scanning needs. ### Scanning Mode The scanning mode determines the programmatic presence of an aimer in the preview to help with precision scanning. | Mode | Description | | ----------- | --------------------------------------------------- | | **Default** | Generally recommended. This mode will display a small camera preview to aid with aiming. The preview size and zoom level can be adjusted as needed. User can aim easily at the intended barcode. | | **Target** | This mode will always add an aimer to the camera preview to precisely select the barcode to scan. This is recommended only when selecting among many close barcodes is the common task. | :::tip Even in the *Default* mode, SparkScan will automatically show an aimer when multiple barcodes are present in the view and no clear intention from the user to scan a single one is recorded ([`SDCSparkScanSettings.ScanIntention`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/spark-scan-settings.html#property-scandit.datacapture.barcode.spark.SparkScanSettings.ScanIntention)). Enabling the *Target* mode will simply force this "precision selection" state to be on at all time. ::: ### Scanning Behavior The scanning behavior determines how barcodes are scanned - one at a time or continuously. | Behavior | Description | | ------------------- | ---------------------------------------------------------- | | **Single scan** | Scan one barcode at a time. The user needs to trigger the scanner every time to scan a barcode. This allows for a more controlled scanning and lower battery consumption. | | **Continuous scan** | Scan barcodes consecutively. The user needs to trigger the scanner once and barcodes will be scanned without any further interaction before each scan. This allows for a smoother experience when multiple barcodes need to be scanned consecutively. | :::tip Users can enable continuous scanning by holding down the trigger button. This gesture can be disabled (`SDCSparkScanViewSettings.HoldToScanEnabled`). ::: ### Preview Behavior The preview behavior determines how the camera preview behaves when the scanner is not actively scanning. | Behavior | Description | | -------------- | -------------------------- | | **Default** | Preview fades away when the scanner is off. This lets the user check important information displayed by the app and reduces battery consumption. | | **Persistent** | Preview remains visible, but darkened, even when the scanner is off. This is useful for scenarios where you want to select a barcode (among many) or need to look through the preview at all times (to ensure the right scan) - especially if used in conjunction with the target mode. | --- ## Get Started # Get Started In this guide you will learn step-by-step how to add SparkScan to your application by: - Create a new Data Capture Context instance. - Configure the Spark Scan Mode. - Create the SparkScanView with the desired settings and bind it to the application’s lifecycle. - Register the listener to be informed when new barcodes are scanned and update your data whenever this event occurs. ## Create a New Data Capture Context Instance The first step to add capture capabilities to your application is to create a new [Data Capture Context](https://docs.scandit.com/data-capture-sdk/dotnet.ios/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```csharp DataCaptureContext dataCaptureContext = DataCaptureContext.ForLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --"); ``` ## Configure the SparkScan Mode The SparkScan Mode is configured through SparkScanSettings and allows you to register one or more listeners that are informed whenever a new barcode is scanned. For this tutorial, we will set up SparkScan for scanning EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```csharp SparkScanSettings settings = new SparkScanSettings(); HashSet symbologies = new HashSet() { Symbology.Ean13Upca }; settings.EnableSymbologies(symbologies); ``` Next, create a SparkScan instance with the settings initialized in the previous step: ```csharp SparkScan sparkScan = new SparkScan(settings); ``` ## Setup the Spark Scan View The SparkScan built-in user interface includes the camera preview and scanning UI elements. These guide the user through the scanning process. The SparkScanView appearance can be customized through SparkScanViewSettings. ```csharp SparkScanViewSettings viewSettings = new SparkScanViewSettings(); // setup the desired appearance settings by updating the fields in the object above ``` By adding a [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/spark-scan-view.html), the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/spark-scan-view.html) to your view hierarchy: Construct a new SparkScan view. The SparkScan view is automatically added to the provided parentView: ```csharp SparkScanView sparkScanView = SparkScanView.Create(parentView, dataCaptureContext, sparkScan, viewSettings); ``` See the [SparkScan Workflow Options](./advanced.md#workflow-options) section for more information. When developing on MAUI the SparkScan view should be added as the last item to [AbsoluteLayout](https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/absolutelayout) or [RelativeLayout](https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/relativelayout), to make sure other UI components are visible. ```xml ``` Additionally, make sure to call [SparkScanView.ViewWillAppear()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.ViewWillAppear) and [SparkScanView.ViewWillDisappear()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.ViewWillDisappear) in your UIViewController’s [ViewWillAppear](https://learn.microsoft.com/en-us/dotnet/api/uikit.uiviewcontroller.viewwillappear) and [ViewWillDisappear](https://learn.microsoft.com/en-us/dotnet/api/uikit.uiviewcontroller.viewwilldisappear) callbacks, to make sure that start up time is optimal and scanning is stopped when the app is going in the background. ```csharp public override void ViewWillAppear(bool animated) { base.ViewWillAppear(animated); sparkScanView.ViewWillAppear(); } public override void ViewWillDisappear(bool animated) { base.ViewWillDisappear(animated); sparkScanView.ViewWillDisappear(); } ``` When developing on MAUI, make sure to call SparkScanView.OnAppearing and SparkScanView.OnDisappearing in your [Page.OnAppearing](https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.page.onappearing) and [Page.OnDisappearing](https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.page.ondisappearing) callbacks, to make sure that start up time is optimal and scanning is stopped when the app is going in the background. ```csharp protected override void OnAppearing() { base.OnAppearing(); this.SparkScanView.OnAppearing(); } protected override void OnDisappearing() { base.OnDisappearing(); this.SparkScanView.OnDisappearing(); } ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [ISparkScanListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface and register the listener to the SparkScan mode. ```csharp // Register self as a listener to monitor the spark scan session. sparkScan.AddListener(this); ``` [ISparkScanListener.OnBarcodeScanned()](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/spark-scan-listener.html#method-scandit.datacapture.barcode.spark.ISparkScanListener.OnBarcodeScanned) is called when a new barcode has been scanned. This result can be retrieved from the first object in the provided barcodes list: [SparkScanSession.NewlyRecognizedBarcode](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/spark-scan-session.html#property-scandit.datacapture.barcode.spark.SparkScanSession.NewlyRecognizedBarcode). Please note that this list only contains one barcode entry. ```csharp public void OnBarcodeScanned(SparkScan sparkScan, SparkScanSession session, IFrameData? data) { Barcode? barcode = session.NewlyRecognizedBarcode; if (barcode == null) { return; } // This method is invoked from a recognition internal thread. // Run the specified action in the UI thread to update the internal barcode list. DispatchQueue.MainQueue.DispatchAsync(() => { // Update the internal list and the UI with the barcode retrieved above this.latestBarcode = barcode; }); } ``` Alternatively to register [ISparkScanListener](https://docs.scandit.com/data-capture-sdk/dotnet.ios/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface it is possible to subscribe to corresponding events. For example: ```csharp sparkScan.BarcodeScanned += (object sender, SparkScanEventArgs args) => { Barcode? barcode = args.Session.NewlyRecognizedBarcode; if (barcode == null) { return; } // This method is invoked from a recognition internal thread. // Run the specified action in the UI thread to update the internal barcode list. DispatchQueue.MainQueue.DispatchAsync(() => { // Update the internal list and the UI with the barcode retrieved above this.latestBarcode = barcode; // Emit sound and vibration feedback this.sparkScanView.EmitFeedback(new SparkScanViewSuccessFeedback()); }); }; ``` ## Scan Some Barcodes Now that you’re up and running, go find some barcodes to scan. Don’t feel like getting up from your desk? Here’s a [handy pdf of barcodes](https://github.com/Scandit/.github/blob/main/images/PrintTheseBarcodes.pdf) you can print out. --- ## About SparkScan # About SparkScan SparkScan is our pre-built smartphone scanning interface designed for high-performance barcode scanning. It fits on top of any smartphone application, providing an intuitive user interface for simple, fast and ergonomic scanning in scan-intensive workflows such as inventory management in retail, or goods receiving in logistics. SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs. ## UI Overview The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience. Two main elements compose the UI: ![SparkScan UI](/img/sparkscan/features_web.png) - **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc). - **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space. There are additional UI elements available for displaying additional scanning modes, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section. ## Workflow Description When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use. To start scanning, the user can simply tap on it. When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app). In the default configuration: - Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away. - Tapping on the trigger button or the mini preview will restart immediately the scanner. Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state. If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released. List building use case using SparkScan. The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field. But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more. ## Supported Symbologies SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx). ## AI-Powered Features SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide. --- ## Installation import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Installation This guide shows you how to add the Scandit Data Capture SDK to your existing project. ## Prerequisites - The latest stable version of [React Native CLI and other related tools and dependencies](https://reactnative.dev/docs/environment-setup). - A project with: - minimum node version of 18 or higher. - minimum iOS deployment target of 15.0 or higher - an Android project with target SDK version 23 (Android 6, Marshmallow) or higher (version 24 or higher for ID Capture) - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). :::tip Android devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ### Internal Dependencies Certain Scandit Data Capture SDK modules have package dependencies. | Module | Dependencies | Optional Dependencies | | ----------- | ----------- | ----------- | | *scandit-react-native-datacapture-core* | None | None | | *scandit-react-native-datacapture-barcode* | *scandit-react-native-datacapture-core* | None | | *scandit-react-native-datacapture-id* | *scandit-react-native-datacapture-core* | *scandit-react-native-datacapture-id-europe-driving-license**scandit-react-native-datacapture-id-aamva-barcode-verification* *scandit-react-native-datacapture-id-voided-detection* | | *scandit-react-native-datacapture-parser* | None | None | | *scandit-react-native-datacapture-label* | *scandit-react-native-datacapture-core* *scandit-react-native-datacapture-barcode* | *scandit-react-native-datacapture-label-text* *scandit-react-native-datacapture-price-label* | :::tip When using ID Capture or Label Capture, consult the respective module's getting started guides to identify the optional dependencies required for your use case. The modules you need to include will vary based on the features you intend to use. Please be aware that your license may only cover a subset of Barcode and/or ID Capture features. If you require additional features, [contact us](mailto:support@scandit.com). ::: ## Get a License Key 1. [Sign up](https://ssl.scandit.com/dashboard/sign-up?p=test) or [Sign in](https://ssl.scandit.com/dashboard/sign-in) to your Scandit account 2. Create a project 3. Create a license key If you have a paid subscription, please reach out to [Scandit Support](mailto:support@scandit.com) if you need a new license key. ## Add the SDK Choose your preferred installation method below. Installing from the package registry is simpler and recommended for most users, while manual installation gives you more control over the SDK version. :::tip You should always make sure to add the `scandit-react-native-datacapture-core` plugin, as all other plugins depend on it. ::: ### Create a new project If you do not have a React Native project yet that you'll use, you should create a new one. ```sh react-native init HelloScandit cd HelloScandit ``` ### Install from Package Registry To add Scandit plugins from the package registry, run the corresponding commands from your project's root folder. **Install the core plugin (required):** ```sh yarn add scandit-react-native-datacapture-core ``` ```sh npm install scandit-react-native-datacapture-core ``` **Then add the plugin(s) for your desired functionality:** ```sh # For barcode scanning yarn add scandit-react-native-datacapture-barcode # For ID capture yarn add scandit-react-native-datacapture-id # For label capture yarn add scandit-react-native-datacapture-label ``` ```sh # For barcode scanning npm install scandit-react-native-datacapture-barcode # For ID capture npm install scandit-react-native-datacapture-id # For label capture npm install scandit-react-native-datacapture-label ``` :::tip You can add only the plugins you need as described in the [Internal Dependencies](#internal-dependencies) section. You can also specify a version `@`. ::: ### Install Manually from Dashboard #### Step 1: Download the SDK from Scandit Dashboard 1. Navigate to the [Scandit Dashboard Downloads page](https://ssl.scandit.com/dashboard/downloads) 2. Sign in to your Scandit account 3. Locate the **React Native** section 4. Click the **Download** button to download the latest React Native SDK archive (`.zip` file) #### Step 2: Extract and locate the plugins 1. Extract the downloaded `.zip` file to a location of your choice (e.g., `~/Downloads/scandit-react-native-sdk/`) 2. The extracted archive contains multiple React Native plugin folders, each representing a different SDK module. #### Step 3: Install the plugins to your project Navigate to your React Native project root directory and install the plugins using their local paths. **Install the core plugin (required):** ```sh yarn add file:../path/to/extracted/scandit-react-native-datacapture-core ``` ```sh npm install file:../path/to/extracted/scandit-react-native-datacapture-core ``` **Then add the plugin(s) for your desired functionality:** ```sh # For barcode scanning yarn add file:../path/to/extracted/scandit-react-native-datacapture-barcode # For ID capture yarn add file:../path/to/extracted/scandit-react-native-datacapture-id # For label capture yarn add file:../path/to/extracted/scandit-react-native-datacapture-label ``` ```sh # For barcode scanning npm install file:../path/to/extracted/scandit-react-native-datacapture-barcode # For ID capture npm install file:../path/to/extracted/scandit-react-native-datacapture-id # For label capture npm install file:../path/to/extracted/scandit-react-native-datacapture-label ``` ### Additional steps on iOS 1. Camera permissions are required to stream the frame source data into various capture modes. You need to set the “Privacy - Camera Usage Description” field in the Info.plist file for iOS. ```xml NSCameraUsageDescription Access to the camera is required for scanning. ``` ![Info file](./img/info-file.png) 2. Then, install the iOS CocoaPods after installing the React Native `node_modules`. **Important:** This project uses Scandit's private CocoaPods repository. First-time setup: ```sh # Add Scandit's private CocoaPods repository (one-time setup) pod repo add scandit-private-specs https://github.com/Scandit/scandit-cocoapods-specs.git ``` Then, install the CocoaPods dependencies: ```sh cd ios && pod install && cd .. ``` :::note The public CocoaPods trunk repository is becoming read-only. Scandit has migrated to a private CocoaPods specs repository to ensure continued support and updates for iOS framework integrations. The repository is publicly accessible at https://github.com/Scandit/scandit-cocoapods-specs. **Troubleshooting**: If you encounter issues: - Verify the repo is added: `pod repo list | grep scandit-private-specs` - Update the repo: `pod repo update scandit-private-specs` ::: ## Additional Information ### Android Content Providers On Android, the Scandit SDK uses content providers to initialize the scanning capabilities properly. If your own content providers depend on the Scandit SDK, choose an **initOrder** lower than 10 to make sure the SDK is ready first. If not specified, **initOrder** is zero by default and you have nothing to worry about. Check [the official `` documentation](https://developer.android.com/guide/topics/manifest/provider-element). ### Camera Permissions When using the Scandit Data Capture SDK you will want to set the camera as the frame source for various capture modes. On Android, you have to request camera permissions in your own application before starting scanning. To see how you can achieve this, take a look at our [samples](https://github.com/Scandit/datacapture-react-native-samples). import OSSLicense from '../../partials/_third-party-licenses-js.mdx'; --- ## Agent Skills import SkillsPage from '@site/src/components/SkillsPage'; # Agent Skills for React Native --- ## Configure Barcode Symbologies # Configure Barcode Symbologies import Intro from '../../../partials/configure-symbologies/_intro.mdx' ## Enable the Symbologies You Want to Read import EnableSymbologies from '../../../partials/configure-symbologies/_enable-symbologies.mdx' The following code shows how to enable scanning Code 128 codes for Barcode Capture: ```js const settings = new BarcodeCaptureSettings(); settings.enableSymbology(Symbology.Code128, true); ``` import CapturePresents from '../../../partials/configure-symbologies/_capture-presents.mdx' ## Configure the Active Symbol Count Barcode symbologies (such as Code 128, Code 39, Code 93, or Interleaved Two of Five) can store variable-length data. For example, Code 39 can be used to store a string from 1 to 40-50 symbols. There is no fixed upper limit, though there are practical limitations to the code’s length for it to still be conveniently readable by barcode scanners. For performance reasons, the Scandit Data Capture SDK limits the [possible symbol range](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.ActiveSymbolCounts) for variable-length symbologies. If you want to read codes that are shorter/longer than the specified default range or you want to tailor your app to only read codes of a certain length, you need to change the active symbol count of the symbology to accommodate the data length you want to use in your application. The below lines of code show how to change the active symbol count for Code 128 to read codes with 6, 7 and 8 symbols. ```js const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code128); symbologySettings.activeSymbolCounts = [6, 7, 8]; ``` import CalculateSymbolCount from '../../../partials/configure-symbologies/_calculate-symbol-count.mdx' ## Read Bright-on-Dark Barcodes Most barcodes are printed using dark ink on a bright background. Some symbologies allow the colors to be inverted and can also be printed using bright ink on a dark background. This is not possible for all symbologies as it could lead to false reads when the symbology is not designed for this use case. See [symbology properties](../symbology-properties.mdx) to learn which symbologies allow color inversion. When you enable a symbology as described above, only dark-on-bright codes are enabled (see [SymbologySettings.isEnabled](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.IsEnabled)). When you also want to read bright-on-dark codes, color-inverted reading for that symbology must also be enabled (see [SymbologySettings.isColorInvertedEnabled](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.IsColorInvertedEnabled)): ```js const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code128); symbologySettings.isColorInvertedEnabled = true; ``` ## Enforce Checksums Some symbologies have a mandatory checksum that will always be enforced while others only have optional [checksums](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/checksum.html#enum-scandit.datacapture.barcode.Checksum). Enforcing an optional checksum will reduce false positives as an additional check can be performed. When enabling a checksum you have to make sure that the data of your codes contains the calculated checksum otherwise the codes get discarded as the checksum doesn’t match. All available checksums per symbology can be found in [symbology properties](../symbology-properties.mdx). You can enforce a specific checksum by setting it through [SymbologySettings.checksums](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.Checksums): ```js const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code39); symbologySettings.checksums = [Checksum.Mod43]; ``` ## Enable Symbology-Specific Extensions Some symbologies allow further configuration. These configuration options are available as symbology extensions that can be enabled/disabled for each symbology individually. Some extensions affect how the data in the code is formatted, others allow for more relaxed recognition modes that are disabled by default to eliminate false reads. All available extensions per symbology and a description of what they do can be found in the documentation on [symbology properties](../symbology-properties.mdx). To enable/disable a symbology extension, use [SymbologySettings.setExtensionEnabled()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/symbology-settings.html#method-scandit.datacapture.barcode.SymbologySettings.SetExtensionEnabled). The following code shows how to enable the full ASCII extension for Code 39. ```js const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code39); symbologySettings.setExtensionEnabled('full_ascii', true); ``` This extension allows Code 39 to encode all 128 ASCII characters instead of only the 43 characters defined in the standard. The extension is disabled by default as it can lead to false reads when enabled. --- ## Get Started import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Get Started In this guide you will learn step-by-step how to add Barcode Capture to your application. The general steps are: - Include the ScanditBarcodeCapture library and its dependencies to your project, if any. - Create a new [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) instance, initialized with your license key. - Create a [BarcodeCaptureSettings](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and enable the [BarcodeSymbologies](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology) you want to read in your application. - Create a new [BarcodeCaptureMode](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance and initialize it with the settings created above. - Register a [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [Camera](https://docs.scandit.com/data-capture-sdk/react-native/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [BarcodeCaptureOverlay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) and add it to [DataCaptureView](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## 1. Obtain a Scandit License Key A valid Scandit Data Capture SDK license key is required enable any capture mode. Sign into your Scandit account and create a new Scandit license key or copy an existing one. :::tip You can create or copy your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: For new projects, create a new _cross-platform_ license key. Depending on the type of license key, it may require entering an iOS Bundle ID and/or Android App ID. If these values are not identical between platforms, the Bundle ID and App ID can both be entered separated by a comma. ## 2. Download the Scandit SDK Add the Scandit SDK dependencies to your current project. Lean more about the [installation requirements](/sdks/react-native/add-sdk). ```sh npm i scandit-react-native-datacapture-core scandit-react-native-datacapture-barcode ``` ```sh yarn add scandit-react-native-datacapture-core scandit-react-native-datacapture-barcode ``` ```sh pnpm add scandit-react-native-datacapture-core scandit-react-native-datacapture-barcode ``` ```sh bun add scandit-react-native-datacapture-core scandit-react-native-datacapture-barcode ``` ## 3. Create the Data Capture Context import DataCaptureContextReactNative from '../../../partials/get-started/_create-data-capture-context-react-native.mdx'; ## 4. Configure the Barcode Scanning Behavior [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) is one of the [DataCaptureMode](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode) options within the Scandit SDK which scans individual barcodes. This mode is attached to a [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) and configured by applying the [BarcodeCaptureSettings](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings). Then, attaching the [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) will provide new [Barcode](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode.html#class-scandit.datacapture.barcode.Barcode) values when recognized. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called a [Symbology](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. Each additional Symbology may reduce recognition speed, therefore only enable the symbologies your application requires. ```ts const settings = new BarcodeCaptureSettings(); settings.codeDuplicateFilter = 300; // optionally add a 300ms timeout between scanning identical barcodes settings.enableSymbologies([ Symbology.Code128, Symbology.Code39, Symbology.QR, Symbology.EAN8, Symbology.UPCE, Symbology.EAN13UPCA, ]); // Create a BarcodeCapture instance with the BarcodeCaptureSettings applied. const barcodeCapture = new BarcodeCapture(settings); context.addMode(barcodeCapture); ``` ```js const settings = new BarcodeCaptureSettings(); settings.codeDuplicateFilter = 300; // optionally add a 300ms timeout between scanning identical barcodes settings.enableSymbologies([ Symbology.Code128, Symbology.Code39, Symbology.QR, Symbology.EAN8, Symbology.UPCE, Symbology.EAN13UPCA, ]); // Create a BarcodeCapture instance with the BarcodeCaptureSettings applied. const barcodeCapture = new BarcodeCapture(settings); context.addMode(barcodeCapture); ``` If you are not disabling barcode capture immediately after having scanned the first code, consider setting the [BarcodeCaptureSettings.codeDuplicateFilter](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture-settings.html#property-scandit.datacapture.barcode.BarcodeCaptureSettings.CodeDuplicateFilter) to around 500 or even \-1 if you do not want codes to be scanned more than once. ## 5. Register the Barcode Capture Listener To get informed whenever a new code has been recognized, add a [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) through [BarcodeCapture.addListener()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.AddListener) and implement the listener methods to suit your application’s needs. First implement the [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) interface. For example: ```ts const barcodeCaptureListener: BarcodeCaptureListener = { didScan: async ( barcodeCapture: BarcodeCapture, session: BarcodeCaptureSession, getFrameData: () => Promise ) => { const barcode = session.newlyRecognizedBarcode; // Do something with the barcodes }, }; // Add the BarcodeCaptureListener to the BarcodeCapture mode. barcodeCapture.addListener(barcodeCaptureListener); ``` ```js const barcodeCaptureListener = { didScan: async ( barcodeCapture, session, getFrameData ) => { const barcode = session.newlyRecognizedBarcode; // Do something with the barcodes }, }; // Add the BarcodeCaptureListener to the BarcodeCapture mode. barcodeCapture.addListener(barcodeCaptureListener); ``` ### Rejecting Barcodes To prevent scanning unwanted codes, you can reject them by adding the desired logic to the `didScan` method. This will prevent the barcode from being added to the session and will not trigger the `didUpdateSession` method. The example below will only scan barcodes beginning with the digits `09` and ignore all others, using a transparent brush to distinguish a rejected barcode from a recognized one: ```js if (!barcode.data?.startsWith('09:')) { overlay.brush = Brush.transparent; return; } ``` ## Use the Built-in Camera The `DataCaptureContext` supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```ts const cameraSettings = BarcodeCapture.createRecommendedCameraSettings(); // cameraSettings.preferredResolution = VideoResolution.FullHD; // or adjust default camera settings const camera = Camera.withSettings(cameraSettings); // Attaches the Camera object as FrameSource to the DataCaptureContext context.setFrameSource(camera); ... // Setup the BarcodeCaptureMode, BarcodeCaptureListener, etc. camera.switchToDesiredState(FrameSourceState.On); ``` ```js const cameraSettings = BarcodeCapture.createRecommendedCameraSettings(); // cameraSettings.preferredResolution = VideoResolution.FullHD; // or adjust default camera settings const camera = Camera.withSettings(cameraSettings); // Attaches the Camera object as FrameSource to the DataCaptureContext context.setFrameSource(camera); ... // Setup the BarcodeCaptureMode, BarcodeCaptureListener, etc. camera.switchToDesiredState(FrameSourceState.On); ``` The FrameSource for the `DataCaptureContext` configurable by calling [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): The camera is off by default. To turn it on, call [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/react-native/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/react-native/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On). ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js ``` To visualize the results of barcode scanning, the following [overlay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) can be added: ```js const overlay = new BarcodeCaptureOverlay(barcodeCapture); view.addOverlay(overlay); ``` ## Disabling Barcode Capture To disable barcode capture, for instance as a consequence of a barcode being recognized, set [BarcodeCapture.isEnabled](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-capture.html#property-scandit.datacapture.barcode.BarcodeCapture.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## Barcode Generator # Barcode Generator The Barcode Generator is a simple tool to generate barcodes directly from the Scandit SDK. In this guide, we will show you how to use the Barcode Generator to generate barcodes and QR codes. The Barcode Generator supports the following formats: * Code 39 * Code 128 * EAN 13 * UPCA * ITF * QR * DataMatrix * PDF417 (SDK version >= 8.2) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/react-native/add-sdk). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ## Generating Barcodes To generate barcodes, you need to initialize the [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`BarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.BarcodeGeneratorBuilder), and use the method of [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) for the symbology you are interested in, in this example Code 128. You can configure the colors used in the resulting image: ```javascript DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); const builder = BarcodeGenerator.code128BarcodeGeneratorBuilder(DataCaptureContext.sharedInstance) .withBackgroundColor(Color.fromHex('#ffffff')) .withForegroundColor(Color.fromHex('#000000')); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: When the builder is configured get the `BarcodeGenerator` and try to generate the image: ```javascript try { const generator = builder.build(); const image = await generator.generate(dataString, 200); // Use the image } catch (error) { // Handle the error console.error(error); } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-generator.html) for more information. ## Generating QR Codes To generate barcodes, you need to initialize the [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). With the context you can then instantiate a [`QRCodeBarcodeGeneratorBuilder`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-generator-builder.html#class-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder) using the method of [`BarcodeGenerator`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-generator.html#class-scandit.datacapture.barcode.generator.BarcodeGenerator) specific for QR codes. You can configure the colors used in the resulting image, and the two settings that can be configured for QR codes: [`QRCodeBarcodeGeneratorBuilder.errorCorrectionLevel`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithErrorCorrectionLevel) and [`QRCodeBarcodeGeneratorBuilder.versionNumber`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-generator-builder.html#method-scandit.datacapture.barcode.generator.QrCodeBarcodeGeneratorBuilder.WithVersionNumber). ```javascript DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); const builder = BarcodeGenerator.qrCodeBarcodeGeneratorBuilder(DataCaptureContext.sharedInstance) .withBackgroundColor(Color.fromHex('#ffffff')) .withForegroundColor(Color.fromHex('#000000')) .withErrorCorrectionLevel(QrCodeErrorCorrectionLevel.Medium) .withVersionNumber(4); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: When the builder is configured get the `BarcodeGenerator` and try to generate the image: ```javascript try { const generator = builder.build(); const image = await generator.generate(dataString, 200); // Use the image } catch (error) { // Handle the error console.error(error); } ``` See the complete [API reference](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-generator.html) for more information. --- ## Get Started # Get Started :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/react-native/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: In this guide you will learn step-by-step how to add Barcode Selection to your application. The general steps are: - Create a new [data capture context](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) instance, initialized with your license key. - Create a [barcode selection settings](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and choose the right configuration. - Create a new [barcode selection mode](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection 'barcode selection mode class') instance and initialize it with the settings created above. - Register a [barcode selection listener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](https://docs.scandit.com/data-capture-sdk/react-native/core/api/camera.html#class-scandit.datacapture.core.Camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). - If displaying a preview, optionally create a new [overlay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-selection-basic-overlay.html#class-scandit.datacapture.barcode.selection.ui.BarcodeSelectionBasicOverlay) and add it to [data capture view](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) for a better visual feedback. ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create the Data Capture Context import DataCaptureContextReactNative from '../../../partials/get-started/_create-data-capture-context-react-native.mdx'; ## Configure the Barcode Selection Behavior _Symbologies_ Barcode selection is orchestrated by the [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) [data capture mode](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). It is configured through [BarcodeSelectionSettings](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-settings.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) that will get informed whenever new codes have been selected. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called [symbologies](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/symbology.html#enum-scandit.datacapture.barcode.Symbology). The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```js const settings = new BarcodeSelectionSettings(); settings.enableSymbologies([ Symbology.Code128, Symbology.EAN8, Symbology.UPCE, Symbology.EAN13UPCA, ]); ``` _Selection Types_ The behavior of Barcode Selection can be changed by using a different [selection type](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-type.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionType). This defines the method used by [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) to select codes. Currently there are two types. If you want the user to select barcodes with a tap, then use [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection). This selection type can automatically freeze the camera preview to make the selection easier. You can configure the freezing behavior via [BarcodeSelectionTapSelection.freezeBehavior](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.FreezeBehavior). With [BarcodeSelectionTapSelection.tapBehavior](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-tap-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection.TapBehavior) you can decide if a second tap on a barcode means that the barcode is unselected or if it is selected another time (increasing the counter). :::note Using [BarcodeSelectionTapSelection](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-tap-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionTapSelection) requires the MatrixScan add-on. ::: If you want the selection to happen automatically based on where the user points the camera, then use [BarcodeSelectionAimerSelection](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-aimer-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAimerSelection). It is possible to choose between two different [selection strategies](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-strategy.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionStrategy). Use [BarcodeSelectionAutoSelectionStrategy](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionAutoSelectionStrategy) if you want the barcodes to be selected automatically when aiming at them as soon as the intention is understood by our internal algorithms. Use [BarcodeSelectionManualSelectionStrategy](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-strategy.html#class-scandit.datacapture.barcode.selection.BarcodeSelectionManualSelectionStrategy) if you want the barcodes to be selected when aiming at them and tapping anywhere on the screen. _Single Barcode Auto Detection_ If you want to automatically select a barcode when it is the only one on screen, turn on [BarcodeSelectionSettings.singleBarcodeAutoDetection](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-settings.html#property-scandit.datacapture.barcode.selection.BarcodeSelectionSettings.SingleBarcodeAutoDetection). _Creating the mode_ Next, create a [BarcodeSelection](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection.html#class-scandit.datacapture.barcode.selection.BarcodeSelection) instance with the settings initialized in the previous step: ```js const barcodeSelection = new BarcodeSelection(settings); context.addMode(barcodeSelection); ``` ## Register the Barcode Selection Listener To get informed whenever a new code has been recognized, add a [BarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) through [BarcodeSelection.addListener()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection.html#method-scandit.datacapture.barcode.selection.BarcodeSelection.AddListener) and implement the listener methods to suit your application’s needs. First implement the [BarcodeSelectionListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection-listener.html#interface-scandit.datacapture.barcode.selection.IBarcodeSelectionListener) interface. For example: ```js const listener = { didUpdateSelection: (barcodeSelection, session) => { const newlySelectedBarcodes = session.newlySelectedBarcodes; // Do something with the barcodes }, }; ``` Then add the listener: ```js barcodeSelection.addListener(listener); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```js const cameraSettings = BarcodeSelection.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. const camera = Camera.default; if (camera) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js context.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/react-native/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/react-native/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```js camera.switchToDesiredState(FrameSourceState.On); ``` ## Disabling Barcode Selection To disable barcode selection, for instance when the selection is complete, set [BarcodeSelection.isEnabled](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-selection.html#property-scandit.datacapture.barcode.selection.BarcodeSelection.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## About Barcode Selection # About Barcode Selection :::warning We recommend using **SparkScan** or **Barcode Capture API** instead of Barcode Selection. With the new [AI-powered features](/sdks/react-native/ai-powered-barcode-scanning), barcode selection in crowded environments is done without the need of a dedicated API. This API will be deprecated. ::: Barcode Selection enables you to increase scanning accuracy and prevent users from scanning the wrong code in scenarios where there are multiple barcodes present, such as a crowded shelf, an order catalog with barcodes printed closely together, or a label with multiple barcodes. Barcode Selection provides two key capabilities: - **Aim to Select** allows users to select one code at a time. This is especially useful for one-handed operation. - **Tap to Select** is a quick way for users to select several codes from the same view. Selection is done by tapping on highlighted barcodes in the live camera preview or on a frozen screen. :::warning Barcode Selection does not support handling of duplicate codes. If a code appears twice in the visible preview both instances will be marked as selected even if only one of them was selected. ::: --- ## Advanced Configurations # Advanced Configurations There are several advanced configurations that can be used to customize the behavior of the ID Capture SDK and enable additional features. ## Configure Data Anonymization By default, data extracted from documents is anonymized according to local regulations. See [Anonymized Documents](/sdks/react-native/id-capture/supported-documents.md#anonymized-documents) for more information. That means certain data from certain fields won’t be returned, even if it’s present on a document. You control the anonymization level with the following setting: ```js // Default value: settings.anonymizationMode = IdAnonymizationMode.FieldsOnly; // Sensitive data is additionally covered with black boxes on returned images: settings.anonymizationMode = IdAnonymizationMode.FieldsAndImages; // Only images are anonymized: settings.anonymizationMode = IdAnonymizationMode.ImagesOnly; // No anonymization: settings.anonymizationMode = IdAnonymizationMode.None; ``` ## Document Capture Zones By default, a new instance of [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) creates a single-sided scanner type with no accepted or rejected documents. To change this, use the `scannerType` method to set the scanner type to either [SingleSideScanner](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-scanner.html#single-side-scanner) or [FullDocumentScanner](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-scanner.html#full-document-scanner). The `FullDocumentScanner` extracts all document information by default. If using the `SingleSideScanner`, you can specify the document zones to extract: ```js // To extract data from barcodes on IDs const scanner = new SingleSideScanner(true, false, false); // To extract data from the visual inspection zone (VIZ) on IDs const scanner = new SingleSideScanner(false, false, true); // To extract data from the machine-readable zone (MRZ) on IDs const scanner = new SingleSideScanner(false, true, false); ``` ## Configure Accepted and Rejected Documents To configure the documents that should be accepted and/or rejected, use the `acceptedDocuments` and `rejectedDocuments` methods in `IdCaptureSettings`. These methods are used in conjunction with the [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) and [IdCaptureRegion](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-region.html#enum-scandit.datacapture.id.IdCaptureRegion) enums to enable highly flexible document filtering as may be desired in your application. For example, to accept only US Driver Licenses: ```js settings.acceptedDocuments = [new DriverLicense(IdCaptureRegion.Us)]; ``` Or to accept all Passports *except* those from the US: ```js settings.acceptedDocuments = [new Passport(IdCaptureRegion.Any)]; settings.rejectedDocuments = [new Passport(IdCaptureRegion.Us)]; ``` ## ID Images Your use can may require that you capture and extract images of the ID document. Use the [IdImageType](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-image-type.html#enum-scandit.datacapture.id.IdImageType) enum to specify the images you want to extract from the `CapturedId` object For the full frame of the document, you can use [`setShouldPassImageTypeToResult`](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-settings.html#method-scandit.datacapture.id.IdCaptureSettings.SetShouldPassImageTypeToResult) when creating the `IdCaptureSettings` object. This will pass the image type to the result, which you can then access in the `CapturedId` object. ## Callbacks and Scanning Workflows The ID Capture Listener provides two callbacks: `onIdCaptured` and `onIdRejected`. The `onIdCaptured` callback is called when an acceptable document is successfully captured, while the `onIdRejected` callback is called when a document is captured but rejected. For a successful capture, the `onIdCaptured` callback provides a `CapturedId` object that contains the extracted information from the document. This object is specific to the type of document scanned. For example, a `CapturedId` object for a US Driver License will contain different fields than a `CapturedId` object for a Passport. For a rejected document, a [RejectionReason](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) is provided in the `onIdRejected` callback to help you understand why the document was rejected and to take appropriate action. These are: * NOT_ACCEPTED_DOCUMENT_TYPE: The document is not in the list of accepted documents. In this scenario, you could direct the user to scan a different document. * INVALID_FORMAT: The document is in the list of accepted documents, but the format is invalid. In this scenario, you could direct the user to scan the document again. * DOCUMENT_VOIDED: The document is in the list of accepted documents, but the document is voided. In this scenario, you could direct the user to scan a different document. * TIMEOUT: The document was not scanned within the specified time. In this scenario, you could direct the user to scan the document again. ## Detect Fake IDs *ID Validate* is a fake ID detection software. It currently supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). Fake ID detection can be performed automatically using the following settings: * [IdCaptureSettings.rejectForgedAamvaBarcodes](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectForgedAamvaBarcodes): Automatically rejects documents whose AAMVA barcode fails authenticity validation. * [IdCaptureSettings.rejectInconsistentData](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectInconsistentData): Automatically rejects documents whose human‑readable data does not match the data encoded in the barcode or MRZ. To enable ID validation for your subscription, please reach out to [Scandit Support](mailto:support@scandit.com). --- ## Get Started # Get Started This page will guide you through the process of adding ID Capture to your React Native application. ID Capture is a mode of the Scandit Data Capture SDK that allows you to capture and extract information from personal identification documents, such as driver's licenses, passports, and ID cards. The general steps are: - Create a new Data Capture Context instance - Access a Camera - Configure the Capture Settings - Implement a Listener to Receive Scan Results - Set-up the Capture View and Overlay - Start the Capture Process :::warning Using ID Capture at the same time as other modes (e.g. Barcode Capture) is not supported. ::: ## Prerequisites Before starting with your integration, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. See the [installation guide](/sdks/react-native/add-sdk.md) for details. :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import IdModuleOverview from '../../../partials/get-started/_id-module-overview-no-eu-dl.mdx'; ## Create the Data Capture Context import DataCaptureContextReactNative from '../../../partials/get-started/_create-data-capture-context-react-native.mdx'; ## Add the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/react-native/core/api/camera.html#class-scandit.datacapture.core.Camera): ```js const camera = Camera.default; context.setFrameSource(camera); const cameraSettings = IdCapture.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. if (camera != null) { camera.applySettings(cameraSettings); } ``` ## Configure the Capture Settings Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scanner type to use and the documents that should be accepted and/or rejected. Check [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) for all the available options. :::tip By default, [anonymized data](./advanced.md#configure-data-anonymization) is not returned in accordance with local regulations for specific documents. This setting can be disabled for testing purposes, but be sure to comply with local laws and requirements in production. ::: ```js const settings = new IdCaptureSettings(); settings.scanner = new SingleSideScanner(true, false, false); // To scan only one-sided documents // settings.scanner = new FullDocumentScanner(); // To scan both sides of the document settings.acceptedDocuments.push( new DriverLicense(IdCaptureRegion.Any), new Passport(IdCaptureRegion.Any) ); settings.rejectedDocuments.push( new IdCard(IdCaptureRegion.Any) ); ``` ## Implement the Listener To receive scan results, implement and [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener). Capture results are delivered as a [CapturedId](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/captured-id.html#class-scandit.datacapture.id.CapturedId). This class contains data common for all kinds of personal identification documents. For more specific information, use its non-null result properties (e.g. [CapturedId.barcode](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/captured-id.html#property-scandit.datacapture.id.CapturedId.Barcode)). ```js const listener = { didCaptureId: (idCapture, session) => { if (session.newlyCapturedId.isPassport() === true) { // Handle the information extracted. } else if (session.newlyCapturedId.isDriverLicense() === true) { // Handle the information extracted. } }, didFailWithError: (idCapture, error, session) => { // Handle the error. }, }; ``` Create a new ID Capture mode with the chosen settings. Then register the listener: ```js const idCapture = new IdCapture(settings); context.addMode(idCapture); idCapture.addListener(listener); ``` ## Set up Capture View and Overlay When using the built-in camera as frame source, you may typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js ``` Then, add an instance of [IdCaptureOverlay](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) to the view: ```js const overlay = new IdCaptureOverlay(idCapture); ``` The overlay chooses the displayed UI automatically, based on the selected [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings). If you prefer to show a different UI or to temporarily hide it, set the appropriate [IdCaptureOverlay.idLayout](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/ui/id-capture-overlay.html#property-scandit.datacapture.id.ui.IdCaptureOverlay.IdLayout). ## Start the Capture Process Finally, turn on the camera to start scanning: ```js camera.switchToDesiredState(FrameSourceState.On); ``` --- ## About ID Capture import AboutIdCapture from '../../../partials/intro/_about-id-capture.mdx'; --- ## Supported Documents ## ID Scanning Supported Documents Scandit ID Capture provides various [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/react-native/id-capture/api/id-capture-scanner.html#id-capture-scanner) types, each designed for specific scanning workflows. These workflows can involve scanning either specific parts of a document or the entire document, including both the front and back sides. This section details the types of documents supported by each scanner type. import IdDocumentsFull from '../../../partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from '../../../partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents import IdValidateDocuments from '../../../partials/advanced/_id-documents-validate.mdx'; --- ## Advanced Configurations import ValidationFlowHowItWorks from '../../../partials/advanced/_validation-flow-how-it-works.mdx'; import ValidationFlowCustomButtons from '../../../partials/advanced/_validation-flow-custom-buttons.mdx'; import ValidationFlowTypingHints from '../../../partials/advanced/_validation-flow-typing-hints.mdx'; import ValidationFlowCloudVLM from '../../../partials/advanced/_validation-flow-cloud-vlm.mdx'; import ReceiptScanning from '../../../partials/advanced/_receipt-scanning.mdx'; import ValidationFlowRequiredOptional from '../../../partials/advanced/_validation-flow-required-optional.mdx'; import ValidationFlowCustomToasts from '../../../partials/advanced/_validation-flow-custom-toasts.mdx'; import ValidationFlowCustomField from '../../../partials/advanced/_validation-flow-custom-field.mdx'; # Advanced Configurations ## Customize the Overlay Appearance To customize the appearance of the overlay, you can implement a [LabelCaptureBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/ui/label-capture-basic-overlay-listener.html#interface-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener). The method [brushForLabel()](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForLabel) is called every time a label captured and [brushForFieldOfLabel()](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForFieldOfLabel) is called for each of its fields to determine the brush for the label or field. ```js import { useMemo, useEffect, useRef } from 'react'; import { Brush, Color } from 'scandit-react-native-datacapture-core'; import { LabelCaptureBasicOverlay, LabelCaptureBasicOverlayListener, } from 'scandit-react-native-datacapture-label'; // Create the overlay for the label capture mode. const basicOverlay = useMemo(() => { return new LabelCaptureBasicOverlay(labelCapture); }, [labelCapture]); // Create a listener to customize the appearance of captured labels and fields. const overlayListener = useMemo(() => ({ /** * Called for each field of a captured label to determine its brush. * Return a Brush to customize the field's appearance, or null to use the default. */ brushForFieldOfLabel: (overlay, field, label) => { // Create colors with transparency (alpha 0.5 = 50% opacity). const cyanColor = Color.fromRGBA(0, 255, 255, 0.5); const orangeColor = Color.fromRGBA(255, 165, 0, 0.5); switch (field.name) { case "Barcode": // Highlight barcode fields with a cyan color. return new Brush(cyanColor, cyanColor, 0); case "Expiry Date": // Highlight expiry date fields with an orange color. return new Brush(orangeColor, orangeColor, 0); default: // Use a transparent brush for other fields. return Brush.transparent; } }, /** * Called for each captured label to determine its brush. * Return a Brush to customize the label's appearance, or null to use the default. */ brushForLabel: (overlay, label) => { // Use a transparent brush for the label itself. return Brush.transparent; }, /** * Called when the user taps on a label. */ didTapLabel: (overlay, label) => { // Handle user tap gestures on the label. } }), []); // Set up the overlay with the listener and add it to the view. useEffect(() => { // Assign the listener to the overlay. basicOverlay.listener = overlayListener; // Add the overlay to the data capture view. dataCaptureViewRef.current?.addOverlay(basicOverlay); return () => { // Clean up: remove the listener and overlay. basicOverlay.listener = null; dataCaptureViewRef.current?.removeOverlay(basicOverlay); }; }, [basicOverlay, overlayListener]); ``` :::tip Use brush colors with transparency (alpha { return new LabelCaptureAdvancedOverlay(labelCapture, dataCaptureView); }, [labelCapture, dataCaptureView]); // Configure the advanced overlay with a listener that handles AR content creation and positioning const advancedOverlayListener = useMemo(() => ({ // This method is called when a label is detected - we return null since we're only adding AR elements to specific fields, not the entire label viewForCapturedLabel: (overlay, capturedLabel) => { return null; }, // This defines where on the detected label the AR view would be anchored anchorForCapturedLabel: (overlay, capturedLabel) => { return Anchor.Center; }, // This defines the offset from the anchor point for the label's AR view offsetForCapturedLabel: (overlay, capturedLabel, view) => { return new PointWithUnit(0, 0, MeasureUnit.Pixel); }, // This method is called when a field is detected in a label viewForCapturedLabelField: (overlay, labelField) => { // We only want to create AR elements for expiry date fields that are text-based if (labelField.name.toLowerCase().includes("expiry") && labelField.type === LabelFieldType.Text) { // Check if scanned expiry date is too close to actual date const daysUntilExpiry = daysUntilExpiryFunction(labelField.text); // Your method const dayLimit = 3; if (daysUntilExpiry Item expires soon! ); } } // Return null for any fields that aren't expiry dates, which means no AR overlay return null; }, // This defines where on the detected field the AR view should be anchored // BottomCenter places it right below the expiry date text for better visibility anchorForCapturedLabelField: (overlay, labelField) => { return Anchor.BottomCenter; }, // This defines the offset from the anchor point offsetForCapturedLabelField: (overlay, labelField, view) => { return new PointWithUnit(0, 22, MeasureUnit.Dip); } }), []); const styles = StyleSheet.create({ warningContainer: { backgroundColor: 'red', paddingHorizontal: 16, paddingVertical: 8, borderRadius: 8, flexDirection: 'row', alignItems: 'center', }, warningText: { color: 'white', fontWeight: 'bold', fontSize: 14, }, }); useEffect(() => { // Assign the overlay listener to the overlay advancedOverlay.listener = advancedOverlayListener; return () => { // Clean up advancedOverlay.listener = null; }; }, [advancedOverlay, advancedOverlayListener]); ``` ## Validation Flow ```jsx import React, { useMemo } from 'react'; const validationFlowOverlay = useMemo(() => { return new LabelCaptureValidationFlowOverlay(labelCapture, dataCaptureView); }, [labelCapture, dataCaptureView]); // Set the listener to receive validation events useEffect(() => { validationFlowOverlay.listener = validationFlowListener; return () => { validationFlowOverlay.listener = null; }; }, [validationFlowOverlay, validationFlowListener]); ``` ### Define a Listener When the user has verified that all fields are correctly captured and presses the finish button, the Validation Flow triggers a callback with the final results. To receive these results, implement the `LabelCaptureValidationFlowOverlayListener` interface: ```jsx const validationFlowListener = useMemo(() => ({ // This is called by the validation flow overlay when a label has been fully captured and validated onValidationFlowLabelCaptured: (fields) => { let barcodeData = null; let expiryDate = null; fields.forEach(field => { if (field.name === "") { barcodeData = field.barcode?.data; } else if (field.name === "") { expiryDate = field.text; } }); // Handle the captured values } }), []); ``` ```jsx const validationFlowOverlaySettings = useMemo(() => { const settings = new LabelCaptureValidationFlowSettings(); settings.setPlaceholderTextForLabelDefinition("Expiry Date", "MM/DD/YYYY"); return settings; }, []); useEffect(() => { validationFlowOverlay.applySettings(validationFlowOverlaySettings); }, [validationFlowOverlay, validationFlowOverlaySettings]); ``` ```jsx const validationFlowOverlaySettings = useMemo(() => { const settings = new LabelCaptureValidationFlowSettings(); settings.restartButtonText = "Borrar todo"; settings.pauseButtonText = "Pausar"; settings.finishButtonText = "Finalizar"; return settings; }, []); useEffect(() => { validationFlowOverlay.applySettings(validationFlowOverlaySettings); }, [validationFlowOverlay, validationFlowOverlaySettings]); ``` ```jsx import React, { useMemo } from 'react'; const validationFlowOverlaySettings = useMemo(() => { const settings = new LabelCaptureValidationFlowSettings(); settings.standbyHintText = "No label detected, camera paused"; settings.validationHintText = "data fields collected"; // X/Y (X fields out of total Y) is shown in front of this string return settings; }, []); useEffect(() => { validationFlowOverlay.applySettings(validationFlowOverlaySettings); }, [validationFlowOverlay, validationFlowOverlaySettings]); ``` ```jsx const validationFlowOverlaySettings = useMemo(() => { const settings = new LabelCaptureValidationFlowSettings(); settings.validationErrorText = "Incorrect format."; settings.scanningText = "Scan in progress"; settings.adaptiveScanningText = "Processing"; return settings; }, []); useEffect(() => { validationFlowOverlay.applySettings(validationFlowOverlaySettings); }, [validationFlowOverlay, validationFlowOverlaySettings]); ``` ```jsx const customBarcode = CustomBarcode.initWithNameAndSymbologies('Barcode', [ Symbology.EAN13UPCA, Symbology.GS1DatabarExpanded, Symbology.Code128, ]); customBarcode.optional = false; const expiryDateText = new ExpiryDateText('Expiry Date'); expiryDateText.labelDateFormat = new LabelDateFormat(LabelDateComponentFormat.MDY, false); expiryDateText.optional = false; const label = new LabelDefinition('Retail Item'); label.fields = [customBarcode, expiryDateText]; label.adaptiveRecognitionMode = AdaptiveRecognitionMode.Auto; const settings = LabelCaptureSettings.settingsFromLabelDefinitions([label], {}); ``` See [AdaptiveRecognitionMode](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/label-definition.html#property-scandit.datacapture.label.LabelDefinition.AdaptiveRecognitionMode) for available options. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Smart Label Capture to your application. The general steps are: - Create a component to handle the capture process - Initialize the Data Capture Context - Initialize the Label Capture Mode - Implement a listener to handle captured labels - Visualize the scan process - Start the camera - Provide feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/react-native/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import LabelCaptureModuleOverview from '../../../partials/get-started/_smart-label-capture-module-overview.mdx'; ## Create a Component to Handle the Capture Process {#create-component} To start capturing labels, you need to setup and configure the Data Capture Context, Camera, and Label Capture Mode. You can then add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy to display the camera preview on the screen together with UI elements that guide the user through the capture process. You can create a component that initializes all the necessary objects and adds the DataCaptureView to the view hierarchy. ```js import { DataCaptureView } from "scandit-react-native-datacapture-core" export const YourDataCaptureView = (props: Props) => { const { /* ... */ } = props const dataCaptureViewRef = useRef(null) const [dataCaptureContext] = // see Data Capture Context section const camera = // see Camera section const labelCapture = useMemo(() => { // Initialize as described in the Label Capture Mode section }, [dataCaptureContext]) const labelCaptureListener = useMemo(() => ({ // Implement a listener as described in the Implement a Listener section }), [onLabelCaptured]) const labelCaptureOverlay = useMemo(() => { // Initialize the overlay as described in the Visualize the Scan Process section }, [labelCapture]) // Add listener to the LabelCapture mode useEffect(() => { labelCapture.addListener(labelCaptureListener) return () => { labelCapture.removeListener(labelCaptureListener) } }, [labelCapture, labelCaptureListener]) // Add the overlay to the DataCaptureView useEffect(() => { const dataCaptureView = dataCaptureViewRef.current dataCaptureView?.addOverlay(basicOverlay) return () => { dataCaptureView?.removeOverlay(basicOverlay) } }, [basicOverlay, basicOverlayListener]) // Subscribe to the AppState and start/stop the camera // as described in the Start the Camera section return ( ) } ``` ## Initialize the Data Capture Context import DataCaptureContextReactNative from '../../../partials/get-started/_create-data-capture-context-react-native.mdx'; ## Initialize the Label Capture Mode The main entry point for the Label Capture Mode is the [LabelCapture](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/label-capture.html#class-scandit.datacapture.label.LabelCapture) object. It is configured through [LabelCaptureSettings](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/label-capture-settings.html#class-scandit.datacapture.label.LabelCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) that get informed whenever a new frame has been processed. ```js import { useMemo } from 'react'; import { Symbology } from 'scandit-react-native-datacapture-barcode'; import { CustomBarcode, ExpiryDateText, LabelCapture, LabelCaptureSettings, LabelDefinition, } from 'scandit-react-native-datacapture-label'; const labelCapture = useMemo(() => { // Create a barcode field with the expected symbologies. const barcodeField = CustomBarcode.initWithNameAndSymbologies('Barcode', [ Symbology.EAN13UPCA, Symbology.Code128, ]); barcodeField.optional = false; // Create an expiry date text field using the ExpiryDateText preset. const expiryDateField = new ExpiryDateText('Expiry Date'); expiryDateField.optional = true; // Create a label definition with the fields created above. const labelDefinition = new LabelDefinition('Product Label'); labelDefinition.fields = [barcodeField, expiryDateField]; // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([labelDefinition], {}); // Create the label capture mode with the settings. const labelCapture = new LabelCapture(settings); // Add the mode to the data capture context created earlier. dataCaptureContext.addMode(labelCapture); return labelCapture; }, [dataCaptureContext]); ``` ## Implement a Listener to Handle Captured Labels To get informed whenever a new label has been recognized, add a [LabelCaptureListener](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) through [LabelCapture.addListener()](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/label-capture.html#method-scandit.datacapture.label.LabelCapture.AddListener) and implement the listener methods to suit your application’s needs. First conform to the `LabelCaptureListener` interface. Here is an example of how to implement a listener that processes the captured labels based on the label capture settings defined above. Remember to add and remove listeners as described in the [Create Component](#create-component) section. ```js import { useMemo } from 'react'; import { Feedback } from 'scandit-react-native-datacapture-core'; import { LabelCaptureListener } from 'scandit-react-native-datacapture-label'; const labelCaptureListener = useMemo(() => ({ didUpdateSession: (labelCapture, session) => { // The session update callback is called for every processed frame. // Early return if no label has been captured. if (session.capturedLabels.length === 0) { return; } // Process each captured label. session.capturedLabels.forEach((capturedLabel) => { const fields = capturedLabel.fields; // Access the barcode field by its name (as defined in the label definition). // The barcode property contains the scanned barcode data. const barcodeField = fields.find((field) => field.name === 'Barcode'); const barcodeData = barcodeField?.barcode?.data; // Access the expiry date field. Use the text property for OCR-captured text, // or the asDate() method to get a parsed LabelDateResult. const expiryDateField = fields.find((field) => field.name === 'Expiry Date'); const expiryDateText = expiryDateField?.text; const expiryDateResult = expiryDateField?.asDate(); // Handle the captured data as needed, for example: // - Update your app's state // - Navigate to a results screen // - Send data to your backend console.log('Barcode:', barcodeData); console.log('Expiry Date:', expiryDateText); }); // Disable label capture to prevent capturing the same labels multiple times. // Re-enable it when you're ready to scan again. labelCapture.isEnabled = false; // Emit feedback to indicate a successful scan. // See the Feedback section for customization options. Feedback.defaultFeedback.emit(); } }), []); ``` ## Visualize the Scan Process The capture process can be visualized by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy. The view controls the UI elements, such as the viewfinder and overlays, that are shown to visualize captured labels. To visualize the results of Label Capture, you can choose between two overlays, [LabelCaptureBasicOverlay](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/ui/label-capture-basic-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureBasicOverlay) and [LabelCaptureAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/ui/label-capture-advanced-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureAdvancedOverlay). Here is an example of how to add a `LabelCaptureBasicOverlay` to the `DataCaptureView`. Remember to add and remove overlays from the data capture view as described in the [Create Component](#create-component) section. ```js import { useMemo } from 'react'; import { RectangularViewfinder, RectangularViewfinderStyle } from 'scandit-react-native-datacapture-core'; import { LabelCaptureBasicOverlay } from 'scandit-react-native-datacapture-label'; const labelCaptureOverlay = useMemo(() => { // Create the overlay for the label capture mode created earlier. const overlay = new LabelCaptureBasicOverlay(labelCapture); // Optionally, add a viewfinder to guide users through the capture process. const viewfinder = new RectangularViewfinder(RectangularViewfinderStyle.Square); overlay.viewfinder = viewfinder; return overlay; }, [labelCapture]); ``` :::tip See the [Advanced Configurations](advanced.md) section for more information about how to customize the appearance of the overlays and how to use the advanced overlay to display arbitrary Android views such as text views, icons or images. ::: ## Start the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/react-native/core/api/camera.html#class-scandit.datacapture.core.Camera): ```js import { Camera, FrameSourceState } from 'scandit-react-native-datacapture-core'; import { LabelCapture } from 'scandit-react-native-datacapture-label'; // Get the default camera (usually the back-facing camera). const camera = Camera.default; // Set the camera as the frame source for the data capture context. dataCaptureContext.setFrameSource(camera); // Use the recommended camera settings for label capture. const cameraSettings = LabelCapture.createRecommendedCameraSettings(); // Depending on the use case, further camera settings adjustments can be made here. camera?.applySettings(cameraSettings); ``` Once the Camera, DataCaptureContext, DataCaptureView and LabelCapture are initialized, you can switch on the camera to start capturing labels. Typically, this is done once the view becomes active and the user granted permission to use the camera, or once the user presses continue scanning after handling a previous scan. ```js // Turn on the camera to start capturing labels. await camera.switchToDesiredState(FrameSourceState.On); ``` Please refer to the available [sample apps](https://github.com/Scandit/datacapture-react-native-samples) for detailed examples of camera permission handling and view lifecycle management. ## Provide Feedback Label Capture doesn’t emit feedback (sound or vibration) by default when a new label is recognized, as it may be that the label is not complete and you choose to ignore it and wait for the next recognition. However, we provide a `Feedback` class that you can use to emit feedback when a label is recognized and successfully processed. Here, we use the default [Feedback](https://docs.scandit.com/data-capture-sdk/react-native/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration. ```js import { Feedback } from 'scandit-react-native-datacapture-core'; // Get the default feedback configuration. const feedback = Feedback.defaultFeedback; ``` After creating the feedback, you can emit it on successful scans with `feedback.emit()`. See the `LabelCaptureListener` implementation above for more information. :::note Audio feedback is only played if the device is not muted. ::: --- ## About Smart Label Capture import AboutLabelCapture from '../../../partials/intro/_about-smart-label-capture.mdx'; import ValidationFlow from '../../../partials/intro/_about_validation_flow.mdx'; See [here](./advanced.md#validation-flow) for more details. --- ## Label Definitions # Label Definitions A **Label Definition** is a configuration that defines the label, and its relevant fields, that Smart Label Capture should recognize and extract during scans. Smart Label Capture provides a [Label Definition](https://docs.scandit.com/data-capture-sdk/react-native/label-capture/api/label-definition.html#label-definition) API, enabling you to configure and extract structured data from predefined and custom labels. This feature provides a flexible way to recognize and decode fields within a specific label layout such as price tags, VIN labels, or packaging stickers without needing to write custom code for each label type. There are two approaches to using label definitions: - [**Pre-built Labels**](#pre-built-labels) - [**Custom Labels**](#custom-labels) ## Pre-built Labels Smart Label Capture includes ready-made label definitions for common use cases. These pre-built options let you recognize and extract information from standard label types without creating custom configurations: ### Example: Price label Use `LabelDefinition.createPriceCaptureDefinition()` to create a pre-built label definition for price labels, such as those found in retail environments: ![Price Label Example](/img/slc/price-label.png) ```js import { LabelCaptureSettings, LabelDefinition } from 'scandit-react-native-datacapture-label'; // Create a pre-built price capture label definition. const priceLabel = LabelDefinition.createPriceCaptureDefinition('price-label'); // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([priceLabel], {}); ``` ## Custom Labels If Smart Label Capture’s pre-built options don’t fit your needs, define a custom label instead. Custom labels can combine your own fields with any of the available pre-built ones. :::tip The following characters are recognized: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ()-./:,$¶"`. ::: ### Custom Fields There are two types of custom fields you can define: The following properties are available to configure custom fields: | Property | Required | Description | |----------|----------|-------------| | `valueRegexes` | Yes | The regex patterns that identify the target string in the scanned content. | | `anchorRegexes` | No | Used to specify keywords or phrases that help identify the context of the field. This is particularly useful when the label contains multiple fields that could match the same pattern (e.g., when both packaging and expiry dates are present). | | `symbologies` | Yes (barcode fields) | The barcode symbologies to match for barcode fields. This is important for ensuring that the field only captures data from specific barcode types, enhancing accuracy and relevance. | | `optional` | No | Whether the field is optional or mandatory. This is helpful when certain fields may not be present on every scan. | #### Example: Fish Shipping Box This example shows how to create a custom label definition for a fish shipping box, which includes fields for barcode and batch number. ![Fish Shipping Box Example](/img/slc/fish-shipping-box.png) ```js import { Symbology } from 'scandit-react-native-datacapture-barcode'; import { CustomBarcode, CustomText, LabelCaptureSettings, LabelDefinition, } from 'scandit-react-native-datacapture-label'; // Create a custom label definition for a fish shipping box. const shippingLabel = new LabelDefinition('shipping-label'); // Add a barcode field with Code 128 symbology. const barcodeField = CustomBarcode.initWithNameAndSymbology('barcode-field', Symbology.Code128); shippingLabel.addField(barcodeField); // Add a custom text field for the batch number. // Use anchorRegexes to specify keywords that help identify the field context. // Use valueRegexes to specify the expected format of the field data. const batchNumberField = new CustomText('batch-number-field'); batchNumberField.anchorRegexes = ['Batch']; batchNumberField.valueRegexes = ['FZ\\d{5,10}']; batchNumberField.optional = true; shippingLabel.addField(batchNumberField); // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([shippingLabel], {}); ``` ### Pre-built Fields You can also build your label using pre-built fields. These common fields speed up integration because their `valueRegexes`, `anchorRegexes`, and `symbologies` are already predefined. Customization of pre-built fields is done via the `valueRegexes`, `anchorRegexes`, and `isOptional` methods, which allow you to specify the expected format of the field data. :::tip All pre-built fields come with default `valueRegexes` and `anchorRegexes` that are suitable for most use cases. **Setting either property is optional and will override the defaults**. You can set `anchorRegexes` to an empty array to remove the default anchor patterns, allowing you to rely solely on the `valueRegexes` for detection. ::: import FeatureList from '@site/src/components/FeatureList'; #### Barcode Fields #### Price and Weight Fields #### Date and Custom Text Fields #### Example: Hard disk drive label This example demonstrates how to configure a label definition for a hard disk drive (HDD) label, which typically includes common fields like serial number and part number. ![Hard Disk Drive Label Example](/img/slc/hdd-label.png) ```js import { Symbology } from 'scandit-react-native-datacapture-barcode'; import { LabelCaptureSettings, LabelDefinition, PartNumberBarcode, SerialNumberBarcode, } from 'scandit-react-native-datacapture-label'; // Create a custom label definition for an HDD label. const hddLabel = new LabelDefinition('hdd-label'); // Add a serial number barcode field. // Pre-built fields like SerialNumberBarcode have predefined valueRegexes and anchorRegexes. const serialNumberField = SerialNumberBarcode.initWithNameAndSymbology('serial-number', Symbology.Code128); hddLabel.addField(serialNumberField); // Add a part number barcode field. const partNumberField = PartNumberBarcode.initWithNameAndSymbology('part-number', Symbology.Code128); hddLabel.addField(partNumberField); // Create the label capture settings from the label definition. const settings = LabelCaptureSettings.settingsFromLabelDefinitions([hddLabel], {}); ``` --- ## Adding AR Overlays # Adding AR Overlays In the previous section we covered how to vizualize the scan process using the `BarcodeBatchBasicOverlay`. In this section we will cover how to add custom AR overlays to your MatrixScan application. :::tip When using the new React Native architecture on iOS, ensure that your React Native version is `>= 0.79` and that your app delegate implements the `ScanditReactNativeFactoryContainer` protocol available in our React-Native core module. If you have followed the [React Native upgrade guide](https://raw.githubusercontent.com/react-native-community/rn-diff-purge/release/0.79.2/RnDiffApp/ios/RnDiffApp/AppDelegate.swift), you should already have the required property implemented. ::: There are two ways to add custom AR overlays to your application: - Using the [`BarcodeBatchAdvancedOverlay`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) class, our ready-to-use implementation for view-based AR overlays. - Provide your own fully custom implementation by using the [`BarcodeBatchListener.didUpdateSession()`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) function to retrieve the tracking information and implement your own AR overlay. The first option is the easiest and recommended approach for most applications. It covers adding, removing, and animating the overlay’s views whenever needed and is also flexible enough to cover the majority of use cases. ## Using BarcodeBatchAdvancedOverlay As mentioned above, the advanced overlay combined with its [listener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) offers an easy way of adding augmentations to your [DataCaptureView](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). In this guide we will add a view above each barcode showing its content. First of all, create a new instance of [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) and add it to the [DataCaptureView](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). ```js const overlay = new BarcodeBatchAdvancedOverlay(barcodeBatch); view.addOverlay(overlay); ``` At this point, you have two options. - Add a [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) to the overlay. - Use the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) to specify the view, anchor and offset for each barcode. :::note The second way will take priority over the first one, which means that if a view for a barcode has been set using [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), the function [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) won’t be invoked for that specific barcode. ::: Using [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) - You need to implement [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener). This interface’s methods are invoked every time a barcode is newly tracked. - [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) asks for a view to animate on top of the barcode. Returning _null_ will show no view. - [BarcodeBatchAdvancedOverlayListener.anchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode) asks how to anchor the view to the barcode through [Anchor](https://docs.scandit.com/data-capture-sdk/react-native/core/api/anchor.html#enum-scandit.datacapture.core.Anchor 'Anchor enum'). Be aware that it anchors the view’s center to the anchor point. To achieve anchoring the top of the view or the bottom etc. you will have to set an offset as explained in the next point. - [BarcodeBatchAdvancedOverlayListener.offsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode) asks for an offset that is applied on the already anchored view. This offset is expressed through a [PointWithUnit](https://docs.scandit.com/data-capture-sdk/react-native/core/api/common.html#struct-scandit.datacapture.core.PointWithUnit). ```js // The component must be registered: `AppRegistry.registerComponent('ARView', () => ARView)` e.g. in index.js class ARView extends BarcodeBatchAdvancedOverlayView { render() { return {this.props.barcodeData} } } // ... overlay.listener = { viewForTrackedBarcode: (overlay, trackedBarcode) => { // Create and return the view you want to show for this tracked barcode. You can also return null, to have no view for this barcode. return new ARView({barcodeData: trackedBarcode.barcode.data}); }, anchorForTrackedBarcode: (overlay, trackedBarcode) => { // As we want the view to be above the barcode, we anchor the view's center to the top-center of the barcode quadrilateral. // Use the function 'offsetForTrackedBarcode' below to adjust the position of the view by providing an offset. return Anchor.TopCenter; }, offsetForTrackedBarcode: (overlay, trackedBarcode) => { // This is the offset that will be applied to the view. // You can use .Fraction to give a measure relative to the view itself, the SDK will take care of transforming this into pixel size. // We now center horizontally and move up the view to make sure it's centered and above the barcode quadrilateral by half of the view's height. return new PointWithUnit( new NumberWithUnit(0, MeasureUnit.Fraction), new NumberWithUnit(-1, MeasureUnit.Fraction), ); }, }; ``` Using the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) The function [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) gives you access to a [session](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession), which contains all added, updated and removed tracked barcodes. From here you can create the view you want to display, and then call [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), [BarcodeBatchAdvancedOverlay.setAnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode) and [BarcodeBatchAdvancedOverlay.setOffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode) ```js didUpdateSession: (barcodeBatch, session) => { session.addedTrackedBarcodes.map((trackedBarcode) => { let trackedBarcodeView = new ARView({ barcodeData: trackedBarcode.barcode.data, }); this.overlay.setViewForTrackedBarcode(trackedBarcodeView, trackedBarcode); this.overlay.setAnchorForTrackedBarcode(Anchor.TopCenter, trackedBarcode); this.overlay.setOffsetForTrackedBarcode( new PointWithUnit( new NumberWithUnit(0, MeasureUnit.Fraction), new NumberWithUnit(-1, MeasureUnit.Fraction) ), trackedBarcode ); }); }; ``` ## Provide your own custom implementation If you do not want to use the overlay, it is also possible to add augmented reality features based on the tracking identifier and the [quadrilateral](https://docs.scandit.com/data-capture-sdk/react-native/core/api/common.html#struct-scandit.datacapture.core.Quadrilateral) coordinates that every tracked barcode has. Below are some pointers. - Set a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) on the barcode tracking - In the [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) function fetch the [added](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.AddedTrackedBarcodes) and [removed](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.RemovedTrackedBarcodes) tracked barcodes. - Create and show the views for the added barcodes. - Remove the views for the lost barcodes. - Add a method that is called 60fps when [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) is enabled. In this method, for each [TrackedBarcode](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/tracked-barcode.html#class-scandit.datacapture.barcode.batch.TrackedBarcode) on-screen, update the position based on [TrackedBarcode.location](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location). Please note that there is no need to animate the change of location, the change of position will happen frequently enough that the view will look as it is animated. :::note The frame coordinates from [TrackedBarcode.location](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location) need to be mapped to view coordinates, using [DataCaptureView.viewQuadrilateralForFrameQuadrilateral()](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#method-scandit.datacapture.core.ui.DataCaptureView.MapFrameQuadrilateralToView). ::: ```js didUpdateSession: (barcodeBatch, session) => { session.removedTrackedBarcodes.map((lostTrackIdentifier) => { // You now know the identifier of the tracked barcode that has been lost. // Usually here you would remove the views associated. }); session.addedTrackedBarcodes.map((trackedBarcode) => { // Fixed identifier for the tracked barcode. const trackingIdentifier = trackedBarcode.identifier; // Current location of the tracked barcode. const location = trackedBarcode.location; view .viewQuadrilateralForFrameQuadrilateral(location) .then((quadrilateral) => { // You now know the location of the tracked barcode. }); }); }; ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan to your application. The general steps are: - Creating a new Data Capture Context instance - Configuring the MatrixScan mode - Using the built-in camera - Visualizing the scan process - Providing feedback - Disabling barcode tracking ## Create the Data Capture Context import DataCaptureContextReactNative from '../../../partials/get-started/_create-data-capture-context-react-native.mdx'; ## Configure the Barcode Batch Mode The main entry point for the Barcode Batch Mode is the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object. It is configured through [BarcodeBatchSettings](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) and allows to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) that will get informed whenever a new frame has been processed. Most of the times, you will not need to implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener), instead you will add a [BarcodeBatchBasicOverlay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) and implement a [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener). For this tutorial, we will setup Barcode Batch for tracking QR codes. ```js const settings = new BarcodeBatchSettings(); settings.enableSymbology(Symbology.QR, true); ``` Next, create a [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance with the data capture context and the settings initialized in the previous steps: ```js const barcodeBatch = new BarcodeBatch(settings); context.addMode(barcodeBatch); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. :::important In iOS, the user must explicitly grant permission for each app to access cameras. Your app needs to provide static messages to display to the user when the system asks for camera permission. To do that include the [NSCameraUsageDescription](https://developer.apple.com/documentation/bundleresources/information%5Fproperty%5Flist/nscamerausagedescription) key in your app’s Info.plist file. ::: :::important In Android, the user must explicitly grant permission for each app to access cameras. Your app needs to declare the use of the Camera permission in the AndroidManifest.xml file and request it at runtime so the user can grant or deny the permission. To do that follow the guidelines from [Request app permissions](https://developer.android.com/training/permissions/requesting) to request the android.permission.CAMERA permission. ::: When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```js const cameraSettings = BarcodeBatch.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. const camera = Camera.default; if (camera != null) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js context.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/react-native/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/react-native/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```js camera.switchToDesiredState(FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js ``` To visualize the results of Barcode Batch, first you need to add the following [overlay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay): ```js const overlay = new BarcodeBatchBasicOverlay(barcodeBatch, BarcodeBatchBasicOverlayStyle.Frame); view.addOverlay(overlay); ``` Once the overlay has been added, you should implement the [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) interface. The method [BarcodeBatchBasicOverlayListener.brushForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode) is invoked every time a new tracked barcode appears and it can be used to set a [brush](https://docs.scandit.com/data-capture-sdk/react-native/core/api/ui/brush.html#class-scandit.datacapture.core.ui.Brush) that will be used to highlight that specific barcode in the [overlay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay). ```js overlay.listener = { brushForTrackedBarcode: (overlay, trackedBarcode) => { // Return a custom Brush based on the tracked barcode. }, }; ``` If you would like to make the highlights tappable, you need to implement the [BarcodeBatchBasicOverlayListener.didTapTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped) method. ```js overlay.listener = { didTapTrackedBarcode: (overlay, trackedBarcode) => { // A tracked barcode was tapped. }, }; ``` ## Get Barcode Batch Feedback Barcode Batch, unlike Barcode Capture, doesn’t emit feedback (sound or vibration) when a new barcode is recognized. However, you may implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) to provide a similar experience. Below, we use the default [Feedback](https://docs.scandit.com/data-capture-sdk/react-native/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration if you want. ```js const feedback = Feedback.defaultFeedback; ``` Next, use this [feedback](https://docs.scandit.com/data-capture-sdk/react-native/core/api/feedback.html#class-scandit.datacapture.core.Feedback) in a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener): ```js const feedbackListener = { didUpdateSession: (barcodeBatch, session) => { if (session.addedTrackedBarcodes.length > 0) { feedback.emit(); } }, }; ``` [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) is invoked for every processed frame. The [session](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession) parameter contains information about the currently tracked barcodes, in particular, the newly recognized ones. We check if there are any and if so, we emit the feedback. As the last step, register the listener responsible for emitting the feedback with the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance. ```js barcodeBatch.addListener(feedbackListener); ``` ## Disabling Barcode Batch To disable barcode tracking set [BarcodeBatch.isEnabled](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-batch.html#property-scandit.datacapture.barcode.batch.BarcodeBatch.IsEnabled) to _false_. The effect is immediate: no more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off or put it in standby calling [SwitchToDesiredState](https://docs.scandit.com/data-capture-sdk/react-native/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [StandBy](https://docs.scandit.com/data-capture-sdk/react-native/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.Standby). --- ## About MatrixScan Batch # About MatrixScan Batch import AboutMatrixScan from '../../../partials/intro/_about-matrixscan.mdx' --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan AR to your application. Implementing MatrixScan AR involves two primary elements: - Barcode AR: The data capture mode that is used for scan and check functionality. - A Barcode AR View: The pre-built UI elements used to highlight items to be checked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode AR Mode - Setup the Barcode AR View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create the Data Capture Context import DataCaptureContextReactNative from '../../../partials/get-started/_create-data-capture-context-react-native.mdx'; ## Configure the Barcode AR Mode The main entry point for the Barcode AR Mode is the `BarcodeAr` object. You can configure the supported Symbologies through its [`BarcodeArSettings`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-ar-settings.html), and set up the list of items that you want MatrixScan AR to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```js const settings = new BarcodeArSettings(); settings.enableSymbology(Symbology.EAN13UPCA, true); ``` The create the mode with the previously created settings: ```js const mode = new BarcodeAr(settings); ``` ## Setup the `BarcodeArView` MatrixScan AR’s built-in AR user interface includes buttons and overlays that guide the user through the scan and check process. By adding a [`BarcodeArView`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView), the scanning interface is added automatically to your application. The `BarcodeArView` is where you provide the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider) to supply the highlight and annotation information for the barcodes to be checked. If *null*, a default highlight is used and no annotations are provided. The `BarcodeArView` appearance can be customized through [`BarcodeArViewSettings`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-ar-view-settings.html#class-scandit.datacapture.barcode.check.ui.BarcodeArViewSettings), and the corresponding settings for your desired highlights and/or annotations, to match your application’s look and feel. The following settings can be customized: * Audio and haptic feedback * Torch button visibility and its position * Switch camera button visibility and its position * Zoom control visibility and its position * The size, colors, and styles of the highlight and annotation overlays ```js const viewSettings = new BarcodeArViewSettings(); ``` Next, create a `BarcodeArView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodeArView` is automatically added to the provided parent view. ```js const viewRef = useRef(null); { viewRef.current = view; }} >; ``` ## Register the Listener Register a [BarcodeArViewUiListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-ar-view.html#interface-scandit.datacapture.barcode.check.ui.IBarcodeArViewUiListener) to be notified when a highlighted barcode is tapped. ```js barcodeArView.uiListener = { didTapHighlightForBarcode(barcodeAr, barcode, highlight) { // Handle the tapped barcode. }, }; ``` ## Start searching As soon as everything is set up, control the [BarcodeArView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView) to start the search. ```js barcodeArView.start(); ``` --- ## About MatrixScan AR # About MatrixScan AR import AboutMatrixScanCheck from '../../../partials/intro/_about-matrixscan-ar.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Count is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Count to best fit your needs. ## Scanning Against A List There is a function to set a list of expected barcodes if you are scanning against a manifest or item list. If this is used, a progress bar is added to the UI, so you can keep track of the process while scanning. When scanning against a list, the UI will also show red icons to mark scanned barcodes that aren’t present on the list. ```js const barcodeCountCaptureListListener = { didUpdateSession: (barcodeCountCaptureList, session) => { // Handling the session }, }; const targetBarcodes = [TargetBarcode.create('data', 1)]; const barcodeCountCaptureList = BarcodeCountCaptureList.create( barcodeCountCaptureListListener, targetBarcodes ); barcodeCount.setBarcodeCountCaptureList(barcodeCountCaptureList); ``` ## Clustering import Clustering from '../../../partials/count/_clustering.mdx' ## Tote Mapping import Totes from '../../../partials/count/_tote-mapping.mdx' ## Strap Mode It can be difficult to reach the shutter button if the smart device is attached to the user’s wrist by a strap or similar. In this instance, you can enable a floating shutter button that can be positioned by the end user in a more ergonomically suitable position. ```js const barcodeCountViewComponent = ( { if (view) { view.shouldShowFloatingShutterButton = true; } }} /> ); ``` ## Filtering If you have several types of barcodes on your label/package, you may want to scan only one of them. In this case, you can filter the others out. This can be done by symbology, symbol count, or setting a regex. For example, you might want to scan only Code 128 barcodes and no PDF417 ones. ```js const settings = new BarcodeCountSettings(); settings.enableSymbologies(enabledSymbologies); const excludedSymbologies = [Symbology.PDF417]; const filterSettings = settings.filterSettings; filterSettings.excludedSymbologies = excludedSymbologies; ``` Or, you want to exclude all the barcodes starting with 4 numbers: ```js const settings = new BarcodeCountSettings(); const filterSettings = settings.filterSettings; filterSettings.excludedCodesRegex = '^1234.*'; ``` By default the filters applied to the relevant barcodes are transparent, but you can use [`BarcodeFilterHighlightSettings`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-filter-highlight-settings.html#barcode-filter-highlight-settings) to change the color and level of transparency. ![Different Filters in MatrixScan Count](/img/matrixscan-count/filtering_styles.png) ## Clear Screen Button There are situations in which the user may find it helpful to clean up their screen (i.e. clear all the AR overlays) but keep the list of barcodes scanned. If this is the case, you can enable the “Clear screen” button. ```js const barcodeCountViewComponent = ( { if (view) { view.shouldShowClearHighlightsButton = true; } }} /> ); ``` ## Customize Overlay Colors MatrixScan Count comes with recommended and user-tested AR overlays. However, if you wish to customize the overlay colors, once the overlay has been added, you can conform to the [BarcodeCountViewListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view-listener.html#interface-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener) interface. The methods [BarcodeCountViewListener.brushForRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForRecognizedBarcode) and [BarcodeCountViewListener.brushForUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.BrushForUnrecognizedBarcode) are invoked every time a new recognized or unrecognized barcode appears. These can be used to set a brush that will be used to highlight that specific barcode in the overlay. Keep in mind that these methods are relevant only when using the style [BarcodeCountViewStyle.Dot](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view.html#value-scandit.datacapture.barcode.count.ui.BarcodeCountViewStyle.Dot). ```js const viewListener = { brushForRecognizedBarcode(view, trackedBarcode) { // Return a custom brush }, brushForUnrecognizedBarcode(view, trackedBarcode) { // Return a custom brush }, }; const barcodeCountViewComponent = ( { if (view) { view.listener = viewListener; } }} /> ); ``` ## Notifications If you want to be notified when a user taps on an overlay, you need to implement the[BarcodeCountViewListener.didTapRecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnRecognizedBarcodeTapped) and [BarcodeCountViewListener.didTapUnrecognizedBarcode()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view-listener.html#method-scandit.datacapture.barcode.count.ui.IBarcodeCountViewListener.OnUnrecognizedBarcodeTapped) methods. ```js const viewListener = { didTapRecognizedBarcode: (view, trackedBarcode) => { console.log( `Tapped recognized barcode with data ${trackedBarcode.barcode.data}` ); }, didTapUnrecognizedBarcode: (view, trackedBarcode) => { console.log( `Tapped unrecognized barcode with data ${trackedBarcode.barcode.data}` ); }, }; const barcodeCountViewComponent = ( { if (view) { view.listener = viewListener; } }} /> ); ``` ## Disable UI Elements The UI is an integral part of MatrixScan Count and we do not recommend that you use it without it. However, if you wish to disable UI elements you can do it as follows. Disable buttons: ```js const barcodeCountViewComponent = ( { if (view) { view.shouldShowListButton = false; view.shouldShowExitButton = false; view.shouldShowShutterButton = false; } }} /> ); ``` Disable feedback and hints: ```js const barcodeCountViewComponent = ( { if (view) { view.shouldShowUserGuidanceView = false; view.shouldShowHints = false; } }} /> ); ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Count to your application. The general steps are: 1. Initialize the Data Capture Context 2. Configure the Barcode Count Mode 3. Obtain camera instance and set frame source used 4. Register the listener to be informed when scanned phase is over 5. Set capture view and AR overlays 6. Set up the camera so that it switches on when you are in scanning view 7. Store and retrieve scanned barcodes 8. Reset Barcode Count mode 9. List and Exit callbacks ## Initialize the Data Capture Context The first step to add capture capabilities to your application is to initialize the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) with a valid Scandit Data Capture SDK license key. ```js DataCaptureContext.initialize('-- ENTER YOUR SCANDIT LICENSE KEY HERE --'); ``` :::note `DataCaptureContext` should be initialized only once. Use `DataCaptureContext.sharedInstance` to access it afterwards. ::: ## Configure The Barcode Count Mode The main entry point for the Barcode Count Mode is the [BarcodeCount](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) object. It is configured through [BarcodeCountSettings](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count-settings.html#class-scandit.datacapture.barcode.count.BarcodeCountSettings) and allows you to register one or more listeners that are informed whenever a scan phase has finished. For this tutorial, we will set up Barcode Count for tracking EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```js const settings = new BarcodeCountSettings(); settings.enableSymbologies([Symbology.EAN13UPCA]); ``` If you are sure that your environment will only have unique barcodes (i.e. no duplicated values), you can also enable [BarcodeCountSettings.expectsOnlyUniqueBarcodes](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count-settings.html#property-scandit.datacapture.barcode.count.BarcodeCountSettings.ExpectsOnlyUniqueBarcodes). This option improves scanning performance as long as you are sure that no duplicates will be present. Next, create a [BarcodeCount](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) instance with the [Data Capture Context](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) and the settings initialized in the previous step: ```js const barcodeCount = new BarcodeCount(settings); DataCaptureContext.sharedInstance.addMode(barcodeCount); ``` ## Obtain Camera Instance And Set Frame Source Used Our recommended camera settings should be used to achieve the best performance and user experience. The following couple of lines show how to get the recommended settings for MatrixScan Count and create the camera from it: ```js const cameraSettings = BarcodeCount.createRecommendedCameraSettings(); const camera = Camera.default; if (camera != null) { camera.applySettings(cameraSettings); } ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/react-native/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js DataCaptureContext.sharedInstance.setFrameSource(camera); ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [BarcodeCountListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count-listener.html#interface-scandit.datacapture.barcode.count.IBarcodeCountListener) interface and register the listener. [BarcodeCountListener.didScan()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan) is called when the scan phase has finished and results can be retrieved from [BarcodeCountSession](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession). ## Set Capture View And AR Overlays MatrixScan Count’s built-in AR user interface includes buttons and overlays that guide the user through the capturing process. By adding a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) to your view hierarchy: ```js const barcodeCountViewComponent = ( ); ``` ## Set Up The Camera So That It Switches On When You Are In Scanning View The camera is not automatically turned on when you are in a scanning view. You need to set up the camera so that it switches on when needed and it switches off when not needed anymore. Similarly [BarcodeCount](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count.html#class-scandit.datacapture.barcode.count.BarcodeCount) should also be enabled and disabled. For instance, you should switch off the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is not visible anymore (including when the app goes in the background), similarly you want to switch on the camera when the [BarcodeCountView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-count-view.html#class-scandit.datacapture.barcode.count.ui.BarcodeCountView) is visible (including when the app goes to the foreground). One way to achieve this is the following: ```js componentDidMount() { handleAppStateChangeSubscription = AppState.addEventListener('change', handleAppStateChange); } componentWillUnmount() { handleAppStateChangeSubscription.remove(); } handleAppStateChange = async (nextAppState) => { if (nextAppState.match(/inactive|background/)) { camera.switchToDesiredState(FrameSourceState.Off); } else { camera.switchToDesiredState(FrameSourceState.On); } } ``` ## Store And Retrieve Scanned Barcodes The values captured as part of the scanning process are part of the [session](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count-session.html#class-scandit.datacapture.barcode.count.BarcodeCountSession), and the session is not accessible outside [BarcodeCountListener.didScan()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count-listener.html#method-scandit.datacapture.barcode.count.IBarcodeCountListener.OnScan). Therefore, we recommend that you store the values to present a list, for example when the user taps the list icon. To do this, make a copy of [BarcodeCountSession.recognizedBarcodes](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count-session.html#property-scandit.datacapture.barcode.count.BarcodeCountSession.RecognizedBarcodes): ```js const listener = { didScan: (barcodeCapture, session, getFrameData) => { const allRecognizedBarcodes = session.recognizedBarcodes; // Handle barcodes }, }; barcodeCount.addListener(listener); ``` ## Reset Barcode Count Mode When the scanning process is over, you need to reset the mode to make it ready for the next process. This clears the list of barcodes scanned and all the AR overlays. To reset Barcode Count’s scanning process, you need to call the [BarcodeCount.reset()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-count.html#method-scandit.datacapture.barcode.count.BarcodeCount.Reset) method. ```js barcodeCount.reset(); ``` ## List And Exit Callbacks The UI includes two icons (buttons) named “List” and “Exit”. The SDK provides the callbacks so you can add the desired action when those icons are tapped by the user. ```js const viewUiListener = { didTapListButton: (view) => { // Show the current progress but the order is not completed }, didTapExitButton: (view) => { // The order is completed }, }; const barcodeCountViewComponent = ( { if (view) { view.uiListener = viewUiListener; } }} /> ); ``` --- ## About MatrixScan Count # About MatrixScan Count import AboutMatrixScanCount from '../../../partials/intro/_about-matrixscan-count.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Find is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Find to best fit your needs. ## Set up a listener on the BarcodeFind mode You may want more fine-grained knowledge over the different events happening during the life of the BarcodeFind mode, such as when the search starts, pauses and stops. To do this, you can directly register a [BarcodeFindListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-find-listener.html#interface-scandit.datacapture.barcode.find.IBarcodeFindListener) on the mode itself. Be aware that these listeners will be called from a background thread. ```js mode.addListener({ didStartSearch() { // The mode was started }, didPauseSearch(foundItems) { // The mode was paused }, didStopSearch(foundItems) { // The mode was stopped after the finish button was clicked }, }); ``` ## UI configuration The [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) will by default show a set of UI elements, which can be optionally hidden: - A play/pause button - A finish button - A searched items carousel - Guidance hints There is also a progress bar but this is hidden by default. Each of these elements can be shown or hidden at will. ```js barcodeFindView.shouldShowCarousel = false; barcodeFindView.shouldShowProgressBar = true; // … ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Find to your application. Implementing MatrixScan Find involves two primary elements: - Barcode Find: The data capture mode that is used for search and find functionality. - A Barcode Find View: The pre-built UI elements used to highlight found items. The general steps are: 1. Create a new Data Capture Context instance. 2. Configure the Barcode Find Mode. 3. Setup the BarcodeFindView. 4. Register a listener to be notified with found items 5. Start searching ## Create the Data Capture Context import DataCaptureContextReactNative from '../../../partials/get-started/_create-data-capture-context-react-native.mdx'; ## Configure the Barcode Find Mode The main entry point for the Barcode Find Mode is the [BarcodeFind](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind) object. You can configure the supported Symbologies through its [BarcodeFindSettings](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-find-settings.html#class-scandit.datacapture.barcode.find.BarcodeFindSettings), and set up the list of items that you want MatrixScan Find to highlight (e.g. a list of products). For this tutorial, we will set up Barcode Find for tracking EAN13 codes. Change this to the correct symbologies for your use case (e.g. Code 128, Code 39…). First create the settings: ```js const settings = new BarcodeFindSettings(); settings.enableSymbology(Symbology.EAN13UPCA, true); ``` Then you have to create the list of items that will be actively searched for. In this tutorial, let’s look up two items based on their EAN13 codes. We will attach to the first item some optional information that can be used by the BarcodeFindView to display extra information. ```js const items = [ new BarcodeFindItem(new BarcodeFindItemSearchOptions("9783598215438"), new BarcodeFindItemContent("Mini Screwdriver Set", "(6-Piece)", null)), new BarcodeFindItem(new BarcodeFindItemSearchOptions("9783598215414"), null) // Item information is optional, used for display only ] ``` Create the mode with the previously created settings and set the items: ```js const mode = new BarcodeFind(settings); mode.setItemList(items); ``` ## Setup the BarcodeFindView MatrixScan Find’s built-in AR user interface includes buttons and overlays that guide the user through the searching process. By adding a [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView), the scanning interface (camera preview and searching UI elements) will be added automatically to your application. The BarcodeFindView appearance can be customized through [BarcodeFindViewSettings](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-find-view-settings.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindViewSettings): - Colors of dots in augmented reality overlay - Enable sound and haptic alerts ```js const viewSettings = new BarcodeFindViewSettings(); ``` Construct a new BarcodeFindView. The BarcodeFindView is automatically added to the provided parent view. ```js const viewRef = useRef(null); { viewRef.current = view; // Handle the view as needed, for example view.startSearching(); }} >; ``` ## Register a listener to be notified with found items The BarcodeFindView displays next to its shutter button a handy “finish” button. Register a [BarcodeFindViewUiListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-find-view.html#interface-scandit.datacapture.barcode.find.ui.IBarcodeFindViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```js barcodeFindView.barcodeFindViewUiListener = { didTapFinishButton(foundItems) { // This method is called when the user presses the // finish button. It returns the list of all items that were found during // the session. }, }; ``` ## Start searching As soon as everything is set up, control the [BarcodeFindView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView) to start the search. ```js barcodeFindView.startSearching(); ``` This is the equivalent of pressing the “Play” button programmatically. It will start the search process, turn on the camera and hide the item carousel. --- ## About MatrixScan Find # About MatrixScan Find import AboutFind from '../../../partials/intro/_about-matrixscan-find.mdx' --- ## Advanced Configurations # Advanced Configurations MatrixScan Pick is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Pick to best fit your needs. ## BarcodePick Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodePick` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodePickViewListener`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-pick-view.html#interface-scandit.datacapture.barcode.pick.IBarcodePickViewListener) on the view itself, keeping in mind that these listeners are called from a background thread. ```js const viewListener = { didStartScanning(view) { // The view started scanning }, didFreezeScanning(view) { // The view was frozen }, didPauseScanning(view) { // The view was paused }, didStopScanning(view) { // The view stopped scanning }, }; barcodePickView.addListener(viewListener); ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Pick to your application. Implementing MatrixScan Pick involves two primary elements: - Barcode Pick: The data capture mode that is used for scan and pick functionality. - A Barcode Pick View: The pre-built UI elements used to highlight items to be picked. The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Pick Mode - Setup the Barcode Pick View - Registering the Listener to notify about found items ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create the Data Capture Context import DataCaptureContextReactNative from '../../../partials/get-started/_create-data-capture-context-react-native.mdx'; ## Configure the Barcode Pick Mode The main entry point for the Barcode Pick Mode is the `BarcodePick` object. You can configure the supported Symbologies through its [`BarcodePickSettings`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-pick-settings.html), and set up the list of items that you want MatrixScan Pick to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```js const settings = new BarcodePickSettings(); settings.enableSymbology(Symbology.EAN13UPCA, true); ``` Then you have to create the list of items that will be picked and quantity to be picked for each item. ```js const items = [ new BarcodePickProduct(new BarcodePickProductIdentifier("9783598215438"), new BarcodePickProductQuantityToPick(3)), new BarcodePickProduct(new BarcodePickProductIdentifier("9783598215414"), new BarcodePickProductQuantityToPick(3)), ]; ``` Create the mode with the previously created settings: ```js const mode = new BarcodePick(settings); ``` ## Setup the `BarcodePickView` MatrixScan Pick’s built-in AR user interface includes buttons and overlays that guide the user through the scan and pick process. By adding a [`BarcodePickView`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-pick-view.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickView), the scanning interface is added automatically to your application. The `BarcodePickView` appearance can be customized through [`BarcodePickViewSettings`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-pick-view-settings.html#class-scandit.datacapture.barcode.pick.ui.BarcodePickViewSettings) to match your application’s look and feel. The following settings can be customized: * Colors of dots in augmented reality overlay * Enable sound and haptic alerts * Guidelines text * Showing hints * Finish button * Pause button * Zoom button * Loading Dialog ```js const viewSettings = new BarcodePickViewSettings(); // ... ``` Construct a new `BarcodePickView`. The `BarcodePickView` is automatically added to the provided parent view. ```js const viewRef = useRef(null); { viewRef.current = view; }} /> ``` ## Register the Listener The `BarcodePickView` displays a **Finish** button next to its shutter button. Register a [BarcodePickViewUiListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/barcode-pick-view.html#interface-scandit.datacapture.barcode.pick.ui.IBarcodePickViewUiListener) to be notified what items have been found once the finish button is pressed. In this tutorial, we will then navigate back to the previous screen to finish the find session. ```js barcodePickView.uiListener = { didTapFinishButton(foundItems) { // This method is called when the user presses the finish button. // It returns the list of all items that were found during the session. }, }; ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `BarcodePickView.start()`. ```js barcodePickView.start(); ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Pick # About MatrixScan Pick MatrixScan Pick is a pre-built UI that uses augmented reality overlays to highlight specific items that need to be picked. Whereas MatrixScan AR is fully customizable, MatrixScan Pick is a pre-built solution that allows you to add a scan and pick experience with augmented reality to an existing native app, with just a few lines of code. MatrixScan Pick is implemented through functionality provided by [`BarcodePick`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/barcode-pick.html). ## UI Overview * MatrixScan Pick is inspired by the familiar paradigm of a camera, including a shutter button that the user operates in order start and pause the scanning view. The Finish button is used at any time to exit the workflow. * It highlights items with obvious and colorful visual dots on screen. * When paused, MatrixScan Pick freezes the display at the last view, even if the device is moved. The Play button transitions back to the live view. * Textual guidance is displayed from the beginning of the session and as the workflow progresses, informing of the user of changes in item status (i.e. Detected, Ignored, To-Pick, or Picked). * Status icons can be defined to provide further information to users for a given barcode. In the live view, the icons are displayed but not tappable. In the frozen view, the status icons can be tapped and expanded to provide additional textual information. * The Quick Start Guide takes you through the process to install the full UI. However, you can then customize it by choosing to remove any elements on the screen except for the AR overlays. This allows you to create custom UIs suitable for your own workflows. ## Supported Symbologies MatrixScan Find supports all [symbologies](../barcode-symbologies.mdx) **except** DotCode, MaxiCode and postal codes (KIX, RM4SCC). If you are not familiar with the symbologies that are relevant for your use case, you can use capture presets that are tailored for different verticals (e.g. retail, logistics, etc.). --- ## Get Started # Get Started The parser parses data strings, e.g. as found in barcodes, into a set of key-value mappings. In this guide, you will know briefly how to use a parser and what types of parser are currently supported by Scandit. These data formats are supported: [Health Industry Bar Code (HIBC)](https://docs.scandit.com/data-capture-sdk/react-native/parser/hibc.html), [GS1 Application Identifier (https://docs.scandit.com/data-capture-sdk/react-native/parser/AI) system](https://docs.scandit.com/data-capture-sdk/react-native/parser/gs1ai.html) and [Swiss QR Codes](https://docs.scandit.com/data-capture-sdk/react-native/parser/swissqr.html), [VIN Vehicle Identification Number](https://docs.scandit.com/data-capture-sdk/react-native/parser/vin.html), [IATA Bar Coded Boarding Pass (BCBP)](https://docs.scandit.com/data-capture-sdk/react-native/parser/iata-bcbp.html), [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/react-native/parser/epc.html). More data formats will be added in future releases. Please contact us if the data format you are using is not yet supported, or you want to use the parser on a currently unsupported platform. ## Format-Specific Documentation - [Supported Data Formats](https://docs.scandit.com/data-capture-sdk/react-native/parser/formats.html) - [HIBC](https://docs.scandit.com/data-capture-sdk/react-native/parser/hibc.html) - [GS1 AI](https://docs.scandit.com/data-capture-sdk/react-native/parser/gs1ai.html) - [GS1 Digital Link](https://docs.scandit.com/data-capture-sdk/react-native/parser/gs1-digital-link.html) - [Swiss QR](https://docs.scandit.com/data-capture-sdk/react-native/parser/swissqr.html) - [VIN](https://docs.scandit.com/data-capture-sdk/react-native/parser/vin.html) - [IATA BCBP](https://docs.scandit.com/data-capture-sdk/react-native/parser/iata-bcbp.html) - [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/react-native/parser/epc.html) ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: First of all, include the ScanditParser library and its dependencies to your project, if any. ## Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### New Features #### Barcode * Added the SelectionMode API to replace the SparkScan target-mode APIs and `ScanIntention.smartSelection`: Set `selectionMode` (off/on/auto) in the `BarcodeCaptureSettings` and `SparkScanSettings` to control whether an aimed-at barcode is scanned automatically or requires explicit selection. #### Id * Added Irish Garda Age Card as `RegionSpecificSubtype.IrelandAgeCard`. * Added double-sided support for the Oman residence card. * Added single-sided support for extraction of issue date and birth date from the 2025 NYC Municipal ID. #### Smart Label Capture * Extended VIN label capture to also scan Code 128 barcodes (in addition to QR, Code 39, and Data Matrix) via `createVinLabelDefinition()`. * Extended LabelCapture to accept label definitions where both "barcode" and "text" field types use the "semantics" feature simultaneously; previously this was restricted to only one field type at a time. ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Smart Label Capture * Improved Receipt Scanning efficiency by optimizing receipt image processing before extraction. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. * Updated `SymbologyDescription.forIdentifier` to return `null` for unrecognized identifiers (e.g. `"EAN-8"` instead of `"ean8"`); previously such input was silently mapped to `Codabar`. ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in item-based scanning. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Id * Fixed an issue where cropped document images were rotated when Frame Image was also enabled. * Added support for Business Travel Permit to Hong Kong/Macau SAR (AKCHN prefix). * Corrected the orientation of cropped Visa document images that were being rotated incorrectly when scanned using a single-frame image source. * Fixed parser handling of non-standard Surrey BC AAMVA barcodes that were incorrectly returning "Invalid Format". #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed React Native projects using the New Architecture (NewArch) on iOS that required a custom `post_install` snippet in the Podfile to build; the Swift-to-Objective-C bridging header search paths are now set correctly in the SDK podspecs. * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a crash when the `DataCaptureContext` singleton was initialized more than once. ### Deprecations #### Barcode * The SparkScan target-mode APIs and `ScanIntention.smartSelection` are deprecated in favour of selectionMode. ## 8.4.1 **Released**: June 23, 2026 ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in SparkScan when using the item-based API. #### Id * Fixed an issue where cropped document images were rotated when they are recovered using the getFrame API. * Resolved a duplicate Objective-C class registration that could trigger spurious casting failures or crashes when an app links both ScanditCaptureCore and ScanditIdCapture. #### Core * Fixed an issue where the camera preview (`DataCaptureView` and other view components) could remain blank in React Native apps while scanning still worked. Native view creation no longer depends on React Native's interaction queue, which a long-running JS animation could block indefinitely. ## 8.4.0 **Released**: May 18, 2026 ### New Features #### Barcode * Added `dotRadius` property to `BarcodeBatchBasicOverlay` to allow customizing the size of dots when using the Dot overlay style. * Added custom view support for barcode pick highlighting in JavaScript frameworks. * Added support for PDF417 in the Barcode Generator. #### Id * Added support for reading the vehicle table on the back of New Zealand driving licences, with the latest expiry date returned; supported vehicle classes are 1–6, including L=learner and R=restricted variants. * Added support for new versions of USA, California – Driver's License; USA, North Carolina – Driver's License; USA, Texas – Driver's License; and USA, Oklahoma – Driver's License. #### Core * Redesigned `ZoomSwitchControl` to support multiple configurable zoom levels; the control now displays as a compact button that expands to show all available zoom levels, automatically filtered to those supported by the device hardware. * Added a new `PinchToZoom` gesture. ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. #### Core * Updated mbedtls from version 3.6.5 to 3.6.6. ### Bug Fixes #### Barcode * Fixed an issue in `BarcodeCount` where the floating shutter button was not visible after setting `shouldShowFloatingShutterButton` to `true`. * Fixed an issue preventing `BarcodeFind` from finding binary barcodes. * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. * Fixed an issue where `BarcodeCountView` would display incorrectly after rotating the device when a sibling view was present in the same parent view. * Fixed an unnecessary second scan callback that occurs after freezing barcode recognition. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed an issue where the Smart Scan Selection aimer would become too small when scan-area margins restricted the visible scan area; the aimer is now sized relative to the view, keeping a consistent on-screen size regardless of margins. * Fixed an issue in BarcodeCount where the strap mode setting would not be saved in all cases. #### Id * Fixed an issue where the US Permanent Residence Card was not processed through the VizMrz flow. * Fixed an issue where AAMVA verification was being performed even when no AAMVA document types were enabled in the accepted documents. #### Smart Label Capture * Fixed a memory leak in LabelCapture * Fixed an issue where the validation flow viewfinder was not displayed. * Fixed a race condition in the validation flow. * Fixed a bug where the label capture validation flow overlay sometimes did not reflect label capture settings when reused. * Fixed a bug that caused error messages in `DataCaptureView` to be rendered partially out-of-view. * Fixed a rare race condition in Label Capture. * Added `.asDate()` support to `ExpiryDate` and `PackingDate` label fields when the text is provided as manual input or as an Adaptive-Recognition-Engine response. * Fixed a bug where the receipt scanning overlay and validation flow overlay could not be used on the same LabelCapture mode instance. #### Core * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. * Fixed a rare crash when opening the camera. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed custom sound not working in Barcode Find on Android. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. * Fixed React Native projects using the New Architecture (NewArch) on iOS that required a custom post_install snippet in the Podfile to build; the Swift-to-Objective-C bridging header search paths are now set correctly in the SDK podspecs. * Fixed a rare crash when starting camera capture while under memory pressure. ## 8.3.1 **Released**: April 14, 2026 ### Bug Fixes #### Smart Label Capture * Fixed the validation flow to accept dates in more formats when manually entered * Fixed a race condition in the validation flow ## 8.3.0 **Released**: March 26, 2026 ### New Features #### Barcode * Added support for composite codes in SparkScan #### Id * Added support for OCR scanning of the 2026 version of Victoria mobile driver licenses * Added IdCaptureSettings.anonymizeDefaultFields setting that controls whether the SDK applies default anonymization rules for specific document types and regions #### Smart Label Capture * Fixed a rare race condition #### Core * Added support for the New Architecture of React Native * Added support for React Native Turbo Module Event Emitters with event handling performance improvements * Added support for React Native Fabric Components * Added Camera-related APIs for macro mode, torch, accessibility hints, as well as ImageBuffer and Timestamp for FrameData. * Added shouldShowZoomNotification and setProperty to DataCaptureView * Added new SparkScan APIs related to feedback, scanning mode change, and periscope mode. * Added BarcodeFilterSettings public constructor and exposed excludedSymbolCounts property for JavaScript frameworks * Added BarcodeCount-related APIs for BarcodeCountNotInListActionSettings, BarcodeCountToolbarSettings, BarcodeCountMappingFlowSettings, status mode and accessibility properties on BarcodeCountView, BarcodeCountStatusProvider with status items and callbacks, cluster support, capture list completion listener, and session update listener * Added moduleCountX and moduleCountY to Barcode API * Added an Expo-based React Native sample for Barcode Capture Simple Sample ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Improved speed of MatrixScan Count scanning phase for mid- and high-end devices ### Bug Fixes #### Barcode * Fixed an issue in BarcodeCount where the floating shutter button was not visible after setting shouldShowFloatingShutterButton to true. * Fixed a bug that was causing BarcodeFind to render barcodes filtered out by the Transformer as if they were valid targets. * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session. #### Id * Fixed BarcodeDictionary anonymization setting for iOS and Web * Fixed support for UAE Esaad card * Sanitized name fields on ACT driver license to split FullName and populate first and last name properties * Added support for scanning MRZ from the back of Argentinian DN when using `FullDocumentScanner` * Fixed misplaced MRZ anonymization on FullFrame images. #### Smart Label Capture * Fixed an issue in the `LabelCaptureValidationFlowOverlay` when using it with Jetpack Compose that caused focus loss when opening the keyboard * Added `LabelCaptureValidationFlowOverlay.ShouldHandleKeyboardInsetsInternally` for cases when customers don't want to follow official Android edge-to-edge and inset guidelines #### Core * Fixed crashes on Android 8.x when native libraries fail to load * Fixed app freeze/deadlock when navigating to DataCaptureView with React Native New Architecture (Fabric) * Fixed default camera settings for LabelCapture and Other Capture Modes. * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.2.1 **Released**: March 5, 2026 ### Bug Fixes #### Id * Sanitized name fields on ACT DL. Splits FullName to populate first and last name properties #### Smart Label Capture * Fixed LabelCaptureValidationFlowOverlay possible issue with Jetpack Compose that caused focus loss when opening the keyboard * Added LabelCaptureValidationFlowOverlay::ShouldHandleKeyboardInsetsInternally in case customers don't want to follow official Android guidelines for edge-to-edge and insets * Fixed a rare race condition #### Core * Fixed app freeze/deadlock when navigating to DataCaptureView with React Native New Architecture (Fabric) * Fixed a syntax error in ScanditReactPackageBase.kt which prevented compilation with some React Native versions ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Barcode * Added new getFeedbackForScannedItem method to SparkScanFeedbackDelegate * Added BarcodeArResponsiveAnnotation API * Added some missing BarcodePick APIs to React-Native, Capacitor and Cordova #### Smart Label Capture * The Validation Flow, our ready‑to‑use workflow in Smart Label Capture for capturing and validating label data with minimal code, now features a completely redesigned user interface. The update improves ergonomics through a simplified API and highly requested customization options, making Smart Label Capture more intuitive and significantly reducing integration and customization effort across a wider range of use cases * Smart Label Capture now supports Receipt Scanning Capture. The feature is available in beta (contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out). * Added `getFrameData` to `didUpdateSession` of the LabelCaptureListener #### Core * Added Electronic Product Code (EPC) data format * Added Flow Types to the React-Native plugins ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes * Barcode Generator: Improved DataMatrix encoding efficiency, which depending on input data may result in smaller generated codes ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed BarcodeCount Scan Preview issues including: fixed an issue where preview barcodes were used to populate the scanning list, the correct feedback is played when a barcode not in list is scanned, fixed an issue where scanning was not possible after the app was put in background, and corrected highlight orientation in landscape * Fixed an issue where MatrixScan AR circle highlights stopped pulsing when the app was restored from the background * Added cameraStateOnStop property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed an issue where the successful hint in BarcodeFind is not displayed * Fixed the missing found item icon in the MatrixScan Find carousel #### Id * Fixed an issue affecting MRZ scanning performance when using the user facing camera in portrait mode on Android * Fixed a memory issue leading to a persistent black screen during ID Capture startup * Treated Puerto Rico driver licenses as AAMVA to enforce barcode capture with FullScanner * Fixed a bug that would cause Canada Northwest Territories driver license scans to be incomplete #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Improved loading of platform defaults in React-Native * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed an issue where some LabelCapture fields were being returned incorrectly on TS frameworks * Fixed a crash in the DataCaptureView overlay management that could occur during rapid view updates. * Fixed compatibility of the React Native plugins with apps using React Native versions below 0.78 ### Deprecations #### Smart Label Capture * Deprecated some LabelCaptureValidationFlowSetting APIs: requiredFieldErrorText, missingFieldsHintText, manualInputButtonText, as those don't make sense anymore with the redesign of Validation Flow in 8.2 ## 8.1.5 **Released**: June 10, 2026 ### Bug Fixes #### Barcode * Fixed BarcodeAR not displaying an overlay for every scanned barcode when duplicate barcode values are present. * Fixed a memory leak in item-based scanning. #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed a rare crash when starting camera capture while under memory pressure. * Fixed a rare crash when opening the camera. * Fixed a rare native crash (SIGABRT in BitTube::recvObjects) that could occur on Android during camera preview rendering. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. #### Core * Fixed a rare issue that was causing a crash when the app moved to the background. * Fixed a rare SIGABRT crash on camera initialization on devices whose HAL returns null from `Camera.Parameters.getSupportedFocusModes()` (e.g. industrial barcode scanners like the Newland NLS-MT93). * Fixed crashes caused by RuntimeExceptions thrown by OEM camera code that are not part of the standard Android Camera API contract; these exceptions are now caught and logged instead of crashing. ## 8.1.3 **Released**: March 25, 2026 ### Bug Fixes #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed a potential deadlock on iOS when reading the camera torch state from the main thread while the camera was starting up. ## 8.1.2 **Released**: March 9, 2026 ### Bug Fixes #### Barcode * Fixed a stability issue that could cause a crash when tracked barcodes were removed or expired during a scanning session #### Smart Label Capture * Fixed a rare race condition ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Id * Fixed a memory issue leading to a persistent black screen during ID Capture startup #### Core * Fixed a crash in the DataCaptureView overlay management that could occur during rapid view updates * Fixed an issue where the camera preview appeared rotated 90 degrees in landscape orientation * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Smart Scan Selection is now available in Barcode Capture. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * [SparkScan](/sdks/react-native/sparkscan/intro.md) is not limited to only barcodes anymore, but can also scan items - in other words any combinations of barcodes and text present on a target to be scanned. The feature is available in beta at the moment, please contact [Scandit Support](mailto:support@scandit.com) if you are interested in trying it out. * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. * Added, in `BarcodeAr`, new classes to create custom highlights (via `BarcodeArCustomHighlight`) and custom annotations (via `BarcodeArCustomAnnotation`). #### Id * Added NationalityISO property that maps results from Nationality field to country ISO code * Added RejectionDiagnosticJSON property to CapturedId to report debug info during Timeout rejections * Added support for new California DL, new South Carolina DL, Arizona Medical Marijuana Card, Kuwait Civil card, and new Texas DL * Our SDK can now scan the following documents both in single-side and double-side mode: - All Mexican DLs - Mexican Voter Cards ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the [“strict" symbology extension](../symbology-properties#symbology-extension-descriptions) #### Smart Label Capture * Incremental improvements in accuracy across all use-cases for the OCR model powering Smart Label Capture. ### Behavioral Changes #### Barcode * Enabling the [“ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 (“Missing Resource”) #### Smart Label Capture * Validation Flow: Manually input values for barcodes will go through a stricter validation. Some values may no longer be accepted if they do not match the symbology specs for the symbology’s definition ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Fixed a bug in the default color of BarcodeCapture highlights * Fixed an issue where popover annotations with HIGHLIGHT_TAP_AND_BARCODE_SCAN trigger could not be opened again * Fixed an issue in BarcodeSequence where camera would not be ON in portrait * Fixed an issue where SparkScan mini preview would sometimes stay in regular when entering target mode * Fixed the app becoming unresponsive after being in the background for extended periods * Added the `cameraStateOnStop` property to BarcodeFindView to optimize camera transitions when switching between modes * Fixed an issue where the successful notification in BarcodeFind was not displayed #### Id * Fixed an issue where front expiry date anonymization rectangle is erroneously drawn on front and back * Fixed a bug that prevented VizResult anonymization of the following fields: additionalAddressInformation, bloodType, employer, fathersName, issuingAuthority, maritalStatus, mothersName, placeOfBirth, profession, race, residentialStatus * Fixed a bug concerning return complete instead of cropped images on the back of EU driving licenses #### Smart Label Capture * Fixed an issue where LabelCapture fields would return default data in some frameworks #### Core * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only * Fixed an issue where barcode scanning would permanently stop after the app returned from background, particularly when camera permission dialogs were shown during initialization * Fixed a bug where getIsTorchAvailable() would return null on Android ## 8.0.1 **Released**: January 14, 2026 ### Bug Fixes #### Barcode * Fixed an issue where the successful hint in BarcodeFind was not displayed * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance #### Core * Fixed an issue where the camera would not restart when opened from another app * Fixed an issue where the interface and video feed could have different visual orientations * Fixed a bug that could in rare cases produce a black screen when starting the camera * Fixed a small memory leak that affected fresh install runs only ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. #### Core * Upgraded all sample applications to React Native 0.81.4 and enabled the new architecture. #### Barcode * All sample applications have been updated to more closely align with React Native best practices. * `BarcodeBatchBasicOverlay` and `BarcodeBatchBasicOverlayListener` now allow for nullable brushes. * MatrixScan AR now allows for the use of custom highlights and annotations. * Updated the Gradle version for all sample applications to 8.14.3. #### Smart Label Capture * We’re introducing an enhancement that makes Smart Label Capture more robust and scalable by complementing its on-device model with a larger, more capable model. When the on-device model can’t capture certain labels, the SDK automatically escalates to this enhancement to handle complex or unforeseen cases with high accuracy and reliability. This capability is currently available in `beta`. If you’re interested in trying it, please contact Scandit Support. For configuration details, see `labelDefinition.adaptiveRecognitionEngine`. #### ID * Added `ElementsToRetain` to `MobileDocumentScanner`: The set of data elements that the application intends to retain from scanned mobile documents. This information is used to set the `IntentToRetain` flag in ISO 18013-5 mdoc requests, which is required for legal compliance with data protection standards. An empty set indicates no elements will be retained, and `IntentToRetain` will be set to `false` for all fields. * ID Capture now supports full-frame anonymization. * The result of `decodeMobileDriverLicenseViz`, which is currently returned as part of the `VizResult` within `CapturedId`, will now be provided through a new field named `mobileDocumentOcr`. * Added `CapturedId::isCitizenPassport`, which indicates whether the passport was issued to a citizen of the issuing country. Returns `false` for travel documents such as refugee, stateless, or alien passports, and for any passports issued by organizations rather than states. * The following Chinese travel permits now extract VIZ + MIZ data during double-sided scanning flows: * CT - Taiwan Residents Mainland Travel Permit * W - Mainland Residents Exit-Entry Permit to and from Hong Kong and Macao * CD - Mainland Residents Entry-Exit Permit to and from Taiwan ### Behavioral Changes #### Barcode * Symbology `RM4SCC` has been renamed to `ROYAL_MAIL_4STATE`. * Changed the default highlight brush in SparkScan and Barcode Capture. #### Label * The `LabelFieldDefinition` API has been updated with the following changes: * Renamed property: `pattern` → `valueRegex`, `patterns` → `valueRegexes` * Renamed property: `dataTypePattern` → `anchorRegex`, `dataTypePatterns` → `anchorRegexes` * Receipt Scanning API has been updated with the following changes: * `ReceiptScanningResult`: * Removed properties: `storeNumber`, `storeStreet`, `storeZip`, `storeState`, `storePhone`, `paymentMethod`, and `paymentCurrency`. * Added property: `storeAddress` - Full address of the store (Street Number, Street, City, State, NPA). * Renamed property: `paymentSubtotal` → `paymentPreTaxTotal` - Total balance before taxes are applied. * `ReceiptScanningLineItem`: * Removed property: `category`. * Renamed properties: `price` → `unitPrice` (Price for a single unit of the item), `total` → `totalPrice` (Total price for a specific product, quantity × unitPrice). #### ID * The configuration for the following documents has been changed as detailed below: * Australian mobile driver licenses (mDL) are now treated as normal documents, with no separate mode. * US Green Cards are now treated as residence permits. * Removed the deprecated API `DateResult::toDate`. Use `DateResult::toLocalDate` or `DateResult::toUtcDate` instead. * `fullName` now an optional field on all `IdCapture` result types and `capturedMrz` now an optional field on `MrzResult`. ### Bug Fixes #### Core * Fixed handling of `ImageFrameSource` turn on and off calls. #### ID * Fixed a bug that could get the scanner stuck when scanning a US passport card. ### Deprecations #### Core * `VideoResolution::Auto` is now deprecated. Please use the capture mode's `recommendedCameraSettings` for the best results. #### Barcode * All previously deprecated APIs have been removed in this release. ## 7.6.7 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/react-native/release-notes) --- ## Advanced Configurations # Advanced Configurations SparkScan is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are some cases where you might want to customize the behavior of SparkScan. This guide will show you how to add additional capabilities and further customize SparkScan to best fit your needs. ## Advanced Capabilities ### Hardware Button Control Allowing the end user to control the scanner with hardware buttons can be useful if your users typically wear gloves. It can also improve ergonomics in some workflows. SparkScan offers a built-in API to let you do this via [scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HardwareTriggerEnabled). ### Trigger Error State You may want to introduce logic in your app to show an error message when scanning specific barcodes (e.g. barcodes already added to the list, barcodes from the wrong lot etc.). SparkScan offers a built-in error state you can easily set to trigger an error feedback prompt to the user. You can customize: * The text message. - The timeout of the error message: the scanner will be paused for the specified amount of time, but the user can quickly restart the scanning process by tapping the trigger button. :::tip A high timeout (>10s) typically requires the users to interact with the UI to start scanning again. This is a good choice when you want to interrupt the scanning workflow (e.g. because a wrong barcode is scanned and some actions need to be performed). A small timeout (\ { if (isValidBarcode(barcode)) { return new SparkScanBarcodeSuccessFeedback(); } else { return new SparkScanBarcodeErrorFeedback( 'This code should not have been scanned', 60 * 1000, Color.fromHex('#FF0000'), new Brush(Color.fromHex('#FF0000'), Color.fromHex('#FF0000'), 1), ); } }, }; ``` You can have different error states triggered by different logic conditions. For example you can trigger an error state when a wrong barcode is scanned, and another one when a duplicate barcode is scanned. These errors can show different colors and have different timeouts. This error state for a code that should not have been scanned. This error state for a code that has been scanned more than once. ### Reject Barcodes To prevent scanning unwanted barcodes (like those already listed or from incorrect lots), use SparkScan’s built-in error state. Setting the [SDCSparkScanBarcodeErrorFeedback.resumeCapturingDelay](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/spark-scan-barcode-feedback.html#property-scandit.datacapture.barcode.spark.feedback.Error.ResumeCapturingDelay) parameter to `0` allows the user to continue scanning immediately without pausing on rejected codes. ## UI Customization :::tip Please refer to [SparkScanView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) for the full list of parameters. ::: import Customization from '../../../partials/advanced/_sparkscan-customization.mdx'; ## React Navigation When using the `SparkScanView` component with React Navigation and `headerShown: true`, you may encounter an issue where the Buttons within your `SparkScanView` don't respond to touch events. This is a known issue with React Navigation's header implementation. The navigation header can interfere with touch event handling for components rendered within certain custom views like `SparkScanView`. While the buttons appear to be functioning visually, their `onPress` events do not trigger when the screen includes a header. Try the following if you encounter this issue: **Use TouchableOpacity instead of Button** ```jsx handleButtonPress()}> Scan ``` or ```jsx handleButtonPress()}> Scan ``` **Ensure you're importing TouchableOpacity from 'react-native'** Some users have found that using the `TouchableOpacity` component from `react-native-gesture-handler` causes issues, while the one from `react-native` works correctly. ## Workflow Options This section explains all the available options to configure SparkScan to best fit your case, in case you found something that didn't work well in the default configuration (that remains our recommended option). Developers can set a combination of scanning mode, scanning behavior and camera preview behavior - defining the initial state of the scanner. This can be done by setting the default scanning mode (SparkScanViewSettings.defaultScanningMode). This combination allows for flexible configurations to suit different scanning needs. ### Scanning Mode The scanning mode determines the programmatic presence of an aimer in the preview to help with precision scanning. | Mode | Description | | ----------- | --------------------------------------------------- | | **Default** | Generally recommended. This mode will display a small camera preview to aid with aiming. The preview size and zoom level can be adjusted as needed. User can aim easily at the intended barcode. | | **Target** | This mode will always add an aimer to the camera preview to precisely select the barcode to scan. This is recommended only when selecting among many close barcodes is the common task. | :::tip Even in the *Default* mode, SparkScan will automatically show an aimer when multiple barcodes are present in the view and no clear intention from the user to scan a single one is recorded ([`SparkScanSettings.ScanIntention`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/spark-scan-settings.html#property-scandit.datacapture.barcode.spark.SparkScanSettings.ScanIntention)). Enabling the *Target* mode will simply force this "precision selection" state to be on at all time. ::: ### Scanning Behavior The scanning behavior determines how barcodes are scanned - one at a time or continuously. | Behavior | Description | | ------------------- | ---------------------------------------------------------- | | **Single scan** | Scan one barcode at a time. The user needs to trigger the scanner every time to scan a barcode. This allows for a more controlled scanning and lower battery consumption. | | **Continuous scan** | Scan barcodes consecutively. The user needs to trigger the scanner once and barcodes will be scanned without any further interaction before each scan. This allows for a smoother experience when multiple barcodes need to be scanned consecutively. | :::tip Users can enable continuous scanning by holding down the trigger button. This gesture can be disabled ([`SparkScanViewSettings.holdToScanEnabled`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HoldToScanEnabled)). ::: ### Preview Behavior The preview behavior determines how the camera preview behaves when the scanner is not actively scanning. | Behavior | Description | | -------------- | -------------------------- | | **Default** | Preview fades away when the scanner is off. This lets the user check important information displayed by the app and reduces battery consumption. | | **Persistent** | Preview remains visible, but darkened, even when the scanner is off. This is useful for scenarios where you want to select a barcode (among many) or need to look through the preview at all times (to ensure the right scan) - especially if used in conjunction with the target mode. | ### Configuring the default scanning mode Combine a scanning mode, scanning behavior, and preview behavior and assign it to [`SparkScanViewSettings.defaultScanningMode`](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/spark-scan-view-settings.html). For example, to start in continuous scanning with the preview always visible: ```ts const viewSettings = new SparkScanViewSettings(); viewSettings.defaultScanningMode = new SparkScanScanningModeDefault( SparkScanScanningBehavior.Continuous, // or .Single SparkScanPreviewBehavior.Persistent, // or .Default ); ``` Pass both arguments — the single-argument constructor is deprecated. Use `SparkScanScanningModeTarget` instead of `SparkScanScanningModeDefault` to force the aimer (target mode). --- ## Get Started # Get Started In this guide you will learn step-by-step how to add SparkScan to your application. The general steps are: 1. Create a new Data Capture Context instance. 2. Configure the Spark Scan Mode. 3. Create the SparkScanView with the desired settings and bind it to the application’s lifecycle. 4. Register the listener to be informed when new barcodes are scanned and update your data whenever this event occurs. ## Prerequisites - The latest stable version of [React Native CLI and other related tools and dependencies](https://reactnative.dev/docs/environment-setup). - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). - If you have not already done so, see [this guide](../add-sdk.md) for information on how to add the Scandit Data Capture SDK to your project. :::warning Android devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ## Create the Data Capture Context import DataCaptureContextReactNative from '../../../partials/get-started/_create-data-capture-context-react-native.mdx'; ## Configure the SparkScan Mode The SparkScan Mode is configured through [SparkScanSettings](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/spark-scan-settings.html) and allows you to register one or more listeners that are informed whenever a new barcode is scanned. For this tutorial, we will set up SparkScan for scanning EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```js const settings = new SparkScanSettings(); settings.enableSymbologies([Symbology.EAN13UPCA]); ``` Next, create a SparkScan instance with the settings initialized in the previous step: ```js const sparkScan = new SparkScan(settings); ``` ## Setup the Spark Scan View The SparkScan built-in user interface includes the camera preview and scanning UI elements. These guide the user through the scanning process. The [SparkScanView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) appearance can be customized through SparkScanViewSettings. ```js const viewSettings = new SparkScanViewSettings(); // setup the desired appearance settings by updating the fields in the object above ``` See the [SparkScan Workflow Options](./advanced.md#workflow-options) section for more information. By adding a [SparkScanView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView), the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a SparkScanView to your view hierarchy: Construct a new SparkScan view. The SparkScan view is automatically added to the provided parentView: ```js const sparkScanComponent = ( ); ``` Additionally, make sure to call [SparkScanView.stopScanning()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.StopScanning) in your app state handling logic. You have to call this for the correct functioning of the [SparkScanView](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView). ```js componentWillUnmount() { sparkScanComponent.stopScanning(); } handleAppStateChange = async (nextAppState) => { if (nextAppState.match(/inactive|background/)) { sparkScanComponent.stopScanning(); } } ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [SparkScanListener](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface and register the listener to the SparkScan mode. ```js // Register a listener object to monitor the spark scan session. const listener = { didScan: (sparkScan, session, getFrameData) => { // Gather the recognized barcode const barcode = session.newlyRecognizedBarcode[0]; // Handle the barcode }, }; sparkScan.addListener(listener); ``` [SparkScanListener.didScan()](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/spark-scan-listener.html#method-scandit.datacapture.barcode.spark.ISparkScanListener.OnBarcodeScanned) is called when a new barcode has been scanned. This result can be retrieved from the first object in the provided barcodes list: [SparkScanSession.newlyRecognizedBarcode](https://docs.scandit.com/data-capture-sdk/react-native/barcode-capture/api/spark-scan-session.html#property-scandit.datacapture.barcode.spark.SparkScanSession.NewlyRecognizedBarcode). Please note that this list only contains one barcode entry. ## Scan Some Barcodes Now that you’re up and running, go find some barcodes to scan. Don’t feel like getting up from your desk? Here’s a [handy pdf of barcodes](https://github.com/Scandit/.github/blob/main/images/PrintTheseBarcodes.pdf) you can print out. --- ## About SparkScan # About SparkScan SparkScan is our pre-built smartphone scanning interface designed for high-performance barcode scanning. It fits on top of any smartphone application, providing an intuitive user interface for simple, fast and ergonomic scanning in scan-intensive workflows such as inventory management in retail, or goods receiving in logistics. SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs. ## UI Overview The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience. Two main elements compose the UI: ![SparkScan UI](/img/sparkscan/features_web.png) - **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc). - **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space. There are additional UI elements available for displaying additional scanning modes, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section. ## Workflow Description When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use. To start scanning, the user can simply tap on it. When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app). In the default configuration: - Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away. - Tapping on the trigger button or the mini preview will restart immediately the scanner. Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state. If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released. List building use case using SparkScan. The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field. But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more. ## Supported Symbologies SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx). ## AI-Powered Features SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide. --- ## Installation # Installation This page describes how to integrate the Scandit Data Capture SDK into your web project. You can consume the Scandit Data Capture SDK Web packages in two ways: - as an external resource from a CDN in HTML - as package dependency via npm. ## Prerequisites Before you begin, make sure you have the following prerequisites in place: - The latest stable version of Node.js and npm (required only if including and building the SDK as part of an app, instead of just including it as an external resource from a CDN in HTML). - Valid Scandit Data Capture SDK license, sign up for a [free trial](https://www.scandit.com/trial/) if you don't already have a license key For detailed information about system requirements, see [System Requirements](/sdks/web/system-requirements/#web-sdk). :::warning Devices running the Scandit Data Capture SDK need to have a GPU and run a browser capable of making it available (requires [WebGL - current support?](https://caniuse.com/#feat=webgl) and [OffscreenCanvas - current support?](https://caniuse.com/#feat=offscreencanvas)) or the performance will drastically decrease. ::: ## Package Information Scandit Data Capture SDKs [npm packages](https://www.npmjs.com/search?q=@scandit) are distributed under `@scandit/` scope. You need to add the `@scandit/web-datacapture-core` package, which contains the shared functionality used by the other data capture packages. If you're using `barcodecapture`-related functionalities, make sure to also add the: - `@scandit/web-datacapture-barcode` package, and/or - `@scandit/web-datacapture-parser` package `@scandit/web-datacapture-parser` package needs `@scandit/web-datacapture-barcode` as dependency. See the [Parser documentation](/sdks/web/parser/get-started.md) to learn more. If you want to scan personal identification documents, such as identity cards, passports or visas you need to add `@scandit/web-datacapture-id`. See the [ID Capture documentation](/sdks/web/id-capture/get-started.md) to learn more. :::tip You can safely remove _barcode_ or _id_ dependencies if you are not going to use their features. ::: ## Install via package manager To add the packages via your preferred package manager, run the following command from your project's root folder: ```sh npm install --save @scandit/web-datacapture-core @scandit/web-datacapture-barcode ``` ```sh yarn add @scandit/web-datacapture-core @scandit/web-datacapture-barcode ``` ```sh pnpm add @scandit/web-datacapture-core @scandit/web-datacapture-barcode ``` ```sh bun add @scandit/web-datacapture-core @scandit/web-datacapture-barcode ``` ```sh deno add npm:@scandit/web-datacapture-core npm:@scandit/web-datacapture-barcode ``` :::note You can also specify a version @``. ::: Then import the package in your JavaScript/TypeScript code by using: ```js // Importing only the necessary items is recommended to allow bundler to optimize the code through tree-shaking import { DataCaptureContext, Camera, } from "@scandit/web-datacapture-core"; import { BarcodeCapture, barcodeCaptureLoader, } from "@scandit/web-datacapture-barcode"; // Insert your code here ``` ## Install via CDN :::warning Important considerations when using CDNs CDNs offer a convenient way to get started but they introduce dependencies into your application. Your app's functionality becomes directly tied to the CDN's availability and performance. Any CDN outages or slowdowns will immediately affect your users' experience. For production environments, we recommend: 1. **Self-hosting** the SDK files on your own infrastructure, where you are strongly encouraged to: - Configure optimal cache headers and compression settings - Set correct MIME types for .wasm, .js and .model files - Control Content-Length headers for accurate loading progress - Minimize request redirections and network latency - Implement your own fallback mechanisms 2. If self-hosting isn't feasible, use a **paid enterprise CDN service** that provides: - Guaranteed uptime and performance metrics - Enterprise-grade support ::: You can use the [jsDelivr](https://jsdelivr.com/) or [UNPKG](https://unpkg.com/) CDN to specify a certain version (or range) and include and import from our library as follows. :::note In alternative to jsdeliver, unpkg can be used: - [UNPKG Core](https://unpkg.com/@scandit/web-datacapture-core@8.x) - [UNPKG Barcode](https://unpkg.com/@scandit/web-datacapture-barcode@8.x) ::: ### Complete CDN Example ```html Scandit CDN Simple sample { "imports": { "@scandit/web-datacapture-core": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-core@8/build/js/index.js", "@scandit/web-datacapture-barcode": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-barcode@8/build/js/index.js", "@scandit/web-datacapture-parser": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-parser@8/build/js/index.js", "@scandit/web-datacapture-barcode/": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-barcode@8/", "@scandit/web-datacapture-core/": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-core@8/", "@scandit/web-datacapture-parser/": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-parser@8/" } } html, body { margin: 0; padding: 0; height: 100%; } #app { height: 100%; } import { DataCaptureView, Camera, DataCaptureContext, FrameSourceState, } from "@scandit/web-datacapture-core"; import { barcodeCaptureLoader, BarcodeCaptureSettings, BarcodeCapture, Symbology, SymbologyDescription, } from "@scandit/web-datacapture-barcode"; let view = new DataCaptureView(); view.connectToElement(document.getElementById("app")); view.showProgressBar(); const context = await DataCaptureContext.forLicenseKey("-- ENTER LICENSE KEY HERE --", { libraryLocation: "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-barcode@8/sdc-lib/", moduleLoaders: [barcodeCaptureLoader()], }); view.hideProgressBar(); const camera = Camera.pickBestGuess(); await view.setContext(context); // Depending on the use case further camera settings adjustments can be made here. const cameraSettings = BarcodeCapture.recommendedCameraSettings; await camera.applySettings(cameraSettings); await context.setFrameSource(camera); await context.frameSource.switchToDesiredState(FrameSourceState.On); const settings = new BarcodeCaptureSettings(); settings.enableSymbologies([Symbology.Code128, Symbology.QR]); let barcodeCapture = await BarcodeCapture.forContext(context, settings); barcodeCapture.addListener({ didScan: async (barcodeCaptureMode, session) => { const barcode = session.newlyRecognizedBarcode; if (!barcode) { return; } const symbology = new SymbologyDescription(barcode.symbology); alert(`Scanned: ${barcode.data ?? ""}\n(${symbology.readableName})`); }, }); await barcodeCapture.setEnabled(true); ``` ## Configure the Library The library needs to be configured and initialized before it can be used, this is done via the DataCaptureContext [`forLicenseKey`](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) function. Note that the configuration expects a valid license key as first argument. :::tip We recommend calling [`forLicenseKey`](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) as soon as possible in your application so that the files can be downloaded and the [`DataCaptureContext`](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) initialized before the capture process starts. ::: The `LibraryLocation` configuration option must be provided and point to the location of the Scandit Data Capture `sdc-lib` location (external WebAssembly files): `scandit-datacapture-sdk\*.js` and `scandit-datacapture-sdk\*.wasm`. WebAssembly requires these separate files which are loaded by our main library at runtime. They can be found inside the `sdc-lib` folder you either added and installed via npm or access via a CDN. If you installed the library through npm, **these files should be copied and served correctly in a path that will be accessible by the SDK during initialization**. The configuration option that you provide should then point to the folder containing these files, either as a path of your website or an absolute URL (like the CDN one). **By default the library will look at the root of your website**. :::caution Version Matching Required The npm package version and the `sdc-lib` files must be from the exact same SDK version. For example, if you have `@scandit/web-datacapture-barcode@8.0.0` in your `package.json`, you must serve the `sdc-lib` folder from `node_modules/@scandit/web-datacapture-barcode@8/sdc-lib/`. **Mismatched versions will cause runtime errors and unexpected behavior.** ::: In case a common CDN is used (jsDelivr or UNPKG) the library will automatically, internally set up the correct URLs pointing to the files needed for the matching library version. **It is highly recommended to handle the serving of these files yourself on your website/server, ensuring optimal compression, correct WASM files MIME type, no request redirections, and correct caching headers usage.** This will aid in faster loading. ## Hosting the `sdc-lib` files We recommend serving the `sdc-lib` folder yourself. :::caution Important: Full Folder Copy and Version Matching You must copy the **entire `sdc-lib` folder recursively** from the installed Scandit package to your server. This includes all subdirectories and files. The `sdc-lib` folder must come from a package version that exactly matches your npm package version. For example, if you have `@scandit/web-datacapture-barcode@8.0.0`, you must copy the `sdc-lib` from `node_modules/@scandit/web-datacapture-barcode@8/sdc-lib/`. Additionally, you should copy `sdc-lib` from all installed Scandit packages (`@scandit/web-datacapture-core`, `@scandit/web-datacapture-barcode`, `@scandit/web-datacapture-id`, `@scandit/web-datacapture-parser`, etc.) to the same location. ::: Once copied, be sure to serve the files correctly by setting up the correct MIME type for the `.wasm`, `.model`, and `.js` files. Some common examples are provided below: ```csharp app.UseStaticFiles(new StaticFileOptions() { ServeUnknownFileTypes = true, DefaultContentType = "application/octet-stream" }); ``` Or ```csharp var provider = new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider(); provider.Mappings[".model"] = "application/octet-stream"; provider.Mappings[".js"] = "application/javascript"; provider.Mappings[".wasm"] = "application/wasm"; ``` Add these MIME types to your `.htaccess` file or Apache configuration: ```apache AddType application/wasm .wasm AddType application/octet-stream .model AddType application/javascript .js ``` Add these MIME types to your Nginx configuration file: ```nginx types { application/wasm wasm; application/octet-stream model; application/javascript js; } ``` For Express.js, you can configure the MIME types like this: ```javascript const express = require("express"); const app = express(); express.static.mime.define({ "application/wasm": ["wasm"] }); express.static.mime.define({ "application/octet-stream": ["model"] }); express.static.mime.define({ "application/javascript": ["js"] }); app.use(express.static("self-hosted-sdc-lib")); // Serve static files from 'public' directory ``` For Flask, you can set the MIME types when serving the files: ```python from flask import Flask, send_file app = Flask(__name__) @app.route('/self-hosted-sdc-lib/') def serve_file(filename): mimetype = None if filename.endswith('.wasm'): mimetype = 'application/wasm' elif filename.endswith('.model'): mimetype = 'application/octet-stream' elif filename.endswith('.js'): mimetype = 'application/javascript' return send_file( f'/self-hosted-sdc-lib/{filename}', mimetype=mimetype ) ``` ## Show loading status with default UI It could take a while the very first time to download the .wasm files. To show some visual feedback to the user about the loading status you have two options: - use the default UI provided with the SDK - subscribe to the loading status and update your own custom UI. Let's see how to do it with the default UI first: ```ts import { DataCaptureView, DataCaptureContext, } from "@scandit/web-datacapture-core"; import { idCaptureLoader } from "@scandit/web-datacapture-id"; const view = new DataCaptureView(); view.connectToElement(document.getElementById("data-capture-view")); view.showProgressBar(); view.setProgressBarMessage("Loading ..."); const context = await DataCaptureContext.forLicenseKey("-- ENTER LICENSE KEY HERE --", { libraryLocation: "/self-hosted-sdc-lib/", moduleLoaders: [idCaptureLoader({ enableVIZDocuments: true })], }); view.hideProgressBar(); await view.setContext(context); ``` ## Show loading status with custom UI You can also subscribe for the [loading status](https://docs.scandit.com/data-capture-sdk/web/core/api/web/loading-status.html) of the library by simply attaching a listener like this: ```ts import type { ProgressInfo } from "@scandit/web-datacapture-core"; import { loadingStatus, DataCaptureContext } from "@scandit/web-datacapture-core"; import { barcodeCaptureLoader } from "@scandit/web-datacapture-barcode"; loadingStatus.subscribe((info: ProgressInfo) => { // updateUI(info.percentage, info.loadedBytes) }); const context = await DataCaptureContext.forLicenseKey("SCANDIT_LICENSE_KEY", { libraryLocation: "/self-hosted-sdc-lib/", moduleLoaders: [barcodeCaptureLoader()], }); ``` :::note The library files should be served with the proper header `Content-Length`. `Content-Encoding` should also be set if any compression is used. In case of missing information, the progress bar tries to show an estimated value, but can also not report progress at all for a while. ::: ## Additional Information ### Server Side Rendering and Server Side Generation If you use a web framework that also renders on the server (SSR or SSG) it's recommended to execute the library only on the client turning off the rendering on the server. For more information: - [GatsbyJS - Using client side only packages](https://www.gatsbyjs.com/docs/using-client-side-only-packages/). - [NextJS - Lazy Loading with no ssr](https://nextjs.org/docs/pages/building-your-application/optimizing/lazy-loading#with-no-ssr). ### Performance Optimization For information on how to improve runtime performance, see [Improve Runtime Performance by Enabling Browser Multithreading](/sdks/web/matrixscan/get-started/#improve-runtime-performance-by-enabling-browser-multithreading). ### Camera Permissions When using the Scandit Data Capture SDK you will likely want to set the camera as the frame source for various capture modes. The camera permissions are handled by the browser, and can only be granted if a [secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts) is used and have been accepted by the user explicitly. If you are embedding the Web SDK inside a native WebView (Android or iOS), the host application must request and delegate camera permissions to the web content. See the [WebView Integration](./webview.md) guide for step-by-step instructions. ### Progressive Web App (PWA) You can configure the scanner to work offline making the web app progressive (Progressive Web App). There are some settings to consider. If you use Workbox, a tool that uses workbox under the hood like [Vite PWA](https://vite-pwa-org.netlify.app/) plugin, you must also set these options: ```js workbox: { globPatterns: ["**/*.{css,html,ico,png,svg,woff2}", "**/*.{wasm,js}"], maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, // up to 10mb because of wasm files // Don't ignore version parameters - let each version have its own cache entry runtimeCaching: [ { urlPattern: /^.*\.wasm(\?.*)?$/, handler: "NetworkFirst", options: { cacheName: "wasm-version-cache", expiration: { maxEntries: 2, // Keep only 2 versions to manage storage maxAgeSeconds: 60 * 60 * 24 * 30, // 30 days }, // This ensures the version parameter is part of the cache key matchOptions: { ignoreSearch: false, // Don't ignore search parameters (like ?v=) as part of the cache key }, networkTimeoutSeconds: 5, // Fallback to cache if network is slow }, }, { // Cache all other assets with NetworkFirst for example urlPattern: /^.*\.(js|css|html|png|jpg|jpeg|svg|ico|woff2)(\?.*)?$/, handler: "NetworkFirst", options: { cacheName: "app-assets-cache", expiration: { maxEntries: 100, maxAgeSeconds: 60 * 60 * 24 * 7, // 7 days }, networkTimeoutSeconds: 3, // Fallback to cache if network is slow }, }, ], cleanupOutdatedCaches: true, // Skip waiting to activate new service worker immediately skipWaiting: true, clientsClaim: true, }, ``` With these settings in place and the service worker correctly configured, you will be able to have a full offline scanning experience. :::warning On iOS there's an [issue](https://bugs.webkit.org/show_bug.cgi?id=252465) while accessing the video stream inside a progressive web app. The issue is flaky and gets reopened periodically. Check the [webkit tracker](https://bugs.webkit.org/buglist.cgi?quicksearch=pwa%20getUserMedia) if you experience similar issues. ::: ### Electron You can configure the Scandit SDK to work in an Electron app. The register method must be called inside the `main.ts` file passing down some dependencies and the `publicKey`. The `publicKey` will be used to decrypt the encrypted license key file that must be placed into the [`DataCaptureContext.forLicenseKeyInElectronPath`](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.ForLicenseKeyInElectronPath) option: ```ts // electron main.ts import { register, unregister } from '@scandit/web-datacapture-core/build/electron/main'; import { app, BrowserWindow, ipcMain } from 'electron'; import fs from 'node:fs/promises'; import crypto from 'node:crypto'; import path from 'node:path'; const mainWindow = new BrowserWindow({ ..., }); register({ fs, ipcMain, app, path, crypto }, publicKey); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() unregister() } }); ``` ```ts // preload.ts import { ipcRenderer } from "electron"; import { preloadBindings } from "@scandit/web-datacapture-core/build/electron/preload"; preloadBindings(ipcRenderer); ``` ```ts // renderer.ts import { DataCaptureContext } from "@scandit/web-datacapture-core"; import { barcodeCaptureLoader } from "@scandit/web-datacapture-barcode"; const context = await DataCaptureContext.forLicenseKeyInElectronPath("./out/renderer/data/sdc-license.data", { // In Electron context the license will be decrypted internally. // The path of the encrypted file is path.join(app.getAppPath(), licenseDataPath) libraryLocation: new URL("self-hosted-sdc-lib", document.baseURI).toString(), moduleLoaders: [barcodeCaptureLoader()], }); ``` You can encrypt your license key with this small Node.js script. Then you should copy the `sdc-license.data` file in the `licenseDataPath` in order to be correctly read at runtime during initialization. You can also check the related [sample](https://github.com/Scandit/datacapture-web-samples/tree/master/ElectronBarcodeCaptureSimpleSample). ```js const crypto = require("node:crypto"); const fs = require("node:fs/promises"); (async function createLicenseAndPublicKey() { const licenseText = process.env.SDC_LICENSE_KEY; if (licenseText == null || licenseText === "") { throw new Error("could not encrypt empty or null string"); } const key = crypto.randomBytes(32); const iv = crypto.randomBytes(16); const keyAndIV = `${key.toString("base64")}:${iv.toString("base64")}`; const cipher = crypto.createCipheriv("aes-256-cbc", key, iv); let licenseEncryptedText = cipher.update(licenseText, "utf8", "hex"); licenseEncryptedText += cipher.final("hex"); await fs.writeFile("sdc-license.data", Buffer.from(licenseEncryptedText), "utf8"); // Save the key to a file await fs.writeFile("sdc-public-key", keyAndIV, "utf8"); })(); ``` :::warning It is recommended to NOT store the public key locally. We also recommend you enable [source code protection](https://electron-vite.org/guide/source-code-protection) with [bytenode](https://github.com/bytenode/bytenode). ::: import OSSLicense from '../../partials/\_third-party-licenses-js.mdx'; --- ## Agent Skills import SkillsPage from '@site/src/components/SkillsPage'; # Agent Skills for Web --- ## AI-Powered Barcode Scanning # AI-Powered Barcode Scanning import AIPoweredBarcodeScanning from '../../partials/_ai-powered-barcode-scanning.mdx'; --- ## Configure Barcode Symbologies # Configure Barcode Symbologies import Intro from '../../../partials/configure-symbologies/_intro.mdx' ## Enable the Symbologies You Want to Read import EnableSymbologies from '../../../partials/configure-symbologies/_enable-symbologies.mdx' The following lines of code show you how to enable scanning Code 128 codes for barcode capture: ```js import { BarcodeCaptureSettings, Symbology } from '@scandit/web-datacapture-barcode'; const settings = new BarcodeCaptureSettings(); settings.enableSymbology(Symbology.Code128, true); ``` import CapturePresents from '../../../partials/configure-symbologies/_capture-presents.mdx' ## Configure the Active Symbol Count Barcode symbologies (such as Code 128, Code 39, Code 93, or Interleaved Two of Five) can store variable-length data. For example, Code 39 can be used to store a string from 1 to 40-50 symbols. There is no fixed upper limit, though there are practical limitations to the code’s length for it to still be conveniently readable by barcode scanners. For performance reasons, the Scandit Data Capture SDK limits the [possible symbol range](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.ActiveSymbolCounts) for variable-length symbologies. If you want to read codes that are shorter/longer than the specified default range or you want to tailor your app to only read codes of a certain length, you need to change the active symbol count of the symbology to accommodate the data length you want to use in your application. The below lines of code show how to change the active symbol count for Code 128 to read codes with 6, 7 and 8 symbols. ```js import { BarcodeCaptureSettings, Symbology } from '@scandit/web-datacapture-barcode'; const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code128); symbologySettings.activeSymbolCounts = [6, 7, 8]; ``` import CalculateSymbolCount from '../../../partials/configure-symbologies/_calculate-symbol-count.mdx' ## Read Bright-on-Dark Barcodes Most barcodes are printed using dark ink on a bright background. Some symbologies allow the colors to be inverted and can also be printed using bright ink on a dark background. This is not possible for all symbologies as it could lead to false reads when the symbology is not designed for this use case. See [symbology properties](../symbology-properties.mdx) to learn which symbologies allow color inversion. When you enable a symbology as described above, only dark-on-bright codes are enabled. If you also want to read bright-on-dark codes, color-inverted reading for that symbology must be enabled ( `SymbologySettings.isColorInvertedEnabled`). The following code shows how to enable color-inverted reading for Code 128: ```js import { BarcodeCaptureSettings, Symbology } from '@scandit/web-datacapture-barcode'; const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code128); symbologySettings.isColorInvertedEnabled = true; ``` ## Enforce Checksums Some symbologies have a mandatory checksum that will always be enforced while others only have optional [checksums](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/checksum.html#enum-scandit.datacapture.barcode.Checksum). Enforcing an optional checksum will reduce false positives as an additional check can be performed. When enabling a checksum you have to make sure that the data of your codes contains the calculated checksum otherwise the codes get discarded as the checksum doesn’t match. All available checksums per symbology can be found in [symbology properties](../symbology-properties.mdx). You can enforce a specific checksum by setting it through [SymbologySettings.checksums](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/symbology-settings.html#property-scandit.datacapture.barcode.SymbologySettings.Checksums): ```js import { BarcodeCaptureSettings, Symbology, Checksum } from '@scandit/web-datacapture-barcode'; const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code39); symbologySettings.checksums = [Checksum.Mod43]; ``` ## Enable Symbology-Specific Extensions Some symbologies allow further configuration. These configuration options are available as symbology extensions that can be enabled/disabled for each symbology individually. Some extensions affect how the data in the code is formatted, others allow for more relaxed recognition modes that are disabled by default to eliminate false reads. All available extensions per symbology and a description of what they do can be found in the documentation on [symbology properties](../symbology-properties.mdx). To enable/disable a symbology extension, use [SymbologySettings.setExtensionEnabled()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/symbology-settings.html#method-scandit.datacapture.barcode.SymbologySettings.SetExtensionEnabled). The following code shows how to enable the full ASCII extension for Code 39. ```js import { BarcodeCaptureSettings, Symbology } from '@scandit/web-datacapture-barcode'; const settings = new BarcodeCaptureSettings(); const symbologySettings = settings.settingsForSymbology(Symbology.Code39); symbologySettings.setExtensionEnabled('full_ascii', true); ``` This extension allows Code 39 to encode all 128 ASCII characters instead of only the 43 characters defined in the standard. The extension is disabled by default as it can lead to false reads when enabled. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Barcode Capture to your application. The general steps are: - Include the ScanditBarcodeCapture library and its dependencies to your project, if any. See the [Installation guide](../add-sdk.md) for details. - Create a new [data capture context](#create-the-data-capture-context) instance, initialized with your license key. - Create a [barcode capture settings](#configure-the-barcode-scanning-behavior) and enable the [barcode symbologies](../barcode-symbologies.mdx) you want to read in your application. - Create a new [barcode capture mode](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance and initialize it with the settings created above. - Register a [barcode capture listener](#register-the-barcode-capture-listener) to receive scan events. Process the successful scans according to your application’s needs, e.g. by looking up information in a database. After a successful scan, decide whether more codes will be scanned, or the scanning process should be stopped. - Obtain a [camera](#use-the-built-in-camera) instance and set it as the frame source on the data capture context. - Display the camera preview by creating a [data capture view](#use-a-capture-view-to-visualize-the-scan-process). - If displaying a preview, optionally create a new [`overlay`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) and add it to data capture view for a better visual feedback. ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to your [Scandit account](https://ssl.scandit.com/dashboard/sign-in?p=test). ::: ### Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create the Data Capture Context Initialize the library and create a data capture context as shown below. For configuration options, `sdc-lib` hosting, and loading-status handling, see the [Installation guide](../add-sdk.md#configure-the-library). ```ts import { DataCaptureContext } from '@scandit/web-datacapture-core'; import { barcodeCaptureLoader } from '@scandit/web-datacapture-barcode'; const context = await DataCaptureContext.forLicenseKey('-- ENTER YOUR SCANDIT LICENSE KEY HERE --', { libraryLocation: new URL('self-hosted-sdc-lib/', document.baseURI).toString(), moduleLoaders: [barcodeCaptureLoader()], }); ``` :::note You must _await_ the returned promise as shown to be able to continue. For information about showing loading status and handling server-side rendering, see the [Installation guide](../add-sdk.md). ::: ## Configure the Barcode Scanning Behavior Barcode scanning is orchestrated by the [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) [data capture mode](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-mode.html#interface-scandit.datacapture.core.IDataCaptureMode). This class is the main entry point for scanning barcodes. It is configured through [BarcodeCaptureSettings](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture-settings.html#class-scandit.datacapture.barcode.BarcodeCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) that will get informed whenever new codes have been recognized. For this tutorial, we will setup barcode scanning for a small list of different barcode types, called symbologies. The list of symbologies to enable is highly application specific. We recommend that you only enable the list of symbologies your application requires. ```ts import { BarcodeCaptureSettings, Symbology } from '@scandit/web-datacapture-barcode'; const settings = new BarcodeCaptureSettings(); settings.enableSymbologies([ Symbology.Code128, Symbology.Code39, Symbology.QR, Symbology.EAN8, Symbology.UPCE, Symbology.EAN13UPCA, ]); ``` If you are not disabling barcode capture immediately after having scanned the first code, consider setting the [BarcodeCaptureSettings.codeDuplicateFilter](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture-settings.html#property-scandit.datacapture.barcode.BarcodeCaptureSettings.CodeDuplicateFilter) to around 500 or even -1 if you do not want codes to be scanned more than once. Next, create a [BarcodeCapture](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture.html#class-scandit.datacapture.barcode.BarcodeCapture) instance with the settings initialized in the previous step: ```ts import { BarcodeCapture } from '@scandit/web-datacapture-barcode'; const barcodeCapture = await BarcodeCapture.forContext( context, settings ); ``` ## Register the Barcode Capture Listener To get informed whenever a new code has been recognized, add a [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) through [BarcodeCapture.addListener()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.AddListener) and implement the listener methods to suit your application’s needs. First implement the [BarcodeCaptureListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture-listener.html#interface-scandit.datacapture.barcode.IBarcodeCaptureListener) interface. For example: ```ts import type { BarcodeCaptureListener, BarcodeCapture, BarcodeCaptureSession, Barcode } from '@scandit/web-datacapture-barcode'; const listener: BarcodeCaptureListener = { didScan: (barcodeCapture: BarcodeCapture, session: BarcodeCaptureSession, frameData: FrameData) => { const recognizedBarcode: Barcode = session.newlyRecognizedBarcode; // Do something with the barcode }, }; barcodeCapture.addListener(listener); ``` ### Rejecting Barcodes To prevent scanning unwanted codes, you can reject them by adding the desired logic to the `didScan` callback. This will prevent the barcode from being processed further. The example below will only scan barcodes beginning with the digits `09` and ignore all others, using a transparent brush to distinguish a rejected barcode from a recognized one: ```ts import { Brush } from '@scandit/web-datacapture-core'; import type { FrameData } from '@scandit/web-datacapture-core'; import type { BarcodeCaptureListener, BarcodeCapture, BarcodeCaptureSession, Barcode } from '@scandit/web-datacapture-barcode'; function onBarcodeCaptured(barcode: Barcode): void { // Handle the captured barcode, e.g. look up information in a database } const defaultBrush = overlay.getBrush(); const listener: BarcodeCaptureListener = { didScan: (barcodeCapture: BarcodeCapture, session: BarcodeCaptureSession, frameData: FrameData) => { const barcode = session.newlyRecognizedBarcode; if (!barcode?.data?.startsWith('09')) { // Barcode does not match — make it transparent and continue scanning await overlay.setBrush(Brush.transparent); return; } // Valid barcode: restore the default brush, stop scanning and process the result await overlay.setBrush(defaultBrush); await barcodeCapture.setEnabled(false); onBarcodeCaptured(barcode); }, }; barcodeCapture.addListener(listener); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. When using the built-in camera, there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```ts import { Camera } from '@scandit/web-datacapture-core'; import { BarcodeCapture } from '@scandit/web-datacapture-barcode'; const cameraSettings = BarcodeCapture.recommendedCameraSettings; // Depending on the use case further camera settings adjustments can be made here. const camera = Camera.pickBestGuess(); await camera.applySettings(cameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```ts await context.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/web/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/web/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```ts import { FrameSourceState } from '@scandit/web-datacapture-core'; await context.frameSource.switchToDesiredState(FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frameSource, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/web/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```ts import { DataCaptureView } from '@scandit/web-datacapture-core'; const view = await DataCaptureView.forContext(context); view.connectToElement(document.querySelector("#the-element-where-to-attach-the-view")); ``` To visualize the results of barcode scanning, the following [overlay](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-capture-overlay.html#class-scandit.datacapture.barcode.ui.BarcodeCaptureOverlay) can be added: ```ts import { BarcodeCaptureOverlay } from '@scandit/web-datacapture-barcode'; const overlay = await BarcodeCaptureOverlay.withBarcodeCaptureForView( barcodeCapture, view ); ``` ## Disabling Barcode Capture ```ts await barcodeCapture.setEnabled(false); ``` To disable barcode capture, for instance, as a consequence of a barcode being recognized call [BarcodeCapture.setEnabled()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-capture.html#method-scandit.datacapture.barcode.BarcodeCapture.SetEnabled) passing false. The effect is immediate: no more frames will be processed after the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off. --- ## Barcode Generator is not available on Web # Barcode Generator is not available on Web The Barcode Generator module is not available for the Web SDK. To view documentation for a platform that supports Barcode Generator, use the framework switcher at the top of the page. --- ## Barcode Selection is not available on Web # Barcode Selection is not available on Web The Barcode Selection module is not available for the Web SDK. To view documentation for a platform that supports Barcode Selection, use the framework switcher at the top of the page. --- ## Barcode Selection is not available on Web # Barcode Selection is not available on Web The Barcode Selection module is not available for the Web SDK. To view documentation for a platform that supports Barcode Selection, use the framework switcher at the top of the page. --- ## Barcode Symbologies import BarcodeSymbologies from '../../partials/_barcode-symbologies.mdx'; --- ## Multiple Barcode Scanning # Multiple Barcode Scanning import BatchScanning from '../../partials/_batch-scanning.mdx'; --- ## Core Concepts import CoreConcepts from '../../partials/_core-concepts.mdx'; --- ## Add-on Codes import ExtensionCodes from '../../partials/_extension-codes.mdx'; --- ## Features by Framework import FeaturesByFramework from '../../partials/_features-by-framework.mdx'; --- ## Get Started # Get Started Get up and running with SparkScan, the easiest way to start with Scandit barcode scanning. SparkScan provides top performance and optimized scanning UX with just a few lines of code, incorporating the best practices developed by Scandit across years of experience and billions of scans. The intentionally minimalistic UI floats on top of any smartphone application, without the need to adapt the existing app. The fastest way to get started is by running our sample application, so we'll cover that first. After that, we'll show you how to integrate SparkScan into your own application. ## Prerequisites Before you start, make sure you have the following: - Most recent LTS versions of Node.js and npm installed on your machine. You can download them from the [Node.js website](https://nodejs.org/). - A Scandit License Key. You can get a free trial key by signing up for an account on the [Scandit website](https://ssl.scandit.com/dashboard/sign-up). ## Sample Application In this section, we'll show you how to try SparkScan in minutes by running our sample application. ### Running the Sample Application 1. First we need a copy of the sample application. It is available on GitHub and also bundled with the SDK archive you can download from your Scandit account dashboard. Here we'll use the GitHub repository. ```bash git clone https://github.com/Scandit/datacapture-web-samples.git ``` 2. The repository contains many sample applications you can try. For this example, we'll use the **ListBuildingSample**. Navigate to the sample directory from the terminal or your preferred IDE: ```bash cd datacapture-web-samples/ListBuildingSample ``` 3. From the `/src/app` directory, open the `presented.ts` file and replace the `licenseKey` variable with your Scandit License Key: ```typescript ... licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE --", ... ``` 4. Install the dependencies: ```bash npm install ``` 5. Start the development server: ```bash npm run dev ``` 6. Open your browser and navigate to `http://localhost:8888`. You should see the sample application running. ## Integrating SparkScan into Your Application This section will guide you through the general steps for integrating SparkScan into your own application. There may be additional steps depending on your specific use case, and you can always reach out to [Scandit Support](mailto:support@scandit.com) with any issues. ### 1. Installation First you need to install the required packages. You can this via npm: ```bash # Core library npm install --save @scandit/web-datacapture-core # Barcode scanning functionality npm install --save @scandit/web-datacapture-barcode ``` ### 2. Create the Context The first step is to create a context for the Data Capture tasks. This is done by creating an instance of the `DataCaptureContext` class: ```typescript const context = await DataCaptureContext.forLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --", { libraryLocation: new URL("library/engine/", document.baseURI).toString(), moduleLoaders: [barcodeCaptureLoader()], }); ``` ### 3. Configure SparkScan Settings Next, you need to configure your desired settings for SparkScan, such as the symbologies you want to scan. This is done by creating an instance of the `SparkScanSettings` class: ```typescript const settings = new SparkScanSettings(); settings.enableSymbologies([Symbology.EAN13UPCA, Symbology.Code128]); settings.codeDuplicateFilter = 0; settings.scanIntention = ScanIntention.Smart; ``` In this example, we're: - Enabling both EAN-13 and Code 128 symbologies - Setting the code duplicate filter to 0, meaning the same code can be reported multiple times - Using the Smart [scan intention](https://docs.scandit.com/data-capture-sdk/web/core/api/scan-intention.html#enum-scandit.datacapture.core.ScanIntention) algorithm, to reduce the likelihood of unintended scans Lastly, we apply the settings to the SparkScan instance. ### 4. Setup the SparkScanView Now we'll create and configure the scanner view and it's settings. This is done via the `SparkScanView` and `SparkScanViewSettings` classes: ```typescript const viewSettings = new SparkScanViewSettings(); viewSettings.defaultScanningMode = new SparkScanScanningModeTarget(); viewSettings.soundEnabled = true; viewSettings.hapticEnabled = false; ``` In this example, we're: - Setting the default scanning mode to `SparkScanScanningModeTarget` for precision scanning - Enabling sound feedback - Disabling haptic feedback Next, we create the `SparkScanView` instance, adding the scanning interface to the application. There are two valid ways to instantiate the `SparkScanView`: **Option 1 — Web Component (recommended for React and other frameworks):** Register the web component once, then use the `` custom element: ```typescript SparkScanView.register(); // In your render/component: (context && sparkScan) && ``` **Option 2 — `SparkScanView.forElement()` (vanilla JS):** ```typescript const sparkScanView = SparkScanView.forElement( document.getElementById("spark-scan-ui"), context, sparkScan, viewSettings ); ``` In your application's state handling logic, you must also call the `stopScanning` method when the scanner is no longer needed: ```typescript useEffect(() => { return () => { sparkScanViewRef.current?.stopScanning().catch(console.error); }; }, []); ``` For a complete React integration example, see the [SparkScan React Sample](https://github.com/Scandit/datacapture-web-samples/tree/master/05_Framework_Integration_Samples/SparkScanReactSample). ### 5. Implement the Listener Lastly, you need to implement the listener to handle the scanned data. This is done by creating an instance of the [`SparkScanListener`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) class: ```typescript const listener = { didScan: (sparkScan, session, getFrameData) => { // Gather the recognized barcode const barcode = session.newlyRecognizedBarcode; // Handle the barcode }, }; sparkScan.addListener(listener); ``` Here, `didScan()` is called when a barcode is recognized. You can access the recognized barcode data from the `SparkScanSession` object. ### 6. Next Steps This guide provides a basic overview of how to integrate SparkScan into your application. For more detailed information, check out the [SparkScan documentation](/sdks/web/sparkscan/intro.md) and [SparkScan API Reference](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/spark-scan.html). If you have any questions or need help, feel free to reach out to [Scandit Support](mailto:support@scandit.com). --- ## Advanced Configurations # Advanced Configurations There are several advanced configurations that can be used to customize the behavior of the ID Capture SDK and enable additional features. ## Configure Data Anonymization By default, data extracted from documents is anonymized according to local regulations. See [Anonymized Documents](/sdks/web/id-capture/supported-documents.md#anonymized-documents) for more information. That means certain data from certain fields won’t be returned, even if it’s present on a document. You control the anonymization level with the following setting: ```js // Default value: settings.anonymizationMode = IdAnonymizationMode.FieldsOnly; // Sensitive data is additionally covered with black boxes on returned images: settings.anonymizationMode = IdAnonymizationMode.FieldsAndImages; // Only images are anonymized: settings.anonymizationMode = IdAnonymizationMode.ImagesOnly; // No anonymization: settings.anonymizationMode = IdAnonymizationMode.None; ``` ## ID Images Your use can may require that you capture and extract images of the ID document. Use the [IdImageType](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-image-type.html#enum-scandit.datacapture.id.IdImageType) enum to specify the images you want to extract from the `CapturedId` object. :::tip Face and Cropped Document can be extracted only by either `SingleSideScanner` with `visualInspectionZone` enabled or by `FullDocumentScanner`. In the case of `FullDocumentScanner`, if the front & the back side of a document are scanned, Cropped Document and Full Frame are returned for both sides. ::: For the full frame of the document, you can use [`setShouldPassImageTypeToResult`](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-settings.html#method-scandit.datacapture.id.IdCaptureSettings.SetShouldPassImageTypeToResult) when creating the `IdCaptureSettings` object. This will pass the image type to the result, which you can then access in the `CapturedId` object. ```js import { IdImageType } from "@scandit/web-datacapture-id"; // Holder's picture as printed on a document: settings.setShouldPassImageTypeToResult(IdImageType.Face, true); // Cropped image of a document: settings.setShouldPassImageTypeToResult(IdImageType.CroppedDocument, true); // Full camera frame that contains the document: settings.setShouldPassImageTypeToResult(IdImageType.Frame, true); ``` ## Callbacks and Scanning Workflows The ID Capture Listener provides two callbacks: `didCaptureId` and `didRejectId`. The `didCaptureId` callback is called when an acceptable document is successfully captured, while the `didRejectId` callback is called when a document is captured but rejected. For a successful capture, the `didCaptureId` callback provides a `CapturedId` object that contains the extracted information from the document. This object is specific to the type of document scanned. For example, a `CapturedId` object for a US Driver License will contain different fields than a `CapturedId` object for a Passport. For a rejected document, a [RejectionReason](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) is provided in the `didRejectId` callback to help you understand why the document was rejected and to take appropriate action. These are: * NOT_ACCEPTED_DOCUMENT_TYPE: The document is not in the list of accepted documents. In this scenario, you could direct the user to scan a different document. * INVALID_FORMAT: The document is in the list of accepted documents, but the format is invalid. In this scenario, you could direct the user to scan the document again. * DOCUMENT_VOIDED: The document is in the list of accepted documents, but the document is voided. In this scenario, you could direct the user to scan a different document. * TIMEOUT: The document was not scanned within the specified time. In this scenario, you could direct the user to scan the document again. ## Detect Fake IDs *ID Validate* is a fake ID detection software. It currently supports documents that follow the Driver License/Identification Card specification by the American Association of Motor Vehicle Administrators (AAMVA). Fake ID detection can be performed as follows: * [AAMVABarcodeVerifier](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/aamva-barcode-verifier.html#class-scandit.datacapture.id.AamvaBarcodeVerifier): Validates the authenticity of the document by scanning the barcode on the back. * [IdCaptureSettings.rejectInconsistentData](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.RejectInconsistentData): Automatically rejects documents whose human‑readable data does not match the data encoded in the barcode or MRZ. To enable ID validation for your subscription, please reach out to [Scandit Support](mailto:support@scandit.com). --- ## Get Started # Get Started This page will guide you through the process of adding ID Capture to your Web application. ID Capture is a mode of the Scandit Data Capture SDK that allows you to capture and extract information from personal identification documents, such as driver's licenses, passports, and ID cards. The general steps are: - Create a [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). - Access a [Camera](https://docs.scandit.com/data-capture-sdk/web/core/api/camera.html#class-scandit.datacapture.core.Camera). - Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scan process. - Implement an [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener) to receive scan results. - Set up [DataCaptureView](https://docs.scandit.com/data-capture-sdk/web/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) and [IdCaptureOverlay](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) to see the camera feed and the scan UI. - Begin the scanning by adding an [IdCapture](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture.html#class-scandit.datacapture.id.IdCapture) to [DataCaptureContext](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext) and starting a camera. :::warning Using ID Capture at the same time as other modes (e.g. Barcode Capture) is not supported. ::: ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](/sdks/web/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: Please note that your license may support only a subset of ID Capture features. If you would like to use additional features please contact us at [Scandit Support](mailto:support@scandit.com). ### Configure and Initialize the Library In addition to the configuration detailed in the [installation guide](/sdks/web/add-sdk.md#configure-the-library), there are some additional steps required for ID Capture. For ID Capture, the result of [idCaptureLoader()](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture.html#method-scandit.datacapture.id.IdCaptureLoader) must be passed to the [ConfigureOptions.moduleLoaders](https://docs.scandit.com/data-capture-sdk/web/core/api/web/configure.html#property-scandit.datacapture.core.IConfigureOptions.ModuleLoaders) option. In this example, we will scan VIZ documents, so we also need to set [IdCaptureLoaderOptions.enableVIZDocuments](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture.html#property-scandit.datacapture.id.IIdCaptureLoaderOptions.EnableVIZDocuments) to `true`: ```ts import { DataCaptureContext } from "@scandit/web-datacapture-core"; import { idCaptureLoader } from "@scandit/web-datacapture-id"; const context = await DataCaptureContext.forLicenseKey( "-- ENTER YOUR SCANDIT LICENSE KEY HERE --", { libraryLocation: "/self-hosted-sdc-lib/", moduleLoaders: [idCaptureLoader({ enableVIZDocuments: true })], } ); ``` :::tip Avoid enabling VIZ documents if you only scan MRZs or barcodes, as it slows down the scanning initialization because more data must be downloaded. ::: :::warning You must await the returned promise as shown to be able to continue. ::: ## Create the View When the scanning process is requested, it is good practice to keep the user informed about what is happening. The SDK may still be loading so you should display a view to the user as soon as possible. To do that, start by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/web/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) and attach it to an HTML element in the page. For example, let's display a progress bar while the SDK is loading: ```ts import { DataCaptureView } from "@scandit/web-datacapture-core"; const view = new DataCaptureView(); view.connectToElement(htmlElement); view.showProgressBar(); ``` :::tip You may not need to do this so early if your application loads the SDK in the background (e.g. on startup) and the view is already available when the user requests scanning. ::: ## Attach Context to View If you already created a view earlier (as shown in the "Create the View" section), you should now attach the context to it: ```js await view.setContext(context); ``` ## Add the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/web/core/api/camera.html#class-scandit.datacapture.core.Camera "Camera class"): ```ts import { Camera } from "@scandit/web-datacapture-core"; import { IdCapture } from "@scandit/web-datacapture-id"; // let the SDK pick the best camera for ID Capture const camera = Camera.pickBestGuess(); // apply the optimized camera settings from ID Capture await camera.applySettings(IdCapture.recommendedCameraSettings); await context.setFrameSource(camera); ``` ## Create ID Capture Settings Use [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings) to configure the scanner type to use and the documents that should be accepted and/or rejected. Check [IdCaptureDocumentType](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-document.html#enum-scandit.datacapture.id.IdCaptureDocumentType) for all available options. :::tip By default, [anonymized data](./advanced.md#configure-data-anonymization) is not returned in accordance with local regulations for specific documents. This setting can be disabled for testing purposes, but be sure to comply with local laws and requirements in production. ::: ```ts import { IdCapture, IdCaptureScanner, IdCaptureSettings, IdCard, Region, RegionSpecific, Passport, SingleSideScanner, FullDocumentScanner, } from "@scandit/web-datacapture-id"; const settings = new IdCaptureSettings(); // Documents from any region: settings.acceptedDocuments.push(new Passport(Region.Any)); // Only documents issued by a specific country: settings.acceptedDocuments.push(new IdCard(Region.Germany)); // Regional documents: settings.acceptedDocuments.push(new RegionSpecific.ApecBusinessTravelCard()); // If we added passports for all regions like above, we can exclude some specific regions settings.rejectedDocuments.push(new Passport(Region.Cuba)); // To scan only one-sided documents and a given zone: // Signature: SingleSideScanner(barcode: boolean, machineReadableZone boolean, visualInspectionZone: boolean) // This would only scan a single side document having an MRZ: settings.scanner = new IdCaptureScanner({ physicalDocument: new SingleSideScanner(true, false, false), }); // To scan both sides of the document: settings.scanner = new IdCaptureScanner({ physicalDocument: new FullDocumentScanner(), }); ``` Create a new ID Capture mode with the chosen settings: ```ts const idCapture = await IdCapture.forContext(context, settings); ``` ## Implement the listener To receive scan results, implement [IdCaptureListener](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-listener.html#interface-scandit.datacapture.id.IIdCaptureListener). The listener provides two important callbacks: `didCaptureId` and `didRejectId`. ```ts import { type CapturedId, RejectionReason } from "@scandit/web-datacapture-id"; idCapture.addListener({ didCaptureId: (capturedId: CapturedId) => { // Success! Handle extracted data here. }, didRejectId: (capturedId: CapturedId, reason: RejectionReason) => { // Something went wrong. Inspect the reason to determine the follow-up action. }, }); ``` When `didCaptureId` or `didRejectId` are called, IdCapture is automatically [reset](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture.html#method-scandit.datacapture.id.IdCapture.Reset) except when the rejection is due to a timeout (see [rejection reason](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/rejection-reason.html)). Note that the camera is still running, you may want to switch it off at this point. ### Handling Success Captured results are delivered as a [CapturedId](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/captured-id.html#class-scandit.datacapture.id.CapturedId). This class contains data common for all kinds of personal identification documents. Note that if you scan boths sides of a document using the [FullDocumentScanner](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-scanner.html#full-document-scanner), this callback will only be executed once both sides have been successfully captured. If the document is known to have only one side, the callback will execute immediately after a successful scan of the first side. This behaviour can be modified with the setting [notifyOnSideCapture](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-settings.html#property-scandit.datacapture.id.IdCaptureSettings.NotifyOnSideCapture). On a successful scan you may read the extracted data from `capturedId`: ```ts didCaptureId: async (capturedId: CapturedId) => { // stop processing new frames, we have a result await idCapture.setEnabled(false); const fullName = capturedId.fullName; const dateOfBirth = capturedId.dateOfBirth; const dateOfExpiry = capturedId.dateOfExpiry; const documentNumber = capturedId.documentNumber; // Process data: processData(fullName, dateOfBirth, dateOfExpiry, documentNumber); }; ``` :::tip All data fields are optional, so it's important to verify whether the required information is present if some of the accepted documents may not contain certain data. ::: ### Handling Rejection The ID scanning process may fail for various reasons. Start from inspecting [RejectionReason](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/rejection-reason.html#enum-scandit.datacapture.id.RejectionReason) to understand the cause. Note that some data may still have been captured, you will find them in the first `capturedId` parameter of the callback. You may wish to implement the follow-up action based on the reason of failure: ```ts didRejectId: (capturedId: CapturedId, reason: RejectionReason) => { if (reason === RejectionReason.Timeout) { // Ask the user to retry, or offer alternative input method. } else if (reason === RejectionReason.DocumentExpired) { // Ask the user to provide alternative document. } else if (reason === RejectionReason.NotAcceptedDocumentType) { // Inform the user which documents are accepted. } ... } ``` ## Add an Overlay The overlay informs and guides the user during the scanning process. Create an instance of [IdCaptureOverlay](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/ui/id-capture-overlay.html#class-scandit.datacapture.id.ui.IdCaptureOverlay) for the existing view like so: ```ts import { IdCaptureOverlay } from "@scandit/web-datacapture-id"; const overlay = await IdCaptureOverlay.withIdCaptureForView(idCapture, view); ``` The overlay chooses the displayed UI automatically, based on the selected [IdCaptureSettings](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-settings.html#class-scandit.datacapture.id.IdCaptureSettings). If you prefer to show a different UI or to temporarily hide it, set the appropriate [IdCaptureOverlay.idLayout](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/ui/id-capture-overlay.html#property-scandit.datacapture.id.ui.IdCaptureOverlay.IdLayout). ## Start the Capture Process Finally, turn on the camera to start scanning: ```ts import { FrameSourceState } from "@scandit/web-datacapture-core"; // ... await camera.switchToDesiredState(FrameSourceState.On); ``` You can also enable or disable IdCapture by using [setEnabled](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture.html#method-scandit.datacapture.id.IdCapture.SetEnabled) whenever you need to. ## Complete IdCapture Example ```js import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState, } from "@scandit/web-datacapture-core"; import { IdCapture, IdCaptureOverlay, IdCaptureSettings, IdCard, Passport, Region, FullDocumentScanner, IdCaptureScanner, RejectionReason, idCaptureLoader, } from "@scandit/web-datacapture-id"; const context = await DataCaptureContext.forLicenseKey( "-- ENTER YOUR SCANDIT LICENSE KEY HERE --", { libraryLocation: "/self-hosted-sdc-lib/", moduleLoaders: [idCaptureLoader({ enableVIZDocuments: true })], } ); const view = await DataCaptureView.forContext(context); view.connectToElement(document.body); const camera = Camera.pickBestGuess(); await camera.applySettings(IdCapture.recommendedCameraSettings); await context.setFrameSource(camera); const settings = new IdCaptureSettings(); settings.acceptedDocuments.push(new IdCard(Region.Any)); settings.acceptedDocuments.push(new Passport(Region.Any)); settings.scanner = new IdCaptureScanner({ physicalDocument: new FullDocumentScanner(), }); const idCapture = await IdCapture.forContext(context, settings); idCapture.addListener({ didCaptureId: async (capturedId) => { await idCapture.setEnabled(false); console.log("Captured ID:", { fullName: capturedId.fullName, dateOfBirth: capturedId.dateOfBirth, documentNumber: capturedId.documentNumber, dateOfExpiry: capturedId.dateOfExpiry, }); }, didRejectId: (capturedId, reason) => { console.log("ID rejected:", reason); if (reason === RejectionReason.Timeout) { console.log("Scan timed out. Please try again."); } else if (reason === RejectionReason.NotAcceptedDocumentType) { console.log("Document type not accepted."); } }, }); const overlay = await IdCaptureOverlay.withIdCaptureForView(idCapture, view); async function mount() { await camera.switchToDesiredState(FrameSourceState.On); await idCapture.setEnabled(true); } async function unmount() { await camera.switchToDesiredState(FrameSourceState.Off); await idCapture.setEnabled(false); } mount().catch(async (error) => { console.error(error); await unmount(); }); ``` A more complete example can be found [here on StackBlitz](https://stackblitz.com/github/Scandit/datacapture-web-samples/tree/master/02_ID_Scanning_Samples/IdCaptureSimpleSample). --- ## About ID Capture import AboutIdCapture from '../../../partials/intro/_about-id-capture.mdx'; --- ## Supported Documents ## ID Scanning Supported Documents Scandit ID Capture provides various [IdCaptureScanner](https://docs.scandit.com/data-capture-sdk/web/id-capture/api/id-capture-scanner.html#id-capture-scanner) types, each designed for specific scanning workflows. These workflows can involve scanning either specific parts of a document or the entire document, including both the front and back sides. This section details the types of documents supported by each scanner type. import IdDocumentsFull from '../../../partials/advanced/_id-documents-full-document.mdx'; import IdDocumentsSingleSide from '../../../partials/advanced/_id-documents-single-side.mdx'; ## ID Validation Supported Documents import IdValidateDocuments from '../../../partials/advanced/_id-documents-validate.mdx'; --- ## Advanced Configurations import ValidationFlowHowItWorks from '../../../partials/advanced/_validation-flow-how-it-works.mdx'; import ValidationFlowCustomButtons from '../../../partials/advanced/_validation-flow-custom-buttons.mdx'; import ValidationFlowTypingHints from '../../../partials/advanced/_validation-flow-typing-hints.mdx'; import ValidationFlowCloudVLM from '../../../partials/advanced/_validation-flow-cloud-vlm.mdx'; import ReceiptScanning from '../../../partials/advanced/_receipt-scanning.mdx'; import ValidationFlowRequiredOptional from '../../../partials/advanced/_validation-flow-required-optional.mdx'; import ValidationFlowCustomToasts from '../../../partials/advanced/_validation-flow-custom-toasts.mdx'; import ValidationFlowCustomField from '../../../partials/advanced/_validation-flow-custom-field.mdx'; # Advanced Configurations ## Customize the Overlay Appearance To customize the appearance of the overlay, you can implement a [LabelCaptureBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/ui/label-capture-basic-overlay-listener.html#interface-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener). The method [brushForLabel()](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForLabel) is called every time a label captured and [brushForField()](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/ui/label-capture-basic-overlay-listener.html#method-scandit.datacapture.label.ui.ILabelCaptureBasicOverlayListener.BrushForField) is called for each of its fields to determine the brush for the label or field. ```js import { Brush, Color } from "@scandit/web-datacapture-core"; overlay.listener = { brushForField: (overlay, field, label) => { switch (field.name) { case "": return new Brush( Color.fromRGBA(0, 255, 255, 0.5), Color.fromRGBA(0, 255, 255, 0.5), 0 ); case "": return new Brush( Color.fromRGBA(255, 165, 0, 0.5), Color.fromRGBA(255, 165, 0, 0.5), 0 ); default: return Brush.transparent; } }, brushForLabel: (overlay, label) => Brush.transparent, onLabelTapped: (overlay, label) => { // Handle user tap gestures on the label. }, }; ``` :::tip Use brush colors with transparency (alpha ```js // Create the overlay const validationFlowOverlay = await LabelCaptureValidationFlowOverlay.withLabelCaptureForView( labelCapture, dataCaptureView ); // Set the listener to receive validation events validationFlowOverlay.listener = validationFlowListener; ``` ### Define a Listener When the user has verified that all fields are correctly captured and presses the finish button, the Validation Flow triggers a callback with the final results. To receive these results, implement the [LabelCaptureValidationFlowOverlayListener](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/ui/label-capture-validation-flow-listener.html) interface: ```js const validationFlowListener = { // This is called by the validation flow overlay when a label has been fully captured and validated onValidationFlowLabelCaptured: (fields) => { const barcodeData = fields.find(f => f.name === "")?.barcode?.data; const expiryDate = fields.find(f => f.name === "")?.text; // Handle the captured values } }; ``` ```js const validationFlowOverlaySettings = await LabelCaptureValidationFlowSettings.create(); await validationFlowOverlaySettings.setPlaceholderTextForLabelDefinition("Expiry Date", "MM/DD/YYYY") validationFlowOverlay.applySettings(validationFlowOverlaySettings) ``` ```js const validationFlowOverlaySettings = await LabelCaptureValidationFlowSettings.create(); await validationFlowOverlaySettings.setRestartButtonText("Borrar todo") await validationFlowOverlaySettings.setPauseButtonText("Pausar") await validationFlowOverlaySettings.setFinishButtonText("Finalizar") validationFlowOverlay.applySettings(validationFlowOverlaySettings) ``` ```js const validationFlowOverlaySettings = await LabelCaptureValidationFlowSettings.create(); await validationFlowOverlaySettings.setStandbyHintText("No label detected, camera paused"); await validationFlowOverlaySettings.setValidationHintText("data fields collected"); // X/Y (X fields out of total Y) is shown in front of this string validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const validationFlowOverlaySettings = await LabelCaptureValidationFlowSettings.create(); await validationFlowOverlaySettings.setValidationErrorText("Incorrect format."); await validationFlowOverlaySettings.setScanningText("Scan in progress"); await validationFlowOverlaySettings.setAdaptiveScanningText("Processing"); validationFlowOverlay.applySettings(validationFlowOverlaySettings); ``` ```js const retailItem = await new LabelDefinitionBuilder() .addCustomBarcode( await new CustomBarcodeBuilder() .isOptional(false) .setSymbologies([Symbology.EAN13UPCA, Symbology.GS1DatabarExpanded, Symbology.Code128]) .build("Barcode") ) .addExpiryDateText( await new ExpiryDateTextBuilder() .isOptional(true) .setLabelDateFormat(new LabelDateFormat(LabelDateComponentFormat.MDY)) .build("Expiry Date") ) .adaptiveRecognitionMode(AdaptiveRecognitionMode.Auto) .build("Perishable Product"); ``` See [AdaptiveRecognitionMode](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/label-definition.html#property-scandit.datacapture.label.LabelDefinition.AdaptiveRecognitionMode) for available options. --- ## Get Started # Get Started In this guide you will learn step-by-step how to add Smart Label Capture to your application. The general steps are: - Create a component to handle the capture process - Initialize the Data Capture Context - Initialize the Label Capture Mode - Implement a listener to handle captured labels - Visualize the scan process - Start the camera - Provide feedback ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this [guide](/sdks/web/add-sdk.md). :::tip You can retrieve your Scandit Data Capture SDK license key by signing in to your account [Dashboard](https://ssl.scandit.com/dashboard/sign-in). ::: ### Module Overview import LabelCaptureModuleOverview from '../../../partials/get-started/\_smart-label-capture-module-overview-web.mdx'; ## Initialize the Data Capture Context import DataCaptureContextWeb from '../../../partials/get-started/\_create-data-capture-context-web.mdx'; ## Initialize the Label Capture Mode The main entry point for the Label Capture Mode is the [LabelCapture](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/label-capture.html#class-scandit.datacapture.label.LabelCapture) object. It is configured through [LabelCaptureSettings](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/label-capture-settings.html#class-scandit.datacapture.label.LabelCaptureSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) that get informed whenever a new frame has been processed. ```js import { Symbology } from "@scandit/web-datacapture-barcode"; import { CustomBarcodeBuilder, ExpiryDateTextBuilder, ImeiOneBarcodeBuilder, ImeiTwoBarcodeBuilder, LabelCapture, LabelCaptureFeedback, LabelCaptureSettingsBuilder, LabelDateComponentFormat, LabelDateFormat, LabelDefinitionBuilder, SerialNumberBarcodeBuilder, TotalPriceTextBuilder, UnitPriceTextBuilder, WeightTextBuilder, labelCaptureLoader, } from "@scandit/web-datacapture-label"; const isofLabel = await new LabelDefinitionBuilder() .addCustomBarcode( // Create a barcode field with the expected symbologies await new CustomBarcodeBuilder() .isOptional(false) .setSymbologies([Symbology.EAN13UPCA]) .build("Barcode") ) .addTotalPriceText( await new TotalPriceTextBuilder().isOptional(false).build("Total Price") ) .addUnitPriceText( await new UnitPriceTextBuilder().isOptional(false).build("Unit Price") ) .addExpiryDateText( await new ExpiryDateTextBuilder() .isOptional(false) .setLabelDateFormat(new LabelDateFormat(LabelDateComponentFormat.MDY)) .build("Expiry Date") ) .addWeightText( await new WeightTextBuilder().isOptional(false).build("Weight") ) .build("ISOF Label"); const smartDeviceLabel = await new LabelDefinitionBuilder() .addImeiOneBarcode( await new ImeiOneBarcodeBuilder() .isOptional(false) .setSymbologies([Symbology.Code128]) .build("IMEI") ) .addImeiTwoBarcode( await new ImeiTwoBarcodeBuilder() .isOptional(false) .setSymbologies([Symbology.Code128]) .build("IMEI2") ) .addSerialNumberBarcode( await new SerialNumberBarcodeBuilder() .isOptional(false) .setSymbologies([Symbology.Code128]) .build("Serial Number") ) .addCustomBarcode( await new CustomBarcodeBuilder() .isOptional(false) .setSymbologies([Symbology.Code128]) .build("EID") ) .build("Smart Device Label"); const settings = await new LabelCaptureSettingsBuilder() .addLabel(isofLabel) .addLabel(smartDeviceLabel) .build(); // Create the label capture mode with the settings and data capture context created earlier const labelCapture = await LabelCapture.forContext(dataCaptureContext, settings); ``` ## Implement a Listener to Handle Captured Labels To get informed whenever a new label has been recognized, add a [LabelCaptureListener](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/label-capture-listener.html#interface-scandit.datacapture.label.ILabelCaptureListener) through [LabelCapture.addListener()](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/label-capture.html#method-scandit.datacapture.label.LabelCapture.AddListener) and implement the listener methods to suit your application’s needs. First conform to the `LabelCaptureListener` interface. Here is an example of how to implement a listener that processes the captured labels based on the label capture settings defined above. ```ts import { CapturedLabel, LabelCaptureListener, } from "@scandit/web-datacapture-label"; import type { LabelCapture, LabelCaptureSession, } from "@scandit/web-datacapture-label"; const labelCaptureListener: LabelCaptureListener = { async didUpdateSession( labelCapture: LabelCapture, session: LabelCaptureSession ) { /* * The session update callback is called for every processed frame. * Early return if no label has been captured. */ if (!session.capturedLabels.length) return; session.capturedLabels.forEach((capturedLabel) => { const { fields } = capturedLabel; /* * Given the label capture settings defined above, barcode data will always be present. */ const barcodeData = fields.find( (field) => field.name === "" )?.barcode?.data; /* * The expiry date is an optional field. * Check for null in your result handling. */ const expiryDate = fields.find( (field) => field.name === "" )?.text; /* * Handle the captured data as needed, for example: * - Update your app's state * - Call a callback function * - Navigate to a results screen */ onLabelCaptured({ barcodeData, expiryDate }); }); /* * Disable the label capture mode after all labels have been processed * to prevent it from capturing the same labels multiple times. */ await labelCapture.setEnabled(false); /* * You may want to communicate a successful scan with vibration and audio feedback. * See the Feedback section for more information on how to customize the feedback. */ LabelCaptureFeedback.default.success.emit(); }, }; ``` ## Visualize the Scan Process The capture process can be visualized by adding a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/web/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy. The view controls the UI elements, such as the viewfinder and overlays, that are shown to visualize captured labels. To visualize the results of Label Capture, you can choose between two overlays, [LabelCaptureBasicOverlay](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/ui/label-capture-basic-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureBasicOverlay) and [LabelCaptureAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/ui/label-capture-advanced-overlay.html#class-scandit.datacapture.label.ui.LabelCaptureAdvancedOverlay). Here is an example of how to add a `LabelCaptureBasicOverlay` to the `DataCaptureView`. ```js import { RectangularViewfinder, RectangularViewfinderStyle, } from "@scandit/web-datacapture-core"; import { LabelCapture, LabelCaptureBasicOverlay, } from "@scandit/web-datacapture-label"; // Create the overlay with the label capture mode created earlier const overlay = await LabelCaptureBasicOverlay.withLabelCaptureForView(mode, view); // Add a square viewfinder to the overlay to guide users through the capture process const viewfinder = new RectangularViewfinder(RectangularViewfinderStyle.Square); await overlay.setViewfinder(viewfinder); ``` :::tip See the [Advanced Configurations](advanced.md) section for more information about how to customize the appearance of the overlays and how to use the advanced overlay to display arbitrary Android views such as text views, icons or images. ::: ## Start the Camera You need to also create the [Camera](https://docs.scandit.com/data-capture-sdk/web/core/api/camera.html#class-scandit.datacapture.core.Camera): ```js import { Camera } from "@scandit/web-datacapture-core"; const camera = Camera.pickBestGuess(); await context.setFrameSource(camera); const cameraSettings = LabelCapture.createRecommendedCameraSettings(); // Depending on the use case further camera settings adjustments can be made here. await camera.applySettings(cameraSettings); ``` Once the `Camera`, `DataCaptureContext`, `DataCaptureView` and `LabelCapture` are initialized, you can switch on the camera to start capturing labels. Typically, this is done once the view becomes active and the user granted permission to use the camera, or once the user presses continue scanning after handling a previous scan. ```js await camera.switchToDesiredState(FrameSourceState.On); ``` Please refer to the available [sample apps](https://github.com/Scandit/datacapture-web-samples) for detailed examples of camera permission handling and view lifecycle management. ## Provide Feedback Smart Label Capture provides customizable feedback, emitted automatically when a label is recognized and successfully processed, configurable via [`LabelCapture.feedback`](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/label-capture.html#property-scandit.datacapture.label.LabelCapture.Feedback). You can use the default feedback, or configure your own sound or vibration. :::tip If you already have a [Feedback](https://docs.scandit.com/data-capture-sdk/web/core/api/feedback.html#class-scandit.datacapture.core.Feedback) instance implemented in your application, remove it to avoid double feedback. ::: ```js import { LabelCaptureFeedback } from "@scandit/web-datacapture-label"; const feedback = LabelCaptureFeedback.default; ``` :::note Audio feedback is only played if the device is not muted. ::: ## Complete Label Capture Example ```js import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState, RectangularViewfinder, RectangularViewfinderStyle, } from "@scandit/web-datacapture-core"; import { Symbology } from "@scandit/web-datacapture-barcode"; import { CustomBarcodeBuilder, LabelCapture, LabelCaptureBasicOverlay, LabelCaptureSettingsBuilder, LabelDefinitionBuilder, TotalPriceTextBuilder, UnitPriceTextBuilder, labelCaptureLoader, } from "@scandit/web-datacapture-label"; const context = await DataCaptureContext.forLicenseKey( "-- ENTER YOUR SCANDIT LICENSE KEY HERE --", { libraryLocation: "/self-hosted-sdc-lib/", moduleLoaders: [labelCaptureLoader()], } ); const view = await DataCaptureView.forContext(context); view.connectToElement(document.body); const camera = Camera.pickBestGuess(); await context.setFrameSource(camera); const cameraSettings = LabelCapture.createRecommendedCameraSettings(); await camera.applySettings(cameraSettings); const priceLabel = await new LabelDefinitionBuilder() .addCustomBarcode( await new CustomBarcodeBuilder() .isOptional(false) .setSymbologies([Symbology.EAN13UPCA]) .build("Barcode") ) .addTotalPriceText( await new TotalPriceTextBuilder().isOptional(false).build("Total Price") ) .addUnitPriceText( await new UnitPriceTextBuilder().isOptional(false).build("Unit Price") ) .build("Price Label"); const settings = await new LabelCaptureSettingsBuilder() .addLabel(priceLabel) .build(); const labelCapture = await LabelCapture.forContext(context, settings); labelCapture.addListener({ didUpdateSession: async (labelCapture, session) => { session.capturedLabels.forEach((label) => { const barcode = label.fields.find((field) => field.name === "Barcode") ?.barcode?.data; const totalPrice = label.fields.find( (field) => field.name === "Total Price" )?.text; const unitPrice = label.fields.find( (field) => field.name === "Unit Price" )?.text; console.log("Captured:", { barcode, totalPrice, unitPrice }); }); await labelCapture.setEnabled(false); }, }); const overlay = await LabelCaptureBasicOverlay.withLabelCaptureForView(labelCapture, view); const viewfinder = new RectangularViewfinder(RectangularViewfinderStyle.Square); await overlay.setViewfinder(viewfinder); async function mount() { await camera.switchToDesiredState(FrameSourceState.On); } async function unmount() { await camera.switchToDesiredState(FrameSourceState.Off); await labelCapture.setEnabled(false); } mount().catch(async (error) => { console.error(error); await unmount(); }); ``` A more complete example can be found [here on StackBlitz](https://stackblitz.com/github/Scandit/datacapture-web-samples/tree/master/03_Advanced_Batch_Scanning_Samples/05_Smart_Label_Capture/LabelCaptureSimpleSample). --- ## About Smart Label Capture import AboutLabelCapture from '../../../partials/intro/_about-smart-label-capture.mdx'; --- ## Label Definitions # Label Definitions A **Label Definition** is a configuration that defines the label, and its relevant fields, that Smart Label Capture should recognize and extract during scans. Smart Label Capture provides a [Label Definition](https://docs.scandit.com/data-capture-sdk/web/label-capture/api/label-definition.html#label-definition) API, enabling you to configure and extract structured data from predefined and custom labels. This feature provides a flexible way to recognize and decode fields within a specific label layout such as price tags, VIN labels, or packaging stickers without needing to write custom code for each label type. There are two approaches to using label definitions: - [**Pre-built Labels**](#pre-built-labels) - [**Custom Labels**](#custom-labels) ## Pre-built Labels Smart Label Capture includes ready-made label definitions for common use cases. These pre-built options let you recognize and extract information from standard label types without creating custom configurations: ### Example: Price label Use the `LabelCaptureSettings` builder to configure a pre-built label definition for price labels, such as those found in retail environments: ![Price Label Example](/img/slc/price-label.png) ```js const settings = LabelCaptureSettings.builder() .addLabel(LabelDefinition.createPriceCaptureDefinition("price-label")) .build(); ``` ## Custom Labels If Smart Label Capture’s pre-built options don’t fit your needs, define a custom label instead. Custom labels can combine your own fields with any of the available pre-built ones. :::tip The following characters are recognized: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ()-./:,$¶"`. ::: ### Custom Fields There are two types of custom fields you can define: The following methods are available to configure custom fields: | Method | Optional | Description | |--------|----------|-------------| | `valueRegexes` | No | The regex patterns that identify the target string in the scanned content. | | `anchorRegexes` | Yes | Used to specify keywords or phrases that help identify the context of the field. This is particularly useful when the label contains multiple fields that could match the same pattern (e.g., when both packaging and expiry dates are present). | | `symbologies` | No | The barcode symbologies to match for barcode fields. This is important for ensuring that the field only captures data from specific barcode types, enhancing accuracy and relevance. | | `isOptional` | Yes | Whether the field is optional or mandatory. This is helpful when certain fields may not be present on every scan. | #### Example: Fish Shipping Box This example shows how to create a custom label definition for a fish shipping box, which includes fields for barcode and batch number. ![Fish Shipping Box Example](/img/slc/fish-shipping-box.png) ```js const settings = LabelCaptureSettings.builder() .addLabel(LabelDefinition.builder() .addCustomBarcode() .setSymbologies([Symbology.code128]) .buildFluent("barcode-field") .addCustomText() .setAnchorRegexes(["Batch"]) .setValueRegexes(["FZ\\d{5,10}"]) .setOptional(true) .buildFluent("batch-number-field") .buildFluent("shipping-label")) .build(); ``` ### Pre-built Fields You can also build your label using pre-built fields. These common fields speed up integration because their `valueRegexes`, `anchorRegexes`, and `symbologies` are already predefined. Customization of pre-built fields is done via the `valueRegexes`, `anchorRegexes`, and `isOptional` methods, which allow you to specify the expected format of the field data. :::tip All pre-built fields come with default `valueRegexes` and `anchorRegexes` that are suitable for most use cases. **Using either method is optional and will override the defaults**. The `resetAnchorRegexes` method can be used to remove the default `anchorRegexes`, allowing you to rely solely on the `valueRegexes` for detection. ::: import FeatureList from '@site/src/components/FeatureList'; #### Barcode Fields #### Price and Weight Fields #### Date and Custom Text Fields #### Example: Hard disk drive label This example demonstrates how to configure a label definition for a hard disk drive (HDD) label, which typically includes common fields like serial number and part number. ![Hard Disk Drive Label Example](/img/slc/hdd-label.png) ```js const settings = LabelCaptureSettings.builder() .addLabel(LabelDefinition.builder() .addSerialNumberBarcode() .buildFluent("serial-number") .addPartNumberBarcode() .buildFluent("part-number") .buildFluent("hdd-label")) .build(); ``` --- ## Adding AR Overlays # Adding AR Overlays In the previous section we covered how to vizualize the scan process using the `BarcodeBatchBasicOverlay`. In this section we will cover how to add custom AR overlays to your MatrixScan application. There are two ways to add custom AR overlays to your application: - Using the [`BarcodeBatchAdvancedOverlay`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) class, our ready-to-use implementation for view-based AR overlays. - Provide your own fully custom implementation by using the [`BarcodeBatchListener.didUpdateSession()`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) function to retrieve the tracking information and implement your own AR overlay. The first option is the easiest and recommended approach for most applications. It covers adding, removing, and animating the overlay’s views whenever needed and is also flexible enough to cover the majority of use cases. ## Using BarcodeBatchAdvancedOverlay As mentioned above, the advanced overlay combined with its [listener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) offers an easy way of adding augmentations to your [DataCaptureView](https://docs.scandit.com/data-capture-sdk/web/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). In this guide we will add a view above each barcode showing its content. First of all, create a new instance of [BarcodeBatchAdvancedOverlay](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) and add it to the [DataCaptureView](https://docs.scandit.com/data-capture-sdk/web/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView). ```js const overlay = await BarcodeBatchAdvancedOverlay.withBarcodeBatchForView( barcodeBatch, view ); ``` At this point, you have two options. - Add a [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) to the overlay. - Use the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) to specify the view, anchor and offset for each barcode. :::note The second way will take priority over the first one, which means that if a view for a barcode has been set using [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), the function [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) won’t be invoked for that specific barcode. ::: ### Using [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener) - You need to implement [BarcodeBatchAdvancedOverlayListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener). This interface’s methods are invoked every time a barcode is newly tracked. - [BarcodeBatchAdvancedOverlayListener.viewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.ViewForTrackedBarcode) asks for a view to animate on top of the barcode. Returning _null_ will show no view. - [BarcodeBatchAdvancedOverlayListener.anchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.AnchorForTrackedBarcode) asks how to anchor the view to the barcode through [Anchor](https://docs.scandit.com/data-capture-sdk/web/core/api/anchor.html#enum-scandit.datacapture.core.Anchor 'Anchor enum'). Be aware that it anchors the view’s center to the anchor point. To achieve anchoring the top of the view or the bottom etc. you will have to set an offset as explained in the next point. - [BarcodeBatchAdvancedOverlayListener.offsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchAdvancedOverlayListener.OffsetForTrackedBarcode) asks for an offset that is applied on the already anchored view. This offset is expressed through a [PointWithUnit](https://docs.scandit.com/data-capture-sdk/web/core/api/common.html#struct-scandit.datacapture.core.PointWithUnit). ```js import { PointWithUnit, MeasureUnit, NumberWithUnit, Anchor } from "@scandit/web-datacapture-core" import { TrackedBarcodeView } from "@scandit/web-datacapture-barcode" // ... overlay.listener = { viewForTrackedBarcode: (overlay, trackedBarcode) => { // Create and return the view you want to show for this tracked barcode. You can also return null, to have no view for this barcode. let element = document.createElement('span'); element.innerText = trackedBarcode.barcode.data; element.style.backgroundColor = '#FFFFFFFF'; return TrackedBarcodeView.withHTMLElement(element, null); }, anchorForTrackedBarcode: (overlay, trackedBarcode) => { // As we want the view to be above the barcode, we anchor the view's center to the top-center of the barcode quadrilateral. // Use the function 'offsetForTrackedBarcode' below to adjust the position of the view by providing an offset. return Anchor.TopCenter; }, offsetForTrackedBarcode: (overlay, trackedBarcode) => { // This is the offset that will be applied to the view. // You can use .fraction to give a measure relative to the view itself, the sdk will take care of transforming this into pixel size. // We now center horizontally and move up the view to make sure it's centered and above the barcode quadrilateral by half of the view's height. return new PointWithUnit( new NumberWithUnit(0, MeasureUnit.Fraction), new NumberWithUnit(-1, MeasureUnit.Fraction), ); }, }; ``` ### Using the setters in the [overlay](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay) The function [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) gives you access to a [session](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession), which contains all added, updated and removed tracked barcodes. From here you can create the view you want to display, and then call [BarcodeBatchAdvancedOverlay.setViewForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetViewForTrackedBarcode), [BarcodeBatchAdvancedOverlay.setAnchorForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetAnchorForTrackedBarcode) and [BarcodeBatchAdvancedOverlay.setOffsetForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-advanced-overlay.html#method-scandit.datacapture.barcode.batch.ui.BarcodeBatchAdvancedOverlay.SetOffsetForTrackedBarcode) ```js import { PointWithUnit, MeasureUnit, NumberWithUnit, Anchor } from "@scandit/web-datacapture-core" import { TrackedBarcodeView } from "@scandit/web-datacapture-barcode" // ... barcodeBatch.addListener({ didUpdateSession: (barcodeBatch, session) => { session.addedTrackedBarcodes.forEach(trackedBarcode => { let element = document.createElement('span'); element.innerText = trackedBarcode.barcode.data; element.style.backgroundColor = '#FFFFFFFF'; let trackedBarcodeView = TrackedBarcodeView.withHTMLElement(element, null); overlay.setViewForTrackedBarcode(trackedBarcodeView, trackedBarcode); overlay.setAnchorForTrackedBarcode(Anchor.TopCenter, trackedBarcode); overlay.setOffsetForTrackedBarcode( new PointWithUnit( new NumberWithUnit(0, MeasureUnit.Fraction), new NumberWithUnit(-1, MeasureUnit.Fraction) ), trackedBarcode); }); } }); ``` ## Provide your own custom implementation If you do not want to use the overlay, it is also possible to add augmented reality features based on the tracking identifier and the [quadrilateral](https://docs.scandit.com/data-capture-sdk/web/core/api/common.html#struct-scandit.datacapture.core.Quadrilateral) coordinates that every tracked barcode has. Below are some pointers. - Set a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) on the barcode tracking - In the [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) function fetch the [added](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.AddedTrackedBarcodes) and [removed](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-session.html#property-scandit.datacapture.barcode.batch.BarcodeBatchSession.RemovedTrackedBarcodes) tracked barcodes. - Create and show the views for the added barcodes. - Remove the views for the lost barcodes. - Add a method that is called 60fps when [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) is enabled. In this method, for each [TrackedBarcode](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/tracked-barcode.html#class-scandit.datacapture.barcode.batch.TrackedBarcode) on-screen, update the position based on [TrackedBarcode.location](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location). Please note that there is no need to animate the change of location, the change of position will happen frequently enough that the view will look as it is animated. :::note The frame coordinates from [TrackedBarcode.location](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/tracked-barcode.html#property-scandit.datacapture.barcode.batch.TrackedBarcode.Location) need to be mapped to view coordinates, using [DataCaptureView.viewQuadrilateralForFrameQuadrilateral()](https://docs.scandit.com/data-capture-sdk/web/core/api/ui/data-capture-view.html#method-scandit.datacapture.core.ui.DataCaptureView.MapFrameQuadrilateralToView). ::: ```js didUpdateSession: (barcodeBatch, session) => { session.removedTrackedBarcodes.map((lostTrackIdentifier) => { // You now know the identifier of the tracked barcode that has been lost. // Usually here you would remove the views associated. }); session.addedTrackedBarcodes.map((trackedBarcode) => { // Fixed identifier for the tracked barcode. const trackingIdentifier = trackedBarcode.identifier; // Current location of the tracked barcode. const location = trackedBarcode.location; view .viewQuadrilateralForFrameQuadrilateral(location) .then((quadrilateral) => { // You now know the location of the tracked barcode. }); }); }; ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan to your application. The general steps are: - [Create the Data Capture Context](#create-the-data-capture-context) initialized with your license key. - [Configure the Barcode Batch Mode](#configure-the-barcode-batch-mode) with the symbologies you want to read. - [Use the Built-in Camera](#use-the-built-in-camera) as the frame source. - [Use a Capture View to Visualize the Scan Process](#use-a-capture-view-to-visualize-the-scan-process) by adding a basic overlay for visual feedback. - [Get Barcode Batch Feedback](#get-barcode-batch-feedback) by registering an overlay listener. - [Disable Barcode Batch](#disabling-barcode-batch) when it is no longer needed. ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ### Improve runtime performance by enabling browser multithreading You can achieve better performance by enabling multithreading in any browser that supports it. Check the [Requirements Page](../../system-requirements) to know the minimum versions that can take advantage of multithreading. To enable multithreading you must set your site to be [crossOriginIsolated](https://developer.mozilla.org/en-US/docs/Web/API/crossOriginIsolated/). This will enable the SDK to use multithreading and significantly boost performance. If the environment supports it the SDK will automatically use multithreading. You can programmatically check for multithreading support using [BrowserHelper.checkMultithreadingSupport()](https://docs.scandit.com/data-capture-sdk/web/core/api/web/browser-compatibility.html#method-scandit.datacapture.core.BrowserHelper.CheckMultithreadingSupport). :::important Multithreading is particularly critical for MatrixScan as it significantly improves frame processing speed and tracking accuracy. Be sure to configure it correctly following this [tutorial](https://web.dev/coop-coep/). You can also check this [guide to enable cross-origin isolation](https://web.dev/cross-origin-isolation-guide/) and [safely reviving shared memory](https://hacks.mozilla.org/2020/07/safely-reviving-shared-memory/). ::: #### Verify multithreading is enabled You can verify that multithreading is working correctly by checking the cross-origin isolation status: ```js import { BrowserHelper } from "@scandit/web-datacapture-core"; // Whether or not the browser supports SharedArrayBuffer, the page is served to be crossOriginIsolated and has support for nested web workers. const supportsMultithreading = await BrowserHelper.checkMultithreadingSupport(); if (supportsMultithreading) { console.log("Multithreading is enabled and working!"); } else { console.warn("Multithreading is not available. Check your cross-origin headers."); } ``` #### Configure cross-origin headers To enable cross-origin isolation, you need to set specific HTTP headers **on your HTML page** (not on the SDK files). The headers you need depend on whether you're self-hosting or using a CDN: :::warning CDN vs Self-Hosting If you're loading the SDK from a CDN (jsDelivr, UNPKG, etc.), you should use `Cross-Origin-Embedder-Policy: credentialless` instead of `require-corp` to avoid blocking cross-origin resources. Alternatively, **we strongly recommend self-hosting the SDK files** when using multithreading for better reliability and to avoid potential CDN CORS/CORP issues. ::: **Choose the appropriate header configuration:** - **If self-hosting the SDK**: Use `Cross-Origin-Embedder-Policy: require-corp` - **If using a CDN**: Use `Cross-Origin-Embedder-Policy: credentialless` (requires modern browsers) Below are examples for common server setups: import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; Add these headers to your Nginx configuration file (usually in `/etc/nginx/sites-available/` or within a `server` block): **For self-hosted SDK:** ```nginx server { # ... other configuration ... location / { add_header Cross-Origin-Embedder-Policy "require-corp" always; add_header Cross-Origin-Opener-Policy "same-origin" always; # ... other directives ... } } ``` **For CDN-hosted SDK:** ```nginx server { # ... other configuration ... location / { add_header Cross-Origin-Embedder-Policy "credentialless" always; add_header Cross-Origin-Opener-Policy "same-origin" always; # ... other directives ... } } ``` After making changes, reload Nginx: ```sh sudo nginx -t && sudo nginx -s reload ``` Add these headers to your `.htaccess` file or Apache configuration: **For self-hosted SDK:** ```apache Header set Cross-Origin-Embedder-Policy "require-corp" Header set Cross-Origin-Opener-Policy "same-origin" ``` **For CDN-hosted SDK:** ```apache Header set Cross-Origin-Embedder-Policy "credentialless" Header set Cross-Origin-Opener-Policy "same-origin" ``` Make sure `mod_headers` is enabled: ```sh sudo a2enmod headers sudo systemctl restart apache2 ``` For Express.js applications, add the headers using middleware: **For self-hosted SDK:** ```javascript const express = require("express"); const app = express(); // Add cross-origin isolation headers app.use((req, res, next) => { res.setHeader("Cross-Origin-Embedder-Policy", "require-corp"); res.setHeader("Cross-Origin-Opener-Policy", "same-origin"); next(); }); // ... rest of your app configuration ... app.listen(3000); ``` **For CDN-hosted SDK:** ```javascript const express = require("express"); const app = express(); // Add cross-origin isolation headers app.use((req, res, next) => { res.setHeader("Cross-Origin-Embedder-Policy", "credentialless"); res.setHeader("Cross-Origin-Opener-Policy", "same-origin"); next(); }); // ... rest of your app configuration ... app.listen(3000); ``` For Vite projects, create a custom plugin in your `vite.config.ts`: **For self-hosted SDK:** ```typescript import { defineConfig, type PluginOption } from 'vite'; function crossOriginIsolation(): PluginOption { return { name: 'vite-plugin-cross-origin-isolation', configureServer: (server) => { server.middlewares.use((_req, res, next) => { res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp'); res.setHeader('Cross-Origin-Opener-Policy', 'same-origin'); next(); }); }, configurePreviewServer: (server) => { server.middlewares.use((_req, res, next) => { res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp'); res.setHeader('Cross-Origin-Opener-Policy', 'same-origin'); next(); }); }, }; } export default defineConfig({ plugins: [crossOriginIsolation()], // ... other config }); ``` **For CDN-hosted SDK:** ```typescript import { defineConfig, type PluginOption } from 'vite'; function crossOriginIsolation(): PluginOption { return { name: 'vite-plugin-cross-origin-isolation', configureServer: (server) => { server.middlewares.use((_req, res, next) => { res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless'); res.setHeader('Cross-Origin-Opener-Policy', 'same-origin'); next(); }); }, configurePreviewServer: (server) => { server.middlewares.use((_req, res, next) => { res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless'); res.setHeader('Cross-Origin-Opener-Policy', 'same-origin'); next(); }); }, }; } export default defineConfig({ plugins: [crossOriginIsolation()], // ... other config }); ``` This plugin configures headers for both `vite dev` (development) and `vite preview` (production preview) modes. Create a `_headers` file in your publish directory (usually `public/` or `dist/`): **For self-hosted SDK:** ``` /* Cross-Origin-Embedder-Policy: require-corp Cross-Origin-Opener-Policy: same-origin ``` **For CDN-hosted SDK:** ``` /* Cross-Origin-Embedder-Policy: credentialless Cross-Origin-Opener-Policy: same-origin ``` Add the headers to your `vercel.json` configuration file: **For self-hosted SDK:** ```json { "headers": [ { "source": "/(.*)", "headers": [ { "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }, { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" } ] } ] } ``` **For CDN-hosted SDK:** ```json { "headers": [ { "source": "/(.*)", "headers": [ { "key": "Cross-Origin-Embedder-Policy", "value": "credentialless" }, { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" } ] } ] } ``` Add the headers in your `Program.cs` or `Startup.cs`: **For self-hosted SDK:** ```csharp app.Use(async (context, next) => { context.Response.Headers.Add("Cross-Origin-Embedder-Policy", "require-corp"); context.Response.Headers.Add("Cross-Origin-Opener-Policy", "same-origin"); await next(); }); ``` **For CDN-hosted SDK:** ```csharp app.Use(async (context, next) => { context.Response.Headers.Add("Cross-Origin-Embedder-Policy", "credentialless"); context.Response.Headers.Add("Cross-Origin-Opener-Policy", "same-origin"); await next(); }); ``` Or use middleware in `Program.cs` (change the COEP value as needed): ```csharp app.UseMiddleware(); // Middleware class: public class CrossOriginIsolationMiddleware { private readonly RequestDelegate _next; private readonly string _coepValue; // "require-corp" or "credentialless" public CrossOriginIsolationMiddleware(RequestDelegate next, string coepValue = "require-corp") { _next = next; _coepValue = coepValue; } public async Task InvokeAsync(HttpContext context) { context.Response.Headers.Add("Cross-Origin-Embedder-Policy", _coepValue); context.Response.Headers.Add("Cross-Origin-Opener-Policy", "same-origin"); await _next(context); } } ``` :::note **Important notes:** - After configuring the headers, clear your browser cache and restart your development server to ensure the new headers take effect. - `Cross-Origin-Embedder-Policy: credentialless` requires Chrome 96+, Edge 96+, or other Chromium-based browsers. For older browser support, self-hosting with `require-corp` is more reliable. - Verify your configuration using `BrowserHelper.checkMultithreadingSupport()` - it should return `true` if multithreading is properly enabled (see [Verify multithreading is enabled](#verify-multithreading-is-enabled) above). - If you see CORS errors after enabling these headers, verify that all external resources (fonts, analytics, etc.) either use CORS or are self-hosted. ::: ### Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Create the Data Capture Context The first step to add capture capabilities to your application is to create a new [data capture context](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). ```js import { DataCaptureContext } from "@scandit/web-datacapture-core"; import { barcodeCaptureLoader } from "@scandit/web-datacapture-barcode"; const context = await DataCaptureContext.forLicenseKey('-- ENTER YOUR SCANDIT LICENSE KEY HERE --', { libraryLocation: new URL('library/engine/', document.baseURI).toString(), moduleLoaders: [barcodeCaptureLoader()], }); ``` ## Configure the Barcode Batch Mode The main entry point for the Barcode Batch Mode is the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) object. It is configured through [BarcodeBatchSettings](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-settings.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSettings) and allows you to register one or more [listeners](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) that will get informed whenever a new frame has been processed. Most of the time, you will not need to implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener), instead you will add a [BarcodeBatchBasicOverlay](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay) and implement a [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener). For this tutorial, we will setup Barcode Batch for tracking QR codes. ```js import { BarcodeBatchSettings, Symbology } from "@scandit/web-datacapture-barcode"; const settings = new BarcodeBatchSettings(); settings.enableSymbologies([Symbology.QR]); ``` Next, create a [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance with the data capture context and the settings initialized in the previous steps: ```js import { BarcodeBatch } from "@scandit/web-datacapture-barcode"; const barcodeBatch = await BarcodeBatch.forContext(context, settings); ``` ## Use the Built-in Camera The data capture context supports using different frame sources to perform recognition on. Most applications will use the built-in camera of the device, e.g. the world-facing camera of a device. The remainder of this tutorial will assume that you use the built-in camera. When using the built-in camera there are recommended settings for each capture mode. These should be used to achieve the best performance and user experience for the respective mode. The following couple of lines show how to get the recommended settings and create the camera from it: ```js import { Camera } from "@scandit/web-datacapture-core"; import { BarcodeBatch } from "@scandit/web-datacapture-barcode"; const camera = Camera.pickBestGuess(); const cameraSettings = BarcodeBatch.recommendedCameraSettings; await camera.applySettings(cameraSettings); ``` Because the frame source is configurable, the data capture context must be told which frame source to use. This is done with a call to [DataCaptureContext.setFrameSource()](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#method-scandit.datacapture.core.DataCaptureContext.SetFrameSourceAsync): ```js await context.setFrameSource(camera); ``` The camera is off by default and must be turned on. This is done by calling [FrameSource.switchToDesiredState()](https://docs.scandit.com/data-capture-sdk/web/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [FrameSourceState.On](https://docs.scandit.com/data-capture-sdk/web/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.On): ```js import { FrameSourceState } from "@scandit/web-datacapture-core"; [...] await camera.switchToDesiredState(FrameSourceState.On); ``` ## Use a Capture View to Visualize the Scan Process When using the built-in camera as frame source, you will typically want to display the camera preview on the screen together with UI elements that guide the user through the capturing process. To do that, add a [DataCaptureView](https://docs.scandit.com/data-capture-sdk/web/core/api/ui/data-capture-view.html#class-scandit.datacapture.core.ui.DataCaptureView) to your view hierarchy: ```js import { DataCaptureView } from "@scandit/web-datacapture-core"; const view = await DataCaptureView.forContext(context); view.connectToElement(htmlElement); ``` To visualize the results of Barcode Batch, first you need to add the following [overlay](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay): ```js import { BarcodeBatchBasicOverlay } from "@scandit/web-datacapture-barcode"; const overlay = await BarcodeBatchBasicOverlay.withBarcodeBatchForView( barcodeBatch, view ); ``` Once the overlay has been added, you should implement the [BarcodeBatchBasicOverlayListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#interface-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener) interface. The method [BarcodeBatchBasicOverlayListener.brushForTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.BrushForTrackedBarcode) is invoked every time a new tracked barcode appears and it can be used to set a [brush](https://docs.scandit.com/data-capture-sdk/web/core/api/ui/brush.html#class-scandit.datacapture.core.ui.Brush) that will be used to highlight that specific barcode in the [overlay](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-basic-overlay.html#class-scandit.datacapture.barcode.batch.ui.BarcodeBatchBasicOverlay). ```js overlay.listener = { brushForTrackedBarcode: (overlay, trackedBarcode) => { // Return a custom Brush based on the tracked barcode. }, }; ``` If you would like to make the highlights tappable, you need to implement the [BarcodeBatchBasicOverlayListener.didTapTrackedBarcode()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-batch-basic-overlay-listener.html#method-scandit.datacapture.barcode.batch.ui.IBarcodeBatchBasicOverlayListener.OnTrackedBarcodeTapped) method. ```js overlay.listener = { didTapTrackedBarcode: (overlay, trackedBarcode) => { // A tracked barcode was tapped. }, }; ``` ## Get Barcode Batch Feedback Barcode Batch, unlike Barcode Capture, doesn’t emit feedback (sound or vibration) when a new barcode is recognized. However, you may implement a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener) to provide a similar experience. Below, we use the default [Feedback](https://docs.scandit.com/data-capture-sdk/web/core/api/feedback.html#class-scandit.datacapture.core.Feedback), but you may configure it with your own sound or vibration if you want. Next, use this [feedback](https://docs.scandit.com/data-capture-sdk/web/core/api/feedback.html#class-scandit.datacapture.core.Feedback) in a [BarcodeBatchListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-listener.html#interface-scandit.datacapture.barcode.batch.IBarcodeBatchListener): ```js import { Feedback } from "@scandit/web-datacapture-core"; const feedback = Feedback.defaultFeedback; const feedbackListener = { didUpdateSession: (barcodeBatch, session) => { if (session.addedTrackedBarcodes.length > 0) { feedback.emit(); } }, }; ``` [BarcodeBatchListener.didUpdateSession()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-listener.html#method-scandit.datacapture.barcode.batch.IBarcodeBatchListener.OnSessionUpdated) is invoked for every processed frame. The [session](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch-session.html#class-scandit.datacapture.barcode.batch.BarcodeBatchSession) parameter contains information about the currently tracked barcodes, in particular, the newly recognized ones. We check if there are any and if so, we emit the feedback. As the last step, register the listener responsible for emitting the feedback with the [BarcodeBatch](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch.html#class-scandit.datacapture.barcode.batch.BarcodeBatch) instance. ```js barcodeBatch.addListener(feedbackListener); ``` ## Disabling Barcode Batch To disable barcode tracking call [BarcodeBatch.setEnabled()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-batch.html#method-scandit.datacapture.barcode.batch.BarcodeBatch.SetEnabled) passing _false_. No more frames will be processed _after_ the change. However, if a frame is currently being processed, this frame will be completely processed and deliver any results/callbacks to the registered listeners. Note that disabling the capture mode does not stop the camera, the camera continues to stream frames until it is turned off or switched to standby by calling [SwitchToDesiredState](https://docs.scandit.com/data-capture-sdk/web/core/api/frame-source.html#method-scandit.datacapture.core.IFrameSource.SwitchToDesiredStateAsync) with a value of [StandBy](https://docs.scandit.com/data-capture-sdk/web/core/api/frame-source.html#value-scandit.datacapture.core.FrameSourceState.Standby). ### Limitations[](#limitations 'Permalink to this headline') MatrixScan does not support the following symbologies: - DotCode - MaxiCode - All postal codes (KIX, RM4SCC) :::important Barcode Batch needs browser multithreading to run. Check the minimum browser support in the [Requirements Page](../../system-requirements) and how to enable it in [Improve runtime performance by enabling browser multithreading](#improve-runtime-performance-by-enabling-browser-multithreading), above. ::: --- ## About MatrixScan Batch # About MatrixScan Batch import AboutMatrixScan from '../../../partials/intro/_about-matrixscan.mdx' --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan AR to your application. Implementing MatrixScan AR involves two primary elements: - Barcode AR: The data capture mode that is used for scanning functionality. - A Barcode AR View: The pre-built UI elements used to highlight desired scanned items. The general steps are: - [Create a Data Capture Context](#create-a-data-capture-context) initialized with your license key. - [Configure the Barcode AR Mode](#configure-the-barcode-ar-mode) with the symbologies you want to track. - [Set up the BarcodeArView](#setup-the-barcodearview) to render the AR overlay. - [Register a Listener](#register-a-listener) to receive annotation events. - [Register a listener for highlights click](#register-a-listener-for-highlights-click) to handle taps on highlighted barcodes. - [Start Scanning](#start-scanning). ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new Data Capture Context. Sdk must be configured first with a valid Scandit Data Capture SDK license key. ```typescript const context = await DataCaptureContext.forLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --", { libraryLocation: new URL("library/engine/", document.baseURI).toString(), moduleLoaders: [barcodeCaptureLoader({ highEndBlurryRecognition: false })], }); const dataCaptureView = new DataCaptureView(); // #root element should be present in .html document dataCaptureView.connectToElement(document.getElementById("root")); await dataCaptureView.setContext(context); ``` ## Configure the Barcode AR Mode The main entry point for the Barcode AR Mode is the `BarcodeAr` object. You can configure the supported Symbologies through its [`BarcodeArSettings`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-ar-settings.html), and set up the list of items that you want MatrixScan AR to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```typescript const settings = new BarcodeArSettings(); settings.enableSymbologies([Symbology.EAN13UPCA]); const barcodeAr = await BarcodeAr.forContext(context, settings); ``` ## Setup the `BarcodeArView` MatrixScan AR’s built-in AR user interface includes buttons and overlays that guide the user through the scan and check process. By adding a [`BarcodeArView`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-ar-view.html#class-scandit.datacapture.barcode.check.ui.BarcodeArView), the scanning interface is added automatically to your application. The `BarcodeArView` is where you provide the [`highlightProvider`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.HighlightProvider) and/or [`annotationProvider`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-ar-view.html#property-scandit.datacapture.barcode.check.ui.BarcodeArView.AnnotationProvider) to supply the highlight and annotation information for the barcodes to be checked. If *null*, a default highlight is used and no annotations are provided. The `BarcodeArView` appearance can be customized through [`BarcodeArViewSettings`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-ar-view-settings.html#class-scandit.datacapture.barcode.check.ui.BarcodeArViewSettings), and the corresponding settings for your desired highlights and/or annotations, to match your application’s look and feel. The following settings can be customized: - Audio and haptic feedback - Torch button visibility and its position - Switch camera button visibility and its position - Zoom control visibility and its position - The size, colors, and styles of the highlight and annotation overlays ```typescript const viewSettings = new BarcodeArViewSettings(); viewSettings.soundEnabled = true; viewSettings.hapticEnabled = true; ``` Next, create a `BarcodeArView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodeArView` is automatically added to the provided parent view. ```typescript let barcodeArView = await BarcodeArView.createWithSettings(dataCaptureView, context, barcodeAr, viewSettings); // OR just create to use the default view settings and camera settings let barcodeArView = await BarcodeArView.create(dataCaptureView, context, barcodeAr); ``` ## Register a Listener If you want a callback when an annotation is tapped, you can register a [BarcodeArInfoAnnotationListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-ar-info-annotation.html#interface-scandit.datacapture.barcode.ar.ui.IBarcodeArInfoAnnotationListener). ```typescript barcodeArView.annotationProvider= { annotationForBarcode(barcode: Barcode, callback: (annotation: BarcodeArAnnotation) => void): void { const annotationArInfoListener: BarcodeArInfoAnnotationListener = { onInfoAnnotationTapped: (annotation) => { // Handle the tapped annotation } }; const infoAnnotation = BarcodeArInfoAnnotation.create(barcode); infoAnnotation.isEntireAnnotationTappable = true; //... other properties infoAnnotation.listener = annotationArInfoListener; callback(infoAnnotation); } }; ``` ## Register a listener for highlights click If you want a callback when an highlight is tapped, you can also register a `BarcodeArViewUiListener` ```typescript const barcodeArViewUiListener: BarcodeArViewUiListener = { didTapHighlightForBarcode(barcodeAr: BarcodeAr, barcode: Barcode, highlight: BarcodeArHighlight): void { // handle click on highlight } } barcodeArView.listener = barcodeArViewUiListener; ``` ## Start Scanning With everything configured, you can now start scanning: ```typescript await barcodeArView.start(); ``` --- ## About MatrixScan AR # About MatrixScan AR import AboutMatrixScanCheck from '../../../partials/intro/_about-matrixscan-ar.mdx' --- ## MatrixScan Count is not available on Web # MatrixScan Count is not available on Web The MatrixScan Count module is not available for the Web SDK. To view documentation for a platform that supports MatrixScan Count, use the framework switcher at the top of the page. --- ## MatrixScan Count is not available on Web # MatrixScan Count is not available on Web The MatrixScan Count module is not available for the Web SDK. To view documentation for a platform that supports MatrixScan Count, use the framework switcher at the top of the page. --- ## MatrixScan Count is not available on Web # MatrixScan Count is not available on Web The MatrixScan Count module is not available for the Web SDK. To view documentation for a platform that supports MatrixScan Count, use the framework switcher at the top of the page. --- ## Advanced Configurations # Advanced Configurations MatrixScan Find is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are multiple advanced settings available to further customize MatrixScan Find to best fit your needs. ## BarcodeFind Listener You may want more fine-grained knowledge over the different events happening during the life of the `BarcodeFind` mode, such as when the search starts, pauses, and stops. To do this, you can directly register a [`BarcodeFindListener`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-find-listener.html#interface-scandit.datacapture.barcode.find.IBarcodeFindListener) on the mode itself, keeping in mind that these listeners are called from a background thread. ```typescript barcodeFindMode.addListener({ didStartSearch: () => { // The mode was started }, didPauseSearch: (foundItems: BarcodeFindItem[]) => { // The mode was paused }, didStopSearch: (foundItems: BarcodeFindItem[]) => { // The mode was stopped after the finish button was clicked } }); ``` ## UI Customization The `BarcodeFindView` by default shows a set of UI elements, any of which can be optionally hidden: - Play/Pause button - Finish button - Searched items carousel - Guidance hints - Progress bar (hidden by default) Each of these elements can be shown or hidden as needed. For example: ```typescript barcodeFindView.setShouldShowCarousel(false); barcodeFindView.setShouldShowProgressBar(true); // … ``` --- ## Get Started # Get Started In this guide you will learn step-by-step how to add MatrixScan Find to your application. Implementing MatrixScan Find involves two primary elements: - Barcode Find: The data capture mode that is used for search and find functionality. - A Barcode Find View: The pre-built UI elements used to highlight found items. :::note MatrixScan Find is implemented via [`BarcodeFind`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-find.html#class-scandit.datacapture.barcode.find.BarcodeFind). ::: The general steps are: - Creating a new Data Capture Context instance - Configuring the Barcode Find Mode - Setup the Barcode Find View - Registering the Listener to be notified about found items ## Create a Data Capture Context The first step to add capture capabilities to your application is to create a new Data Capture Context with a valid Scandit Data Capture SDK license key. ```typescript const context = await DataCaptureContext.forLicenseKey("-- ENTER YOUR SCANDIT LICENSE KEY HERE --", { libraryLocation: new URL("library/engine/", document.baseURI).toString(), moduleLoaders: [barcodeCaptureLoader({ highEndBlurryRecognition: false })], }); const dataCaptureView = new DataCaptureView(); // #root element should be present in .html document dataCaptureView.connectToElement(document.getElementById("root")); await dataCaptureView.setContext(context); ``` ## Configure the Barcode Find Mode The main entry point for the Barcode Find Mode is the `BarcodeFind` object. You can configure the supported Symbologies through its [`BarcodeFindSettings`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/barcode-find-settings.html#class-scandit.datacapture.barcode.find.BarcodeFindSettings), and set up the list of items that you want MatrixScan Find to highlight. Here we configure it for tracking EAN13 codes, but you should change this to the correct symbologies for your use case. ```typescript const settings = new BarcodeFindSettings(); settings.enableSymbologies([Symbology.EAN13UPCA]); const barcodeFind = await BarcodeFind.forSettings(settings); ``` Next, create the list of items that will be actively searched for. We will also attach some optional information to the first item that can be used by the `BarcodeFindView` to display extra information: ```typescript const items: BarcodeFindItem[] = [] items.push( new BarcodeFindItem( new BarcodeFindItemSearchOptions("9783598215438"), new BarcodeFindItemContent("Mini Screwdriver Set", "(6-Piece)", null) ) ); items.push( new BarcodeFindItem( new BarcodeFindItemSearchOptions("9783598215414"), null // Item information is optional, used for display only ) ); ``` ## Setup the `BarcodeFindView` MatrixScan Find’s built-in AR user interface includes buttons and overlays that guide the user through the searching process. By adding a [`BarcodeFindView`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-find-view.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindView), the scanning interface is added automatically to your application. The `BarcodeFindView` appearance can be customized through [`BarcodeFindViewSettings`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-find-view-settings.html#class-scandit.datacapture.barcode.find.ui.BarcodeFindViewSettings) to match your application’s look and feel. For example, you can change the color of the dots that are overlaid on top of the items that are found and enable sound and haptic alerts. ```typescript const inListItemColorGreen = Color.fromHex("#00FF00"); const notInListItemColorRed = Color.fromHex("#FF0000"); const soundEnabled = true; const hapticEnabled = true; const viewSettings = new BarcodeFindViewSettings(inListItemColorGreen, notInListItemColorRed, soundEnabled, hapticEnabled); ``` Next, create a `BarcodeFindView` instance with the Data Capture Context and the settings initialized in the previous step. The `BarcodeFindView` is automatically added to the provided parent view. ```typescript let barcodeFindView = await BarcodeFindView.createWithSettings(dataCaptureView, context, barcodeFind, viewSettings); // OR just create to use the default view settings and camera settings let barcodeFindView = await BarcodeFindView.create(dataCaptureView, context, barcodeFind); // finally set the item list to be searched await barcodeFind.setItemList(items); ``` ## Register The Listener The `BarcodeFindView` displays a **Finish** button next to its shutter button. Register a [BarcodeFindViewUiListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/barcode-find-view.html#interface-scandit.datacapture.barcode.find.ui.IBarcodeFindViewUiListener) to be notified what items have been found once the finish button is pressed. ```typescript barcodeFindView.setListener({ didTapFinishButton: (foundItems: BarcodeFindItem[]) => { // do something with found items. // maybe relaunch the search } }); ``` ## Start Searching With everything configured, you can now start searching for items. This is done by calling `barcodeFindView.startSearching()`. ```typescript barcodeFindView.startSearching(); ``` This is the equivalent of pressing the Play button programmatically. It will start the search process, turn on the camera, and hide the item carousel. --- ## About MatrixScan Find # About MatrixScan Find import AboutFind from '../../../partials/intro/_about-matrixscan-find.mdx' --- ## MatrixScan Pick is not available on Web # MatrixScan Pick is not available on Web The MatrixScan Pick module is not available for the Web SDK. To view documentation for a platform that supports MatrixScan Pick, use the framework switcher at the top of the page. --- ## MatrixScan Pick is not available on Web # MatrixScan Pick is not available on Web The MatrixScan Pick module is not available for the Web SDK. To view documentation for a platform that supports MatrixScan Pick, use the framework switcher at the top of the page. --- ## MatrixScan Pick is not available on Web # MatrixScan Pick is not available on Web The MatrixScan Pick module is not available for the Web SDK. To view documentation for a platform that supports MatrixScan Pick, use the framework switcher at the top of the page. --- ## Migrate from 5.x to 6.x import Migrate5To6 from '../../partials/_migrate-5-to-6.mdx'; --- ## Migrate from 6.x to 7.x import Migrate6To7 from '../../partials/_migrate-6-to-7.mdx'; --- ## Migrate from 7.x to 8.x import Migrate7To8 from '../../partials/_migrate-7-to-8.mdx'; --- ## Get Started # Get Started The Parser parses data strings (as found in barcodes) into a set of key-value mappings. These data formats are supported: - [Health Industry Bar Code (HIBC)](https://docs.scandit.com/data-capture-sdk/web/parser/hibc.html) - [GS1 Application Identifier system](https://docs.scandit.com/data-capture-sdk/web/parser/gs1ai.html) - [Swiss QR Codes](https://docs.scandit.com/data-capture-sdk/web/parser/swissqr.html) - [VIN Vehicle Identification Number](https://docs.scandit.com/data-capture-sdk/web/parser/vin.html) - [IATA Bar Coded Boarding Pass (BCBP)](https://docs.scandit.com/data-capture-sdk/web/parser/iata-bcbp.html) - [Electronic Product Code (EPC)](https://docs.scandit.com/data-capture-sdk/web/parser/epc.html) More data formats will be added in future releases. Please contact us if the data format you are using is not yet supported, or you want to use the parser on a currently unsupported platform. ## Prerequisites Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out [this guide](../add-sdk.md). :::note You can retrieve your Scandit Data Capture SDK license key by signing in to [your Scandit account](https://ssl.scandit.com/dashboard/sign-in). ::: First of all, include the ScanditParser library and its dependencies to your project, if any. ### Internal dependencies import InternalDependencies from '../../../partials/get-started/_internal-deps.mdx'; ## Installation ### Install via package manager To add the packages via your preferred package manager, run the following command from your project's root folder: ```sh npm install --save @scandit/web-datacapture-core @scandit/web-datacapture-barcode @scandit/web-datacapture-parser ``` ```sh yarn add @scandit/web-datacapture-core @scandit/web-datacapture-barcode @scandit/web-datacapture-parser ``` ```sh pnpm add @scandit/web-datacapture-core @scandit/web-datacapture-barcode @scandit/web-datacapture-parser ``` ```sh bun add @scandit/web-datacapture-core @scandit/web-datacapture-barcode @scandit/web-datacapture-parser ``` ```sh deno add npm:@scandit/web-datacapture-core npm:@scandit/web-datacapture-barcode npm:@scandit/web-datacapture-parser ``` :::note You can also specify a version @``. ::: ### Install via CDN You can consume the packages through a CDN like [JSDelivr](https://www.jsdelivr.com/?query=%40scandit%2Fweb-datacapture-). :::warning Important considerations when using CDNs For important information about CDN risks and recommendations for production environments, see [Install via CDN](/sdks/web/add-sdk/#install-via-cdn). ::: ## Basic CDN Example ```html Scandit Parser CDN Sample { "imports": { "@scandit/web-datacapture-core": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-core@8/build/js/index.js", "@scandit/web-datacapture-barcode": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-barcode@8/build/js/index.js", "@scandit/web-datacapture-parser": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-parser@8/build/js/index.js", "@scandit/web-datacapture-barcode/": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-barcode@8/", "@scandit/web-datacapture-core/": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-core@8/", "@scandit/web-datacapture-parser/": "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-parser@8/" } } html, body { margin: 0; padding: 0; height: 100%; } #app { height: 100%; } #resultDialog { max-width: 600px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } #resultDialog::backdrop { background-color: rgba(0, 0, 0, 0.5); } #resultDialog pre { background-color: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; padding: 16px; overflow-x: auto; max-height: 400px; font-size: 12px; margin: 0; } #resultDialog h2 { margin-top: 0; } #resultDialog button { background-color: #007bff; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; margin-top: 16px; } #resultDialog button:hover { background-color: #0056b3; } import { DataCaptureContext, Logger } from '@scandit/web-datacapture-core'; import { barcodeCaptureLoader } from '@scandit/web-datacapture-barcode'; import { parserLoader, Parser, ParserDataFormat } from "@scandit/web-datacapture-parser"; const context = await DataCaptureContext.forLicenseKey('-- ENTER LICENSE KEY HERE --', { libraryLocation: "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-barcode@8/sdc-lib/", moduleLoaders: [ barcodeCaptureLoader({ libraryLocation: "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-barcode@8/sdc-lib/" }), parserLoader({ libraryLocation: "https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-parser@8/sdc-lib/" })], logLevel: Logger.Level.Quiet, }); const parserIata = await Parser.forFormat(context, ParserDataFormat.IATA_BCBP); const encodedData = "M1BLEAH/ZZZZZZ EU3TAVO LCAZRHCY 0350 259Y009A0131 348>5180 BCY 2A07824010159820 CY N"; const parsed = await parserIata.parseStringToJson(encodedData); console.log("the parsed data", parsed); // Display the parsed data in a dialog const dialog = document.getElementById('resultDialog'); const resultsContent = document.getElementById('resultsContent'); resultsContent.textContent = JSON.stringify(parsed, null, 2); dialog.showModal(); Parsed Data Close ``` --- ## Release Notes ## 8.5.0-beta.1 **Released**: June 18, 2026 ### New Features #### Barcode * Added the SelectionMode API to replace the SparkScan target-mode APIs and `ScanIntention.smartSelection`: Set `selectionMode` (off/on/auto) in the `BarcodeCaptureSettings` and `SparkScanSettings` to control whether an aimed-at barcode is scanned automatically or requires explicit selection. * Added `logoStyle` and `logoAnchor` customization properties to `BarcodeArView`, `BarcodeCountView`, `BarcodeFindView`, `BarcodePickView`, and `BarcodeSequenceView`. #### Id * Added Irish Garda Age Card as `RegionSpecificSubtype.IrelandAgeCard`. * Added a new `PassportType` property to `MrzResult`. * Added double-sided support for the Oman residence card. * Added single-sided support for extraction of issue date and birth date from the 2025 NYC Municipal ID. * Added Web support for: Australia ACT Driver's License, USA Oklahoma Driver's License, and USA Puerto Rico ID. #### Smart Label Capture * Extended VIN label capture to also scan Code 128 barcodes (in addition to QR, Code 39, and Data Matrix) via `createVinLabelDefinition()`. * Extended LabelCapture to accept label definitions where both "barcode" and "text" field types use the "semantics" feature simultaneously; previously this was restricted to only one field type at a time. * Improved the add/remove lifecycle handling of the validation flow overlay. ### Performance Improvements #### Barcode * Enhanced detection of low-resolution QR codes is now enabled by default, improving scan rates for challenging QR codes with degraded print quality or unfavorable capture conditions. * Improved scanning of micro-QR codes affected by quiet zone violations and perspective distortion. #### Smart Label Capture * Improved Receipt Scanning efficiency by optimizing receipt image processing before extraction. #### Core * Improved worker loading. ### Behavioral Changes #### Barcode * Reduced Code 128 minimum symbol count from 6 to 4; short codes (4 & 5 symbols) use stricter matching rules than longer codes. To explicitly exclude short codes, disable symbol counts 4 & 5 via `sc_symbology_settings_set_active_symbol_counts()` for Code 128. Note that if you previously enabled short code scanning, more strict settings are now in effect to reduce the chance of false positives, which are more likely for very short codes. * Tightened Code 39 false positive filter thresholds by default; to restore the previous behavior, enable the `relaxed` extension on Code 39 via `sc_symbology_settings_set_extension_enabled()`. This is only advised when external validation measures are available, e.g. scanning against a known list of valid codes or when codes contain structured data. * Updated `SymbologyDescription.forIdentifier` to return `null` for unrecognized identifiers (e.g. `"EAN-8"` instead of `"ean8"`); previously such input was silently mapped to `Codabar`. ### Bug Fixes #### Barcode * Fixed a memory leak in item-based scanning. * Fixed BarcodeAR view settings not being taken into account. * Fixed recommended BarcodeAR camera settings not being applied correctly. * Fixed a `BarcodeFind` view issue where overlay dots were sometimes not rendered correctly after pausing. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. #### Id * Fixed an issue where cropped document images were rotated when Frame Image was also enabled. * Corrected the orientation of cropped Visa document images that were being rotated incorrectly when scanned using a single-frame image source. * Fixed parser handling of non-standard Surrey BC AAMVA barcodes that were incorrectly returning "Invalid Format". #### Smart Label Capture * Fixed a memory leak in LabelCapture. #### Core * Fixed the Web SDK camera preview expanding to full-screen in iOS WebViews by setting `playsinline` and `webkit-playsinline` attributes on the video element; the host `WKWebView` must also enable `allowsInlineMediaPlayback`. * Fixed a bug that caused the zoom notification to not be shown when using the `ZoomSwitchControl`. * Fixed a crash when the `DataCaptureContext` singleton was initialized more than once. * Fixed an issue that caused the torch to turn off after minimizing the browser or switching tabs. ### Deprecations #### Barcode * The SparkScan target-mode APIs and `ScanIntention.smartSelection` are deprecated in favour of selectionMode. ## 8.4.1 **Released**: June 23, 2026 ### Bug Fixes #### Barcode * Fixed BarcodeAR view settings not being taken into account. * Fixed recommended BarcodeAR camera settings not being applied correctly. * Fixed a memory leak in SparkScan when using the item-based API. #### Id * Fixed an issue where cropped document images were rotated when they are recovered using the getFrame API. #### Core * Fixed WebKit 26.x bugs causing pthreads WASM crashes (WebKit bug #303387) and SIMD corruption in barcode/ID scanning (Apple Radar 176035764) by pinning memory and disabling SIMD on affected versions. ## 8.4.0 **Released**: May 18, 2026 ### New Features #### Barcode * Added `dotRadius` property to `BarcodeBatchBasicOverlay` to allow customizing the size of dots when using the Dot overlay style. #### Id * Added support for reading the vehicle table on the back of New Zealand driving licences, with the latest expiry date returned; supported vehicle classes are 1–6, including L=learner and R=restricted variants. * Added support for new versions of USA, California – Driver's License; USA, North Carolina – Driver's License; USA, Texas – Driver's License; and USA, Oklahoma – Driver's License. #### Smart Label Capture * Added the `numberOfMandatoryInstances` property to the Web platform. #### Core * Redesigned `ZoomSwitchControl` to support multiple configurable zoom levels; the control now displays as a compact button that expands to show all available zoom levels, automatically filtered to those supported by the device hardware. * Added a new `PinchToZoom` gesture. * Introduced a new `ZoomListener` on the Camera object. * Added support for the `SwipeToZoom` gesture. * Added a default value to the `ZoomSwitchOrientation` enum. * Adjusted control colors for better visibility on dark and light backgrounds. * Fixed a bug where sound feedback was not correctly played in a multi-tab scenario. ### Performance Improvements #### Barcode * Improved Code 128 scan robustness for codes with uneven blur and geometric distortions. Available on all platforms except WebAssembly without SIMD and ARM without FP16. * Improved 1D barcode scanning speed and reduced false positives for linear symbologies. * Further improved scanning of square DataMatrix codes with damaged or occluded timing patterns. #### Core * Improved worker loading. ### Behavioral Changes #### Barcode * Smart Scan Intention now continuously adapts between Single Scan and Selection modes during a scanning session when Smart Scan Selection is enabled, switching back to Single Scan when the scene no longer requires Selection mode. Previously, once Selection mode was activated it remained active for the rest of the session. * Changed ITF scanning to reduce false positives by introducing checksum-dependent scoring. ITF has an optional checksum which is mandated to be enabled by many of the standards that use ITF as the data carrier. Starting with this release, checksum-passing ITF codes are scanned with more relaxed conditions than codes that don't pass the checksum test. This happens even if the optional mod 10 checksum isn't enabled. To disable this behavior, enable the `no_checksum_dependent_validation` symbology extension for the ITF symbology. * Removed the Abseil library dependency. * Reduced Code 39 false positives. #### Core * Updated mbedtls from version 3.6.5 to 3.6.6. * Updated the `CameraSwitchControl` and `TorchSwitchControl` UI. ### Bug Fixes #### Barcode * Fixed an issue where zoom notifications were not shown when zooming in and out. * Fixed an issue causing the SparkScan mini preview to have an incorrect size in landscape orientation. * Fixed an issue that caused the SparkScan camera to stop working when disposing the context and re-initializing it. * Fixed PDF417 macro block file ID decoding to correctly handle numeric formatting according to the ISO/IEC 15438:2015 specification. * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed an issue where the Smart Scan Selection aimer would become too small when scan-area margins restricted the visible scan area; the aimer is now sized relative to the view, keeping a consistent on-screen size regardless of margins. #### Id * Fixed an issue where the US Permanent Residence Card was not processed through the VizMrz flow. * Fixed an issue with browsers that don't support `createImageBitmap` in ID Capture. * Fixed an issue where AAMVA verification was being performed even when no AAMVA document types were enabled in the accepted documents. #### Smart Label Capture * Fixed a memory leak in LabelCapture * Fixed an issue where the validation flow viewfinder was not displayed. * Fixed a race condition in the validation flow. * Fixed an issue where adaptive scanning text was sometimes not correctly shown in the validation flow overlay. * Fixed a bug in the validation flow where input was not fully visible when focused in landscape orientation. * Fixed a bug that caused error messages in `DataCaptureView` to be rendered partially out-of-view. * Fixed a rare race condition in Label Capture. * Added `.asDate()` support to `ExpiryDate` and `PackingDate` label fields when the text is provided as manual input or as an Adaptive-Recognition-Engine response. * Fixed a bug where the receipt scanning overlay and validation flow overlay could not be used on the same LabelCapture mode instance. #### Core * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. * Fixed a bug where setting the same `DataCaptureContext` instance twice on a `DataCaptureView` would lead to a crash. ### Deprecations #### Core * Added `zoomLevels` property to `CameraSettings` and deprecated `zoomGestureZoomFactor`. * Deprecated `CameraFOVSwitchControl` in favor of `ZoomSwitchControl`. ## 8.3.1 **Released**: April 14, 2026 ### Bug Fixes #### Id * Fixed an issue with browsers that don't support `createImageBitmap` in ID Capture #### Smart Label Capture * Fixed the validation flow to accept dates in more formats when manually entered * Fixed a race condition in the validation flow #### Core * Fixed JavaScript syntax in the sdc-lib folder that was not correctly downleveled to respect the minimum browser version ## 8.3.0 **Released**: March 26, 2026 ### New Features #### Barcode * Added support for composite codes in SparkScan #### Id * Corrected Mexican Voter ID parent names to firstName and lastName * Added support for OCR scanning of the 2026 version of Victoria mobile driver licenses * Added IdCaptureSettings.anonymizeDefaultFields setting that controls whether the SDK applies default anonymization rules for specific document types and regions * US, EU/ Schengen + UK passports no longer fallback to MRZ only. Now, US, EU/ Schengen + UK passports must capture VIZ instead of returning MRZ values after the configurable timeout has elapsed. This applies to FullDocumentScanner or SingleSideScanner when both VIZ and MRZ zones are enabled. #### Smart Label Capture * Fixed a rare race condition * Fixed some issues with keyboard handling in Validation Flow ### Performance Improvements #### Barcode * Improved EAN8 false positive filtering in strict mode * Improved speed of MatrixScan Count scanning phase for mid- and high-end devices ### Bug Fixes #### Barcode * Fixed an issue that caused the SparkScan camera to stop working when disposing the context and re-initializing it. * Fixed an issue causing the SparkScan toolbar buttons to be aligned incorrectly. #### Id * Fixed BarcodeDictionary anonymization setting for iOS and Web * Fixed support for UAE Esaad card * Sanitized name fields on ACT driver license to split FullName and populate first and last name properties * Added support for scanning MRZ from the back of Argentinian DN when using `FullDocumentScanner` * Fixed misplaced MRZ anonymization on FullFrame images. #### Smart Label Capture * Fixed issue where the `LabelCaptureValidationFlowOverlay` sometimes did not reflect label capture settings when reused * Enhanced the `LabelCaptureValidationFlowOverlay` to resume when the mode is enabled and Validation Flow is paused. * Fixed camera being incorrectly paused while cloud backup started in Validation Flow * Fixed runtime error that sometimes occurred during cloud backup request when screen was tapped in validation flow #### Core * Fixed sound feedback playback in multi-tab scenarios * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. ## 8.2.1 **Released**: March 5, 2026 ### Bug Fixes #### Id * Corrected Mexican Voter ID parent names to map to firstName and lastName * Sanitized name fields on ACT DL. Splits FullName to populate first and last name properties #### Smart Label Capture * Fixed `LabelCaptureValidationFlowOverlay` not reflecting Label Capture settings if reused * Fixed `LabelCaptureValidationFlowOverlay` not correctly resuming if user changes view when in pause and comes back * Fixed some issues with keyboard handling in Validation Flow * Fixed camera being incorrectly paused while cloud backup started in Validation Flow * Fixed runtime error thrown in Validation Flow when screen was tapped while a cloud backup request was running * Fixed a rare race condition ## 8.2.0 **Released**: February 13, 2026 ### New Features #### Barcode * Stopped emitting vibration feedbacks when the scanner is stopped without user interaction #### Id * Enabled scanning of MRZ on the backside of several EU residence permits * Added extraction of a cropped document image from Passports and VISAs that do not support VIZ extraction * Added extraction of the date of birth from Romanian IDs #### Smart Label Capture * The Validation Flow, our ready‑to‑use workflow in Smart Label Capture for capturing and validating label data with minimal code, now features a completely redesigned user interface. The update improves ergonomics through a simplified API and highly requested customization options, making Smart Label Capture more intuitive and significantly reducing integration and customization effort across a wider range of use cases #### Core * Removed Howler.hs and JavaScript Cookie 3rd party dependencies ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Barcode * Improved the Smart Scan Intention logic for detecting main codes + five-digit add on codes. This improves the rate of complete main + add-on code pairs. * Fixed a bug where the torch control would be shown even if the torch was not supported * Fixed an issue where SparkScan would select the wrong camera * Fixed an issue where the SparkScanView was not being disposed correctly #### Id * Treated Puerto Rico driver licenses as AAMVA to enforce barcode capture with FullScanner * Fixed a bug that would cause Canada Northwest Territories driver license scans to be incomplete #### Core * Fixed an issue where in some webview scenarios the wrong back camera was selected on the iPhone Pro ### Deprecations #### Smart Label Capture * Deprecated some LabelCaptureValidationFlowSetting APIs: requiredFieldErrorText, missingFieldsHintText, manualInputButtonText, as those don't make sense anymore with the redesign of Validation Flow in 8.2 ## 8.1.5 **Released**: June 10, 2026 ### Bug Fixes #### Barcode * Fixed a memory leak in item-based scanning. #### Smart Label Capture * Fixed a memory leak in LabelCapture. ## 8.1.4 **Released**: April 21, 2026 ### Bug Fixes #### Barcode * Fixed a crash that could occur when scanning barcodes with the k-out-of-n filter enabled, if some detected barcodes were not subject to filtering. * Fixed a crash that occurred when the `DataCaptureContext` singleton was initialized more than once. #### Id * Fixed an issue with browsers that don't support `createImageBitmap` in ID Capture. ## 8.1.3 **Released**: March 25, 2026 ### Bug Fixes #### Core * Fixed a potential app hang when the app transitions to the background for licenses without analytics enabled. * Fixed syntax in JavaScript sdc-lib folder not correctly downleveled to respect minimum browser version. ## 8.1.2 **Released**: March 9, 2026 ### Bug Fixes #### Barcode * Fixed an issue where SparkScan would select the wrong camera #### Smart Label Capture * Fixed a rare race condition #### Core * Fixed an issue where in some webview scenarios on iPhone Pro the wrong back camera was selected ## 8.1.1 **Released**: February 5, 2026 ### Performance Improvements #### Core * Reduced intermittent memory spikes while configuring the barcode scanner across all capture modes ### Bug Fixes #### Barcode * Fixed an issue where the SparkScanView was not being disposed correctly #### Id * Removed the Centaurus dependency from the ID Capture package which was accidentally added in 8.1.0 but never actually used ## 8.1.0 **Released**: December 17, 2025 ### New Features #### Barcode * Smart Scan Selection is now available in Barcode Capture. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * Added SymbologySettings.ocrFallbackRegex, allowing you to filter or constrain results returned from OCR fallback. * Extended Aztec codes reader to support scanning mirrored codes. * Added support for square DataMatrix codes with one-sided damage or occlusion. This feature is only enabled in Barcode Capture and SparkScan. * [SparkScan](/sdks/web/sparkscan/intro.md) now supports Smart Scan Selection. Scanning a single barcode is often difficult in environments where multiple barcodes are placed closely together, like on a densely packed warehouse shelf or on a package with various labels. This can lead to scanning the wrong item, causing errors and slowing down operations. Users might have to manually switch to a special, more precise scanning mode (Target Mode), which is inefficient. Smart Scan Selection solves this problem by automatically detecting when a user is trying to scan in a "dense barcode" environment. The interface then intelligently adapts, providing an aimer to help the user precisely select the desired barcode without needing to manually change any settings. This creates a seamless and more intuitive scanning experience. * Added `ScanditIconType.Delete` and `ScanditIconType.Slash` which can be used in `BarcodeArStatusIconAnnotationAnchor`. #### Id * Added NationalityISO property that maps results from Nationality field to country ISO code * Added RejectionDiagnosticJSON property to CapturedId to report debug info during Timeout rejections * Added rejectionTimeoutSeconds to IdCaptureSettings allowing customers to use timeout other than default (6s). Minimum timeout is 1s. * Added support for new California DL, new South Carolina DL, Arizona Medical Marijuana Card, Kuwait Civil card, and new Texas DL #### Core * Added Electronic Product Code (EPC) parser and GS1_DIGITAL_LINK parsers ### Performance Improvements #### Barcode * Improved MicroQR detector tolerance to quiet zone violations * Improved suppression of incorrect Codabar recognitions when using the [“strict" symbology extension](../symbology-properties#symbology-extension-descriptions) #### Id * Improved success rate when scanning using the ImageFrameSource or the SingleImageUploader as frame source #### Smart Label Capture * Incremental improvements in accuracy across all use-cases for the OCR model powering Smart Label Capture. ### Behavioral Changes #### Barcode * Enabling the [“ocr_fallback" symbology extension](../symbology-properties#symbology-extension-descriptions) with missing OCR model resources now triggers the context error 28 (“Missing Resource”) #### Smart Label Capture * Validation Flow: Manually input values for barcodes will go through a stricter validation. Some values may no longer be accepted if they do not match the symbology specs for the symbology’s definition ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance * Fixed an issue that caused continuous scanning to stop working when rotating the device * Fixed an issue where FrameData was not usable for tracking modes #### Core * Fixed a small memory leak that affected fresh install runs only * Overcome orientation change limitation in iOS PWAs when display mode is fullscreen or standalone ## 8.0.1 **Released**: January 14, 2026 ### Bug Fixes #### Barcode * Fixed a rare out-of-bound memory access crash when scanning low-resolution or blurry `EAN13/UPCA` codes at a specific distance #### Core * Fixed a small memory leak that affected fresh install runs only ## 8.0.0 **Released**: November 4, 2025 ### New Features Scandit's SDK 8.0 marks the evolution of data capture from a high-performing scanning tool into an intelligent AI-powered workflow enabler. As frontline operations face mounting pressures with more data points to capture, increasingly complex workflows to navigate, and tighter resource constraints, SDK 8.0 delivers a set of innovations that: * Adapt its scanning settings and UI to context by analyzing the scanning environment and user intent; * Automate the capture of any data format, barcode clustering, task handling or camera settings; * Accelerate critical use cases to maximize ROI through intuitive, streamlined scanning workflows, using interactive AR-guidance, adaptive UI and out-of-the-box custom-branded passenger experiences. With SDK 8.0 businesses can transform data capture from a basic function to a strategic advantage. It enables intelligent scanning that: * Understands not just what is being scanned, but also what you want to scan and why you’re scanning it * Adapts accordingly by adjusting scanning settings and/or UI, understanding what comes next and how to guide users seamlessly through sophisticated tasks to ensure the highest level of productivity. #### Core * The `Camera` API has been completely redesigned for this release. See the [API reference](https://docs.scandit.com/data-capture-sdk/web/core/api/camera.html#camera) for complete details. * The minimum Chrome version supported is now 85+. * The `DataCaptureContext.create`, `createWithOptions` and `configure` methods have been removed in favor of `DataCaptureContext.forLicenseKey`. #### Barcode * Smart Scan Selection is now available in SparkScan for the Web SDK. * Adapted `SparkScanView` to now be usable as a web component. Also added a `SparkScanReactSample` to demonstrate this usage. * The following have been added to MatrixScan AR: * `BarcodeArView.getHighlightForBarcode` * `BarcodeAirView.getAnnotationForBarcode` #### Smart Label Capture * We’re introducing an enhancement that makes Smart Label Capture more robust and scalable by complementing its on-device model with a larger, more capable model. When the on-device model can’t capture certain labels, the SDK automatically escalates to this enhancement to handle complex or unforeseen cases with high accuracy and reliability. This capability is currently available in `beta`. If you’re interested in trying it, please contact Scandit Support. For configuration details, see `labelDefinition.adaptiveRecognitionEngine`. #### ID * Added `ElementsToRetain` to `MobileDocumentScanner`: The set of data elements that the application intends to retain from scanned mobile documents. This information is used to set the `IntentToRetain` flag in ISO 18013-5 mdoc requests, which is required for legal compliance with data protection standards. An empty set indicates no elements will be retained, and `IntentToRetain` will be set to `false` for all fields. * ID Capture now supports full-frame anonymization. * The result of `decodeMobileDriverLicenseViz`, which is currently returned as part of the `VizResult` within `CapturedId`, will now be provided through a new field named `mobileDocumentOcr`. * Added `CapturedId::isCitizenPassport`, which indicates whether the passport was issued to a citizen of the issuing country. Returns `false` for travel documents such as refugee, stateless, or alien passports, and for any passports issued by organizations rather than states. * The following Chinese travel permits now extract VIZ + MIZ data during double-sided scanning flows: * CT - Taiwan Residents Mainland Travel Permit * W - Mainland Residents Exit-Entry Permit to and from Hong Kong and Macao * CD - Mainland Residents Entry-Exit Permit to and from Taiwan ### Behavioral Changes #### Barcode * Symbology `RM4SCC` has been renamed to `ROYAL_MAIL_4STATE`. * Changed the default highlight brush in SparkScan and Barcode Capture. #### Label * The `LabelFieldDefinition` API has been updated with the following changes: * Renamed property: `pattern` → `valueRegex`, `patterns` → `valueRegexes` * Renamed property: `dataTypePattern` → `anchorRegex`, `dataTypePatterns` → `anchorRegexes` * Receipt Scanning API has been updated with the following changes: * `ReceiptScanningResult`: * Removed properties: `storeNumber`, `storeStreet`, `storeZip`, `storeState`, `storePhone`, `paymentMethod`, and `paymentCurrency`. * Added property: `storeAddress` - Full address of the store (Street Number, Street, City, State, NPA). * Renamed property: `paymentSubtotal` → `paymentPreTaxTotal` - Total balance before taxes are applied. * `ReceiptScanningLineItem`: * Removed property: `category`. * Renamed properties: `price` → `unitPrice` (Price for a single unit of the item), `total` → `totalPrice` (Total price for a specific product, quantity × unitPrice). #### ID * The configuration for the following documents has been changed as detailed below: * Australian mobile driver licenses (mDL) are now treated as normal documents, with no separate mode. * US Green Cards are now treated as residence permits. * Removed the deprecated API `DateResult::toDate`. Use `DateResult::toLocalDate` or `DateResult::toUtcDate` instead. * `fullName` now an optional field on all `IdCapture` result types and `capturedMrz` now an optional field on `MrzResult`. ### Bug Fixes #### ID * Fixed a bug that could get the scanner stuck when scanning a US passport card. * Fixed an issue where unavailable dates would not be properly set to `null` in an ID scan result. ### Deprecations #### Core * `VideoResolution::Auto` is now deprecated. Please use the capture mode's `recommendedCameraSettings` for the best results. #### Barcode * All previously deprecated APIs have been removed in this release. * `DataCaptureContext.create`, `createWithOptions` and `configure` have been removed in favor of the `forLicenseKey` method. ## 7.6.7 Find earlier versions in the [release notes section of version 7](/7.6.14/sdks/web/release-notes) --- ## Composite Codes import ScanningCompositeCodes from '../../partials/_scanning-composite-codes.mdx'; --- ## Single Barcode Scanning # Single Barcode Scanning import SingleScanning from '../../partials/_single-scanning.mdx'; --- ## Advanced Configurations # Advanced Configurations SparkScan is optimized by default for efficiency, accuracy, and a seamless user experience. However, there are some cases where you might want to customize the behavior of SparkScan. This guide will show you how to add additional capabilities and further customize SparkScan to best fit your needs. ## Advanced Capabilities ### Trigger Error State You may want to introduce logic in your app to show an error message when scanning specific barcodes (e.g. barcodes already added to the list, barcodes from the wrong lot etc.). SparkScan offers a built-in error state you can easily set to trigger an error feedback prompt to the user. You will be able to customize: - The text message - The timeout of the error message: the scanner will be paused for the specified amount of time, but the user can quickly restart the scanning process by tapping the trigger button :::tip A high timeout (>10s) typically requires the users to interact with the UI to start scanning again. This is a good choice when you want to interrupt the scanning workflow (e.g. because a wrong barcode is scanned and some actions need to be performed). A small timeout (\ { if (isValidBarcode(barcode)) { return new SparkScanBarcodeSuccessFeedback(); } else { return new SparkScanBarcodeErrorFeedback( 'This code should not have been scanned', 60 * 1000, Color.fromHex('#FF0000'), new Brush(Color.fromHex('#FF0000'), Color.fromHex('#FF0000'), 1), ); } }, }; ``` You can have different error states triggered by different logic conditions. These errors can show different colors and have different timeouts. For example: This error state for a code that should not have been scanned. This error state for a code that has been scanned more than once. ### Reject Barcodes To prevent scanning unwanted barcodes (like those already listed or from incorrect lots), use SparkScan’s built-in error state. Setting the [`SparkScanBarcodeErrorFeedback.resumeCapturingDelay`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/spark-scan-barcode-feedback.html#property-scandit.datacapture.barcode.spark.feedback.Error.ResumeCapturingDelay) parameter to 0 allows the user to continue scanning immediately without pausing on rejected codes. ## UI Customization :::tip Please refer to [SparkScanView](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) for the full list of parameters. ::: import Customization from '../../../partials/advanced/_sparkscan-customization.mdx'; ## Workflow Options This section explains all the available options to configure SparkScan to best fit your case, in case you found something that didn't work well in the default configuration (that remains our recommended option). Developers can set a combination of scanning mode, scanning behavior and camera preview behavior - defining the initial state of the scanner. This can be done by setting the default scanning mode ([`SparkScanViewSettings.defaultScanningMode`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.DefaultScanningMode)). This combination allows for flexible configurations to suit different scanning needs. ### Scanning Mode The scanning mode determines the programmatic presence of an aimer in the preview to help with precision scanning. | Mode | Description | | ----------- | --------------------------------------------------- | | **Default** | Generally recommended. This mode will display a small camera preview to aid with aiming. The preview size and zoom level can be adjusted as needed. User can aim easily at the intended barcode. | | **Target** | This mode will always add an aimer to the camera preview to precisely select the barcode to scan. This is recommended only when selecting among many close barcodes is the common task. | :::tip Even in the *Default* mode, SparkScan will automatically show an aimer when multiple barcodes are present in the view and no clear intention from the user to scan a single one is recorded ([`SparkScanSettings.ScanIntention`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/spark-scan-settings.html#property-scandit.datacapture.barcode.spark.SparkScanSettings.ScanIntention)). Enabling the *Target* mode will simply force this "precision selection" state to be on at all time. ::: ### Scanning Behavior The scanning behavior determines how barcodes are scanned - one at a time or continuously. | Behavior | Description | | ------------------- | ---------------------------------------------------------- | | **Single scan** | Scan one barcode at a time. The user needs to trigger the scanner every time to scan a barcode. This allows for a more controlled scanning and lower battery consumption. | | **Continuous scan** | Scan barcodes consecutively. The user needs to trigger the scanner once and barcodes will be scanned without any further interaction before each scan. This allows for a smoother experience when multiple barcodes need to be scanned consecutively. | :::tip Users can enable continuous scanning by holding down the trigger button. This gesture can be disabled ([`SparkScanViewSettings.holdToScanEnabled`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/spark-scan-view-settings.html#property-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings.HoldToScanEnabled)). ::: ### Preview Behavior The preview behavior determines how the camera preview behaves when the scanner is not actively scanning. | Behavior | Description | | -------------- | -------------------------- | | **Default** | Preview fades away when the scanner is off. This lets the user check important information displayed by the app and reduces battery consumption. | | **Persistent** | Preview remains visible, but darkened, even when the scanner is off. This is useful for scenarios where you want to select a barcode (among many) or need to look through the preview at all times (to ensure the right scan) - especially if used in conjunction with the target mode. | --- ## Get Started # Get Started In this guide you will learn step-by-step how to add SparkScan to your application. The general steps are: 1. Create a new Data Capture Context instance. 2. Configure the Spark Scan Mode. 3. Create the SparkScanView with the desired settings and bind it to the application’s lifecycle. 4. Register the listener to be informed when new barcodes are scanned and update your data whenever this event occurs. ## Prerequisites - The latest stable version of [Node.js and npm](https://nodejs.org/en/download/) (required only if including and building the SDK as part of an app, instead of just including it as an external resource from a CDN in HTML). - A valid Scandit Data Capture SDK license key. You can sign up for a free [test account](https://ssl.scandit.com/dashboard/sign-up?p=test&utm%5Fsource=documentation). - If you have not already done so, see [this guide](../add-sdk.md) for information on how to add the Scandit Data Capture SDK to your project :::note Devices running the Scandit Data Capture SDK need to have a GPU or the performance will drastically decrease. ::: ## Create a New Data Capture Context Instance The first step to add capture capabilities to your application is to create a new [Data Capture Context](https://docs.scandit.com/data-capture-sdk/web/core/api/data-capture-context.html#class-scandit.datacapture.core.DataCaptureContext). The context expects a valid Scandit Data Capture SDK license key during construction. ```js import { DataCaptureContext } from "@scandit/web-datacapture-core"; import { barcodeCaptureLoader, SparkScanSettings, SparkScan, SparkScanViewSettings, } from "@scandit/web-datacapture-barcode"; const dataCaptureContext = await DataCaptureContext.forLicenseKey( "-- ENTER YOUR SCANDIT LICENSE KEY HERE --", { libraryLocation: new URL( "sdc-lib-self-hosted-path", document.baseURI ).toString(), // or use the cdn https://cdn.jsdelivr.net/npm/@scandit/web-datacapture-barcode@latest/sdc-lib/ moduleLoaders: [barcodeCaptureLoader()], } ); ``` ## Configure the SparkScan Mode The SparkScan Mode is configured through [`SparkScanSettings`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/spark-scan-settings.html#class-scandit.datacapture.barcode.spark.SparkScanSettings) and allows you to register one or more listeners that are informed whenever a new barcode is scanned. For this tutorial, we will set up SparkScan for scanning EAN13 codes. Change this to the correct symbologies for your use case (for example, Code 128, Code 39…). ```js const sparkScanSettings = new SparkScanSettings(); sparkScanSettings.enableSymbologies([Symbology.EAN13UPCA]); ``` Next, create a SparkScan instance with the settings initialized in the previous step: ```js const sparkScan = SparkScan.forSettings(sparkScanSettings); ``` ## Setup the Spark Scan View The SparkScan built-in user interface includes the camera preview and scanning UI elements. These guide the user through the scanning process. The [`SparkScanView`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/spark-scan-view-settings.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView) appearance can be customized through [`SparkScanViewSettings`](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/spark-scan-view-settings.html#class-scandit.datacapture.barcode.spark.ui.SparkScanViewSettings). ```js const sparkScanViewSettings = new SparkScanViewSettings(); // setup the desired appearance settings by updating the fields in the object above ``` See the [SparkScan Workflow Options](./advanced.md#workflow-options) section for more information. By adding a `SparkScanView`, the scanning interface (camera preview and scanning UI elements) will be added automatically to your application. Add a `SparkScanView` to your view hierarchy. Construct a new SparkScan view. The `SparkScanView` is automatically added to the provided `parentView`: ```js const sparkScanView = SparkScanView.forElement( document.body, dataCaptureContext, sparkScan, sparkScanViewSettings ); // setup any desired view properties by updating the fields in the object above ``` Optionally you may set a feedback delegate on the SparkScanView, if you wish to validate barcodes and emit a success or error feedback based on certain conditions: ```js sparkScanView.feedbackDelegate = { getFeedbackForBarcode: (barcode) => { // Replace the line below with your own validation logic if (isInvalidBarcode(barcode)) { // Return an error feedback for invalid barcodes return new SparkScanBarcodeErrorFeedback( "Invalid barcode.", 60_000 // How many ms to wait for scanning to be resumed ); } // Return a success feedback for valid barcodes return new SparkScanBarcodeSuccessFeedback(); }, }; ``` Once your app is ready to mount the SparkScanView, make sure to call [SparkScanView.prepareScanning()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.PrepareScanning): ```js async connectedCallback() { await sparkScanView.prepareScanning(); } ``` Additionally, make sure to call [SparkScanView.stopScanning()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/spark-scan-view.html#method-scandit.datacapture.barcode.spark.ui.SparkScanView.StopScanning) when your app is unmounting. You have to call this for disposing the [SparkScanView](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/ui/spark-scan-view.html#class-scandit.datacapture.barcode.spark.ui.SparkScanView). ```js async disconnectedCallback() { await sparkScanView.stopScanning(); } ``` ## Register the Listener To keep track of the barcodes that have been scanned, implement the [SparkScanListener](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/spark-scan-listener.html#interface-scandit.datacapture.barcode.spark.ISparkScanListener) interface and register the listener to the SparkScan mode. ```js // Register a listener object to monitor the spark scan session. const listener = { didScan: (sparkScan, session, frameData) => { // Gather the recognized barcode const barcode = session.newlyRecognizedBarcode; if (barcode != null) { // Handle the barcode } }, }; sparkScan.addListener(listener); ``` [SparkScanListener.didScan()](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/spark-scan-listener.html#method-scandit.datacapture.barcode.spark.ISparkScanListener.OnBarcodeScanned) is called when a new barcode has been scanned. This result can be retrieved by using the [SparkScanSession.newlyRecognizedBarcode](https://docs.scandit.com/data-capture-sdk/web/barcode-capture/api/spark-scan-session.html#property-scandit.datacapture.barcode.spark.SparkScanSession.NewlyRecognizedBarcode) property on the session object. ## Complete SparkScan example ```js import { SparkScan, SparkScanBarcodeErrorFeedback, SparkScanBarcodeSuccessFeedback, SparkScanSettings, SparkScanView, SparkScanViewSettings, Symbology, barcodeCaptureLoader, } from "@scandit/web-datacapture-barcode"; import { DataCaptureContext } from "@scandit/web-datacapture-core"; const context = await DataCaptureContext.forLicenseKey( "-- ENTER YOUR SCANDIT LICENSE KEY HERE --", { libraryLocation: "/self-hosted-sdc-lib/", moduleLoaders: [barcodeCaptureLoader()], } ); const settings = new SparkScanSettings(); settings.enableSymbologies([ Symbology.EAN13UPCA, Symbology.Code128, Symbology.QR, ]); const sparkScan = SparkScan.forSettings(settings); sparkScan.addListener({ didScan: (sparkScan, session) => { const barcode = session.newlyRecognizedBarcode; if (barcode) { console.log("Scanned", barcode.symbology, barcode.data); } }, }); const viewSettings = new SparkScanViewSettings(); const view = SparkScanView.forElement( document.body, context, sparkScan, viewSettings ); view.feedbackDelegate = { getFeedbackForBarcode: (barcode) => { if (barcode.data === "5901234123457") { return new SparkScanBarcodeErrorFeedback("Invalid barcode.", 60_000); } else { return new SparkScanBarcodeSuccessFeedback(); } }, }; async function mount() { await view.prepareScanning(); } async function unmount() { await view.stopScanning(); } mount().catch(async (error) => { console.error(error); await unmount(); }); ``` A more complete example can be found [here on StackBlitz](https://stackblitz.com/github/Scandit/datacapture-web-samples/tree/master/01_Single_Scanning_Samples/01_Barcode_Scanning_with_Pre-built_UI/ListBuildingSample). ## Scan Some Barcodes Now that you’re up and running, go find some barcodes to scan. Don’t feel like getting up from your desk? Here’s a [handy pdf of barcodes](https://github.com/Scandit/.github/blob/main/images/PrintTheseBarcodes.pdf) you can print out. --- ## About SparkScan # About SparkScan SparkScan is our pre-built smartphone scanning interface designed for high-performance barcode scanning. It fits on top of any smartphone application, providing an intuitive user interface for simple, fast and ergonomic scanning in scan-intensive workflows such as inventory management in retail, or goods receiving in logistics. SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs. ## UI Overview The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience. Two main elements compose the UI: ![SparkScan UI](/img/sparkscan/features_web.png) - **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc). - **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space. There are additional UI elements available for displaying advanced scanning mode, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section. ## Workflow Description When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use. To start scanning, the user can simply tap on it. When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app). In the default configuration: - Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away. - Tapping on the trigger button or the mini preview will restart immediately the scanner. Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state. If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released. List building use case using SparkScan. The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field. But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more. ## Supported Symbologies SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx). ## AI-Powered Features SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide. --- ## Symbology Properties import SymbologyProperties from '../../partials/_symbology-properties.mdx'; --- ## System Requirements import SystemRequirements from '../../partials/_system-requirements.mdx'; --- ## WebView Integration # WebView Integration The Scandit Web SDK can run inside a native WebView on Android and iOS. Because WebViews do not have direct access to device APIs, the native host application is responsible for requesting and delegating camera permissions to the web content. ## Secure Context Requirement Browsers — including WebView runtimes — only allow camera access in a [secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts). This means the web content must be served over HTTPS or from `localhost`. A plain `file://` URL is not a secure context and `getUserMedia` will fail. The recommended approach is to embed a lightweight local HTTP server in the native app and load the web content from `http://localhost:/`. This satisfies the secure context requirement without requiring a remote server. ## Android :::warning Android WebView does not support `SharedArrayBuffer` because its process model cannot provide the OS-level process isolation required to be [cross-origin isolated](https://developer.mozilla.org/en-US/docs/Web/API/crossOriginIsolated). This is an Android-specific limitation — iOS WKWebView supports cross-origin isolation since iOS 15.2. As a result, multithreading is unavailable on Android WebView and performance-intensive capture modes such as MatrixScan Batch and MatrixScan AR will run significantly slower than in a standard browser. See [Improve Runtime Performance by Enabling Browser Multithreading](./matrixscan/get-started.md#improve-runtime-performance-by-enabling-browser-multithreading) for context on what multithreading provides. If scanning performance is critical for your use case, consider these alternatives: - **Progressive Web App (PWA)**: a PWA runs in the device browser, which does support cross-origin isolation and multithreading, while still offering an app-like experience. - **Native Android SDK**: the [Scandit Android SDK](/sdks/android/add-sdk.md) runs entirely in native code and is not subject to any WebView or browser limitations. ::: ### 1. Declare the Camera Permission Add the `CAMERA` permission to your `AndroidManifest.xml`: ```xml ``` ### 2. Request Camera Permission at Runtime Request the OS-level camera permission before loading the WebView. Using the Activity Result Contracts API: ```kotlin # import android.Manifest # import android.content.pm.PackageManager # import android.os.Bundle # import androidx.activity.result.contract.ActivityResultContracts # import androidx.core.content.ContextCompat private val cameraPermission = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { granted -> if (granted) { loadWebView() } else { // Handle denial — the web content cannot access the camera } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { loadWebView() } else { cameraPermission.launch(Manifest.permission.CAMERA) } } ``` ### 3. Grant Camera Access to Web Content When the web SDK calls `getUserMedia`, the WebView triggers `WebChromeClient.onPermissionRequest`. Override this method to forward the permission to the web content. It is safe to grant automatically here because the native app has already received the OS camera permission in the previous step: ```kotlin # import android.webkit.PermissionRequest # import android.webkit.WebChromeClient webView.webChromeClient = object : WebChromeClient() { override fun onPermissionRequest(request: PermissionRequest) { val cameraResources = request.resources.filter { it == PermissionRequest.RESOURCE_VIDEO_CAPTURE }.toTypedArray() request.grant(cameraResources) } } ``` ### 4. Configure the WebView Enable JavaScript and allow media autoplay so the SDK can start the camera without requiring a user gesture: ```kotlin # import android.webkit.WebSettings # import android.webkit.WebView webView.settings.apply { javaScriptEnabled = true domStorageEnabled = true mediaPlaybackRequiresUserGesture = false } ``` ### 5. Serve Content from Localhost Load the web app from a local server to satisfy the secure context requirement: ```kotlin # import android.webkit.WebView webView.loadUrl("http://localhost:$port/") ``` A minimal implementation using [NanoHTTPD](https://github.com/NanoHttpd/nanohttpd) can serve static files from the APK's `assets/` folder. Make sure to include the correct MIME type for `.wasm` files (`application/wasm`) — without it, the browser will reject the Scandit engine files. For general guidance on serving the SDK's engine files, see [Hosting the `sdc-lib` files](./add-sdk.md#hosting-the-sdc-lib-files). ## iOS ### 1. Add the Camera Usage Description Add a camera usage description to your `Info.plist`: ```xml NSCameraUsageDescription Camera access is required for barcode scanning. ``` ### 2. Configure the WKWebView Enable inline media playback and allow media to start without a user gesture: ```swift import WebKit let configuration = WKWebViewConfiguration() configuration.allowsInlineMediaPlayback = true configuration.mediaTypesRequiringUserActionForPlayback = [] let webView = WKWebView(frame: .zero, configuration: configuration) webView.uiDelegate = self ``` ### 3. Handle the Media Capture Permission Request Implement `WKUIDelegate` to respond when the web SDK requests camera access. Tie the decision to the current `AVCaptureDevice` authorization status: ```swift import AVFoundation import WebKit func webView( _ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void ) { AVCaptureDevice.requestAccess(for: .video) { granted in DispatchQueue.main.async { decisionHandler(granted ? .grant : .deny) } } } ``` This delegate method is called every time the web content requests camera access. Calling `AVCaptureDevice.requestAccess` here triggers the system permission prompt on first launch, and returns immediately on subsequent calls based on the stored authorization status. ### 4. Pre-request the Camera Permission (Recommended) Requesting the native camera permission before loading the page results in a smoother user experience, because the system prompt appears immediately at app launch rather than mid-scan: ```swift override func viewDidLoad() { super.viewDidLoad() setupWebView() requestCameraPermission() loadContent() } private func requestCameraPermission() { AVCaptureDevice.requestAccess(for: .video) { _ in } } ``` ### 5. Load the Web Content Load a bundled HTML file or a local server URL. For bundled files, use `loadFileURL(_:allowingReadAccessTo:)` — note that `file://` URLs are not a secure context, so you must either serve from a local HTTP server or load the file with the SDK already initialized for a non-camera use-case. The simplest approach is to bundle the web app and load it directly: ```swift if let path = Bundle.main.path(forResource: "index", ofType: "html") { let url = URL(fileURLWithPath: path) webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent()) } ``` :::note `loadFileURL` grants the web content a secure context on iOS, so `getUserMedia` works even for `file://` URLs when loaded this way. :::