├── .gitignore ├── AnylineExamples ├── README.md ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── kotlin │ │ │ └── com │ │ │ └── anyline │ │ │ └── examples │ │ │ └── ViewConfigTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ │ ├── cow.ale │ │ │ ├── viewConfigEditor │ │ │ │ ├── json-editor-css.html │ │ │ │ └── json-editor │ │ │ │ │ └── jsoneditor.js │ │ │ └── viewConfigs │ │ │ │ ├── barcode_config_barcode.json │ │ │ │ ├── barcode_config_multi_barcode.json │ │ │ │ ├── barcode_config_overlays.json │ │ │ │ ├── barcode_config_overlays_visualfeedback.json │ │ │ │ ├── custom_script_config.json │ │ │ │ ├── id_config_arabic_id.json │ │ │ │ ├── id_config_cyrillic_id.json │ │ │ │ ├── id_config_mrz.json │ │ │ │ ├── id_config_mrz_frontcam.json │ │ │ │ ├── id_config_universal_id.json │ │ │ │ ├── meter_config_analog_digital.json │ │ │ │ ├── meter_config_serial_number.json │ │ │ │ ├── ocr_config_shipping_container_horizontal.json │ │ │ │ ├── ocr_config_shipping_container_vertical.json │ │ │ │ ├── ocr_config_vin.json │ │ │ │ ├── ocr_config_vin_with_uifeedback.json │ │ │ │ ├── odometer_config.json │ │ │ │ ├── tire_commercial_tire_id.json │ │ │ │ ├── tire_config_tin_dot_with_uifeedback.json │ │ │ │ ├── tire_config_tin_universal_with_uifeedback.json │ │ │ │ ├── tire_config_tire_make.json │ │ │ │ ├── tire_config_tire_size.json │ │ │ │ ├── tire_size_tin_demo.json │ │ │ │ ├── tire_size_tin_make_demo.json │ │ │ │ ├── vehicle_config_license_plate.json │ │ │ │ ├── vehicle_config_license_plate_eu_vis.json │ │ │ │ ├── vehicle_config_license_plate_us.json │ │ │ │ ├── vehicle_config_registration_certificate.json │ │ │ │ ├── workflows_config_parallel_first_vin_barcode.json │ │ │ │ ├── workflows_config_parallel_meter_barcode.json │ │ │ │ └── workflows_config_sequential.json │ │ ├── ic_launcher-playstore.png │ │ ├── java │ │ │ └── com │ │ │ │ └── anyline │ │ │ │ └── examples │ │ │ │ ├── CameraStateObserver.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── MainApplication.kt │ │ │ │ ├── ScanActivity.kt │ │ │ │ ├── SelectConfigActivity.kt │ │ │ │ ├── barcodeOverlay │ │ │ │ ├── BarcodeOverlayScanActivity.kt │ │ │ │ └── BarcodeOverlayViewHolderList.kt │ │ │ │ ├── scanViewConfig │ │ │ │ ├── ScanViewConfigFile.kt │ │ │ │ └── ScanViewConfigFolder.kt │ │ │ │ └── viewConfigEditor │ │ │ │ ├── ViewConfigEditorActivity.kt │ │ │ │ ├── ViewConfigEditorFragment.kt │ │ │ │ ├── WebContentFragment.kt │ │ │ │ ├── WebContentFragmentAction.kt │ │ │ │ └── WebContentFragmentCallback.kt │ │ └── res │ │ │ ├── drawable-hdpi │ │ │ ├── ic_file.png │ │ │ └── ic_folder.png │ │ │ ├── drawable-mdpi │ │ │ ├── ic_file.png │ │ │ └── ic_folder.png │ │ │ ├── drawable-xhdpi │ │ │ ├── ic_file.png │ │ │ └── ic_folder.png │ │ │ ├── drawable-xxhdpi │ │ │ ├── ic_file.png │ │ │ └── ic_folder.png │ │ │ ├── drawable-xxxhdpi │ │ │ ├── ic_file.png │ │ │ └── ic_folder.png │ │ │ ├── drawable │ │ │ ├── ic_action_filter.xml │ │ │ ├── ic_action_pencil.xml │ │ │ ├── ic_barcode_overlay_checkmark_green.png │ │ │ ├── ic_barcode_overlay_far_blue.png │ │ │ ├── ic_barcode_overlay_far_green.png │ │ │ ├── ic_barcode_overlay_plus_blue.png │ │ │ ├── ic_help_circle.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── ic_launcher_foreground.xml │ │ │ ├── selected_barcode_overlay_rounded_corner.xml │ │ │ ├── uifeedback_inprogress_tire_make.png │ │ │ ├── uifeedback_inprogress_tire_size.png │ │ │ ├── uifeedback_inprogress_tire_tin.png │ │ │ └── webcontent_no_network_error_image.png │ │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ ├── activity_scan.xml │ │ │ ├── activity_select_view_config.xml │ │ │ ├── activity_view_config_editor.xml │ │ │ ├── fragment_webcontent.xml │ │ │ └── item_view_select_config.xml │ │ │ ├── menu │ │ │ └── menu_activity_scan.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values-night │ │ │ └── themes.xml │ │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── string-arrays.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ │ └── xml │ │ │ ├── backup_rules.xml │ │ │ └── data_extraction_rules.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── anyline │ │ └── examples │ │ └── ExampleUnitTest.kt ├── build.gradle ├── debug.keystore ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── README.md └── license ├── LICENSE.md └── third_party ├── license-dependency.json └── third_party_LICENSE.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | .gradle 4 | build/ 5 | local.properties 6 | AnylineSDK-Examples/AnylineSDK-Examples-Source/gradle 7 | AnylineSDK-Examples/AnylineSDK-Examples-Source/gradlew 8 | AnylineSDK-Examples/AnylineSDK-Examples-Source/gradlew.bat 9 | -------------------------------------------------------------------------------- /AnylineExamples/README.md: -------------------------------------------------------------------------------- 1 | # anyline-ocr-examples-android 2 | Anyline - A powerful OCR SDK for Android 3 | 4 | ## File summary 5 | 6 | * `AnylineExamples` - Example app source code 7 | * `README.md` - This readme. 8 | * `LICENSE.md` - The license file. 9 | 10 | ## API Reference 11 | 12 | The API reference for the Anyline SDK for Android can be found here: https://documentation.anyline.com/android-sdk-component/latest/_attachments/documentation/index.html 13 | 14 | ## Getting Started 15 | 16 | Check out our getting-started section here: https://documentation.anyline.com/android-sdk-component/latest/getting-started.html 17 | 18 | ## Documentation 19 | 20 | Check out our developer guide here: https://documentation.anyline.com/android-sdk-component/latest/index.html 21 | 22 | ## License 23 | 24 | See LICENSE file. -------------------------------------------------------------------------------- /AnylineExamples/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /AnylineExamples/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'org.jetbrains.kotlin.android' 4 | } 5 | 6 | ext { 7 | anylinesdk_version = "55.2.0" 8 | timber_version = "5.0.1" 9 | leakcanary_version = "2.9.1" 10 | 11 | anyline_examples_version_code = 13 12 | anyline_examples_version_name = "55.2.0" 13 | } 14 | 15 | android { 16 | namespace "com.anyline.examples" 17 | compileSdk 34 18 | 19 | defaultConfig { 20 | applicationId "io.anyline.examples" 21 | minSdk 21 22 | targetSdk 34 23 | versionCode anyline_examples_version_code 24 | versionName anyline_examples_version_name 25 | 26 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 27 | } 28 | 29 | buildFeatures { 30 | buildConfig true 31 | viewBinding true 32 | dataBinding true 33 | } 34 | 35 | signingConfigs { 36 | debug { 37 | storeFile file("../debug.keystore") 38 | } 39 | release { 40 | storeFile file("../debug.keystore") 41 | } 42 | } 43 | buildTypes { 44 | debug { 45 | signingConfig signingConfigs.debug 46 | } 47 | release { 48 | signingConfig signingConfigs.debug 49 | shrinkResources true 50 | minifyEnabled true 51 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 52 | } 53 | } 54 | compileOptions { 55 | coreLibraryDesugaringEnabled true 56 | sourceCompatibility JavaVersion.VERSION_17 57 | targetCompatibility JavaVersion.VERSION_17 58 | } 59 | kotlinOptions { 60 | jvmTarget = '17' 61 | } 62 | 63 | sourceSets { 64 | androidTest { 65 | assets.srcDirs += ['src/main/assets'] 66 | } 67 | } 68 | } 69 | 70 | dependencies { 71 | 72 | implementation "io.anyline:anylinesdk:$anylinesdk_version" 73 | 74 | coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.2.2" 75 | 76 | implementation "com.jakewharton.timber:timber:$timber_version" 77 | implementation "androidx.fragment:fragment-ktx:1.6.1" 78 | implementation 'androidx.webkit:webkit:1.7.0' 79 | implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' 80 | debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakcanary_version" 81 | 82 | implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" 83 | 84 | implementation 'androidx.core:core-ktx:1.10.1' 85 | implementation 'androidx.appcompat:appcompat:1.4.1' 86 | implementation 'com.google.android.material:material:1.6.0' 87 | implementation 'androidx.constraintlayout:constraintlayout:2.1.3' 88 | testImplementation 'junit:junit:4.13.2' 89 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 90 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 91 | } -------------------------------------------------------------------------------- /AnylineExamples/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/martin/develop/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | 20 | # [-- Kotlin Serialization Library 21 | # Keep `Companion` object fields of serializable classes. 22 | # This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects. 23 | -if @kotlinx.serialization.Serializable class ** 24 | -keepclassmembers class <1> { 25 | static <1>$Companion Companion; 26 | } 27 | 28 | # Keep `serializer()` on companion objects (both default and named) of serializable classes. 29 | -if @kotlinx.serialization.Serializable class ** { 30 | static **$* *; 31 | } 32 | -keepclassmembers class <1>$<3> { 33 | kotlinx.serialization.KSerializer serializer(...); 34 | } 35 | 36 | # Keep `INSTANCE.serializer()` of serializable objects. 37 | -if @kotlinx.serialization.Serializable class ** { 38 | public static ** INSTANCE; 39 | } 40 | -keepclassmembers class <1> { 41 | public static <1> INSTANCE; 42 | kotlinx.serialization.KSerializer serializer(...); 43 | } 44 | 45 | # @Serializable and @Polymorphic are used at runtime for polymorphic serialization. 46 | -keepattributes RuntimeVisibleAnnotations,AnnotationDefault 47 | 48 | # Serializer for classes with named companion objects are retrieved using `getDeclaredClasses`. 49 | # If you have any, uncomment and replace classes with those containing named companion objects. 50 | #-keepattributes InnerClasses # Needed for `getDeclaredClasses`. 51 | #-if @kotlinx.serialization.Serializable class 52 | #com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions. 53 | #com.example.myapplication.HasNamedCompanion2 54 | #{ 55 | # static **$* *; 56 | #} 57 | #-keepnames class <1>$$serializer { # -keepnames suffices; class is kept when serializer() is kept. 58 | # static <1>$$serializer INSTANCE; 59 | #} 60 | # Kotlin Serialization Library --] -------------------------------------------------------------------------------- /AnylineExamples/app/src/androidTest/kotlin/com/anyline/examples/ViewConfigTest.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples 2 | 3 | import android.content.Context 4 | import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner 5 | import androidx.test.platform.app.InstrumentationRegistry 6 | import io.anyline2.sdk.ScanViewConfigHolder 7 | import org.json.JSONObject 8 | import org.junit.Before 9 | import org.junit.Test 10 | import org.junit.runner.RunWith 11 | import java.io.File 12 | import java.io.IOException 13 | 14 | @RunWith(AndroidJUnit4ClassRunner::class) 15 | class ViewConfigTest { 16 | private val instrumentation = InstrumentationRegistry.getInstrumentation() 17 | private lateinit var context: Context 18 | @Before 19 | fun setUp() { 20 | context = instrumentation.targetContext.applicationContext 21 | } 22 | 23 | @Test 24 | fun validateViewConfigs() { 25 | validateAllViewConfigsInAssetsSubFolder("viewConfigs") 26 | } 27 | 28 | private fun validateAllViewConfigsInAssetsSubFolder(assetsSubFolder: String) { 29 | listAssetFiles(assetsSubFolder) { isDir, path -> 30 | if (!isDir) { 31 | val fileContent = context.assets.open(path).bufferedReader().use { 32 | it.readText() 33 | } 34 | val jsonObject = JSONObject(fileContent) 35 | 36 | val validationResult = ScanViewConfigHolder.validateJsonObject(context, jsonObject) 37 | when (validationResult) { 38 | is ScanViewConfigHolder.ScanViewJsonValidationResult.ValidationSucceeded -> 39 | assert(true) { 40 | "file $path contains a valid ScanViewConfig" 41 | } 42 | is ScanViewConfigHolder.ScanViewJsonValidationResult.ValidationFailed -> 43 | assert(false) { 44 | "file $path does not contain a valid ScanViewConfig: ${validationResult.exception.message}" 45 | } 46 | } 47 | } 48 | } 49 | } 50 | 51 | private fun listAssetFiles(path: String, block: (isDir: Boolean, path: String) -> Unit): Boolean { 52 | try { 53 | val list = context.assets.list(path) 54 | list?.also { files-> 55 | if (files.isNotEmpty()) { 56 | for (file in files) { 57 | val relativePath = if (path.isEmpty()) file else "$path${File.separatorChar}$file" 58 | if (!listAssetFiles(relativePath, block)) 59 | block.invoke(false, relativePath) else block.invoke(true, relativePath) 60 | } 61 | } else return false 62 | } 63 | } catch (e: IOException) { 64 | return false 65 | } 66 | return true 67 | } 68 | } -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 20 | 24 | 28 | 32 | 36 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigEditor/json-editor-css.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ViewConfig JSON Editor 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 47 | 48 | 49 |
50 |
51 |
52 | 53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | 61 |
62 |
63 | 72 |
73 | 74 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/barcode_config_barcode.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for scanning single barcodes with a cutout. All formats enabled.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "auto", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Barcode|Barcodes", 13 | "barcodeConfig": { 14 | "fastProcessMode": true, 15 | "barcodeFormats": [ 16 | "ALL" 17 | ], 18 | "parseAAMVA": true 19 | }, 20 | "cancelOnResult": false 21 | }, 22 | "cutoutConfig": { 23 | "maxWidthPercent": "80%", 24 | "maxHeightPercent": "80%", 25 | "alignment": "center", 26 | "ratioFromSize": { 27 | "width": 100, 28 | "height": 80 29 | }, 30 | "strokeWidth": 1, 31 | "cornerRadius": 3, 32 | "strokeColor": "FFFFFF", 33 | "outerColor": "000000", 34 | "outerAlpha": 0.3, 35 | "feedbackStrokeColor": "0099FF" 36 | }, 37 | "scanFeedbackConfig": { 38 | "style": "rect", 39 | "strokeColor": "0099FF", 40 | "fillColor": "220099FF", 41 | "animationDuration": 150, 42 | "blinkAnimationOnResult": true, 43 | "beepOnResult": true, 44 | "vibrateOnResult": true 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/barcode_config_multi_barcode.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for full frame scanning of multiple barcodes simultaneously. All formats enabled.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "auto", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Barcode|Barcodes", 13 | "barcodeConfig": { 14 | "fastProcessMode": true, 15 | "barcodeFormats": [ 16 | "ALL" 17 | ], 18 | "parseAAMVA": true, 19 | "multiBarcode": true 20 | }, 21 | "cancelOnResult": false 22 | }, 23 | "scanFeedbackConfig": { 24 | "style": "rect", 25 | "strokeColor": "0099FF", 26 | "fillColor": "220099FF", 27 | "animationDuration": 150, 28 | "blinkAnimationOnResult": true, 29 | "beepOnResult": true, 30 | "vibrateOnResult": false 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/barcode_config_overlays.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for demonstrating overlay feature for scanning of multiple barcodes simultaneously. All formats enabled.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "auto", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Barcode|Barcodes", 13 | "barcodeConfig": { 14 | "fastProcessMode": true, 15 | "barcodeFormats": [ 16 | "ALL" 17 | ], 18 | "parseAAMVA": true, 19 | "multiBarcode": true 20 | }, 21 | "cancelOnResult": false 22 | }, 23 | "cutoutConfig": { 24 | "maxWidthPercent": "90%", 25 | "maxHeightPercent": "85%", 26 | "alignment": "center", 27 | "strokeWidth": 3, 28 | "cornerRadius": 2, 29 | "strokeColor": "FFFFFF", 30 | "outerColor": "000000", 31 | "outerAlpha": 0.5, 32 | "feedbackStrokeColor": "0099FF" 33 | }, 34 | "uiFeedbackConfig": { 35 | "presets": [ 36 | { 37 | "presetName": "simple_instruction_label", 38 | "presetAttributes": [ 39 | { 40 | "attributeName": "instruction_text", 41 | "attributeValue": "Tap on a barcode to select it, tap again to unselect" 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/barcode_config_overlays_visualfeedback.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for demonstrating overlay + visual feedback feature for scanning of multiple barcodes simultaneously. All formats enabled.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "auto", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Barcode|Barcodes", 13 | "barcodeConfig": { 14 | "fastProcessMode": true, 15 | "barcodeFormats": [ 16 | "ALL" 17 | ], 18 | "parseAAMVA": true, 19 | "multiBarcode": true 20 | }, 21 | "cancelOnResult": false 22 | }, 23 | "cutoutConfig": { 24 | "maxWidthPercent": "90%", 25 | "maxHeightPercent": "85%", 26 | "alignment": "center", 27 | "strokeWidth": 3, 28 | "cornerRadius": 2, 29 | "strokeColor": "FFFFFF", 30 | "outerColor": "000000", 31 | "outerAlpha": 0.5, 32 | "feedbackStrokeColor": "0099FF" 33 | }, 34 | "scanFeedbackConfig": { 35 | "style": "rect", 36 | "strokeWidth": 2, 37 | "strokeColor": "3C3C43", 38 | "fillColor": "223C3C43", 39 | "animationDuration": 150, 40 | "blinkAnimationOnResult": false, 41 | "beepOnResult": false, 42 | "vibrateOnResult": false 43 | }, 44 | "uiFeedbackConfig": { 45 | "presets": [ 46 | { 47 | "presetName": "simple_instruction_label", 48 | "presetAttributes": [ 49 | { 50 | "attributeName": "instruction_text", 51 | "attributeValue": "Tap on a barcode to select it, tap again to unselect" 52 | } 53 | ] 54 | } 55 | ] 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/custom_script_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Demo config for scanning using custom script.", 3 | "cameraConfig": { 4 | "captureResolution": "1080" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Cattle Tags", 13 | "ocrConfig": { 14 | "scanMode": "auto", 15 | "customCmdFile": "cow.ale" 16 | }, 17 | "cancelOnResult": true 18 | }, 19 | "cutoutConfig": { 20 | "maxWidthPercent": "80%", 21 | "maxHeightPercent": "80%", 22 | "alignment": "center", 23 | "width": 600, 24 | "ratioFromSize": { 25 | "width": 1, 26 | "height": 1 27 | }, 28 | "strokeWidth": 2, 29 | "cornerRadius": 10, 30 | "strokeColor": "FFFFFF", 31 | "outerColor": "000000", 32 | "outerAlpha": 0.3, 33 | "feedbackStrokeColor": "0099FF", 34 | "cropPadding": { 35 | "x": 60, 36 | "y": 60 37 | }, 38 | "cropOffset": { 39 | "x": 0, 40 | "y": 0 41 | } 42 | }, 43 | "scanFeedbackConfig": { 44 | "style": "rect", 45 | "strokeWidth": 2, 46 | "strokeColor": "0099FF", 47 | "fillColor": "330099FF", 48 | "cornerRadius": 0, 49 | "beepOnResult": true, 50 | "vibrateOnResult": true, 51 | "blinkAnimationOnResult": true 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/id_config_arabic_id.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for Arabic script ID scanning, includes all layouts with full configurability to include or exclude specific layouts as needed.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "zoomGesture": true 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginConfig": { 12 | "pluginConfig": { 13 | "id": "ID|Arabic IDs", 14 | "cancelOnResult": true, 15 | "universalIdConfig": { 16 | "faceDetectionEnabled": true, 17 | "allowedLayouts": { 18 | "mrz": [], 19 | "idFront": [], 20 | "drivingLicense": [] 21 | }, 22 | "alphabet": "arabic", 23 | "idFront": { 24 | "fullName": { 25 | "scanOption": "mandatory", 26 | "minConfidence": 60 27 | }, 28 | "dateOfBirth": { 29 | "scanOption": "mandatory", 30 | "minConfidence": 60 31 | }, 32 | "placeOfBirth": { 33 | "scanOption": "optional", 34 | "minConfidence": 60 35 | }, 36 | "dateOfExpiry": { 37 | "scanOption": "optional", 38 | "minConfidence": 60 39 | }, 40 | "documentNumber": { 41 | "scanOption": "mandatory", 42 | "minConfidence": 60 43 | }, 44 | "nationality": { 45 | "scanOption": "optional", 46 | "minConfidence": 60 47 | } 48 | }, 49 | "drivingLicense": { 50 | "fullName": { 51 | "scanOption": "mandatory", 52 | "minConfidence": 60 53 | }, 54 | "dateOfBirth": { 55 | "scanOption": "mandatory", 56 | "minConfidence": 60 57 | }, 58 | "placeOfBirth": { 59 | "scanOption": "optional", 60 | "minConfidence": 60 61 | }, 62 | "dateOfExpiry": { 63 | "scanOption": "optional", 64 | "minConfidence": 60 65 | }, 66 | "documentNumber": { 67 | "scanOption": "mandatory", 68 | "minConfidence": 60 69 | } 70 | } 71 | } 72 | }, 73 | "cutoutConfig": { 74 | "maxWidthPercent": "90%", 75 | "maxHeightPercent": "90%", 76 | "alignment": "center", 77 | "strokeWidth": 2, 78 | "cornerRadius": 8, 79 | "strokeColor": "FFFFFF", 80 | "outerColor": "000000", 81 | "outerAlpha": 0.3, 82 | "ratioFromSize": { 83 | "width": 50, 84 | "height": 31 85 | }, 86 | "cropPadding": { 87 | "x": -50, 88 | "y": -50 89 | }, 90 | "cropOffset": { 91 | "x": 0, 92 | "y": 0 93 | }, 94 | "feedbackStrokeColor": "0099FF" 95 | }, 96 | "scanFeedbackConfig": { 97 | "style": "contour_rect", 98 | "redrawTimeout": 100, 99 | "strokeColor": "0099FF", 100 | "fillColor": "220099FF", 101 | "beepOnResult": true, 102 | "vibrateOnResult": true, 103 | "strokeWidth": 2 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/id_config_cyrillic_id.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for Cyrillic script ID scanning, includes all layouts with full configurability to include or exclude specific layouts as needed.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "zoomGesture": true 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginConfig": { 12 | "pluginConfig": { 13 | "id": "ID|Cyrillic IDs", 14 | "cancelOnResult": true, 15 | "universalIdConfig": { 16 | "faceDetectionEnabled": true, 17 | "allowedLayouts": { 18 | "mrz": [], 19 | "drivingLicense": [], 20 | "idFront": [] 21 | }, 22 | "alphabet": "cyrillic", 23 | "drivingLicense": { 24 | "lastName": { 25 | "scanOption": "mandatory", 26 | "minConfidence": 40 27 | }, 28 | "firstName": { 29 | "scanOption": "mandatory", 30 | "minConfidence": 40 31 | }, 32 | "dateOfBirth": { 33 | "scanOption": "mandatory", 34 | "minConfidence": 50 35 | }, 36 | "placeOfBirth": { 37 | "scanOption": "optional", 38 | "minConfidence": 50 39 | }, 40 | "dateOfIssue": { 41 | "scanOption": "mandatory", 42 | "minConfidence": 50 43 | }, 44 | "dateOfExpiry": { 45 | "scanOption": "optional", 46 | "minConfidence": 50 47 | }, 48 | "authority": { 49 | "scanOption": "optional", 50 | "minConfidence": 30 51 | }, 52 | "documentNumber": { 53 | "scanOption": "mandatory", 54 | "minConfidence": 40 55 | }, 56 | "address": { 57 | "scanOption": "optional" 58 | } 59 | }, 60 | "idFront": { 61 | "lastName": { 62 | "scanOption": "mandatory", 63 | "minConfidence": 40 64 | }, 65 | "firstName": { 66 | "scanOption": "mandatory", 67 | "minConfidence": 40 68 | }, 69 | "dateOfBirth": { 70 | "scanOption": "mandatory", 71 | "minConfidence": 50 72 | }, 73 | "placeOfBirth": { 74 | "scanOption": "optional", 75 | "minConfidence": 50 76 | }, 77 | "dateOfIssue": { 78 | "scanOption": "mandatory", 79 | "minConfidence": 50 80 | }, 81 | "dateOfExpiry": { 82 | "scanOption": "optional", 83 | "minConfidence": 50 84 | }, 85 | "authority": { 86 | "scanOption": "optional", 87 | "minConfidence": 30 88 | }, 89 | "documentNumber": { 90 | "scanOption": "mandatory", 91 | "minConfidence": 40 92 | }, 93 | "address": { 94 | "scanOption": "optional" 95 | }, 96 | "nationality": { 97 | "scanOption": "optional" 98 | } 99 | } 100 | } 101 | }, 102 | "cutoutConfig": { 103 | "maxWidthPercent": "90%", 104 | "maxHeightPercent": "90%", 105 | "alignment": "center", 106 | "strokeWidth": 2, 107 | "cornerRadius": 8, 108 | "strokeColor": "FFFFFF", 109 | "outerColor": "000000", 110 | "outerAlpha": 0.3, 111 | "ratioFromSize": { 112 | "width": 50, 113 | "height": 31 114 | }, 115 | "cropPadding": { 116 | "x": -50, 117 | "y": -50 118 | }, 119 | "cropOffset": { 120 | "x": 0, 121 | "y": 0 122 | }, 123 | "feedbackStrokeColor": "0099FF" 124 | }, 125 | "scanFeedbackConfig": { 126 | "style": "contour_rect", 127 | "redrawTimeout": 100, 128 | "strokeColor": "0099FF", 129 | "fillColor": "220099FF", 130 | "beepOnResult": true, 131 | "vibrateOnResult": true, 132 | "strokeWidth": 2 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/id_config_mrz.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for MRZ and passports scanning.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "ID|MRZ & Passports", 13 | "cancelOnResult": true, 14 | "mrzConfig": { 15 | "faceDetectionEnabled": true, 16 | "mrzFieldScanOptions": { 17 | "vizAddress": "optional", 18 | "vizDateOfIssue": "optional" 19 | }, 20 | "cropAndTransformID": false, 21 | "strictMode": false 22 | } 23 | }, 24 | "cutoutConfig": { 25 | "maxWidthPercent": "90%", 26 | "maxHeightPercent": "90%", 27 | "alignment": "center", 28 | "strokeWidth": 2, 29 | "cornerRadius": 4, 30 | "strokeColor": "FFFFFF", 31 | "outerColor": "000000", 32 | "outerAlpha": 0.3, 33 | "cropPadding": { 34 | "x": -30, 35 | "y": -90 36 | }, 37 | "cropOffset": { 38 | "x": 0, 39 | "y": 90 40 | }, 41 | "ratioFromSize": { 42 | "width": 50, 43 | "height": 31 44 | }, 45 | "feedbackStrokeColor": "0099FF" 46 | }, 47 | "scanFeedbackConfig": { 48 | "style": "rect", 49 | "redrawTimeout": 100, 50 | "strokeColor": "0099FF", 51 | "fillColor": "220099FF", 52 | "beepOnResult": true, 53 | "vibrateOnResult": true, 54 | "strokeWidth": 2 55 | } 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/id_config_mrz_frontcam.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for MRZ and passports scanning using the device front camera.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "pictureResolution": "1080p", 6 | "zoomGesture": true, 7 | "defaultCamera": "front" 8 | }, 9 | "viewPluginConfig": { 10 | "pluginConfig": { 11 | "id": "mrz", 12 | "mrzConfig": { 13 | "strictMode": false, 14 | "cropAndTransformID": false 15 | } 16 | }, 17 | "cutoutConfig": { 18 | "maxWidthPercent": "90%", 19 | "maxHeightPercent": "90%", 20 | "alignment": "center", 21 | "strokeWidth": 2, 22 | "cornerRadius": 4, 23 | "strokeColor": "FFFFFF", 24 | "outerColor": "000000", 25 | "outerAlpha": 0.3, 26 | "cropPadding": { 27 | "x": -30, 28 | "y": -90 29 | }, 30 | "cropOffset": { 31 | "x": 0, 32 | "y": 90 33 | }, 34 | "ratioFromSize": { 35 | "width": 50, 36 | "height": 31 37 | }, 38 | "feedbackStrokeColor": "0099FF" 39 | }, 40 | "scanFeedbackConfig": { 41 | "style": "rect", 42 | "strokeWidth": 2, 43 | "strokeColor": "0099FF", 44 | "fillColor": "220099FF", 45 | "beepOnResult": false, 46 | "vibrateOnResult": false, 47 | "blinkAnimationOnResult": false 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/id_config_universal_id.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for Latin script ID scanning, includes all layouts with full configurability to include or exclude specific layouts as needed.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "zoomGesture": true 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginConfig": { 12 | "pluginConfig": { 13 | "id": "ID|Universal IDs", 14 | "cancelOnResult": true, 15 | "universalIdConfig": { 16 | "faceDetectionEnabled": true, 17 | "allowedLayouts": { 18 | "mrz": [], 19 | "drivingLicense": [], 20 | "idFront": [], 21 | "insuranceCard": [] 22 | } 23 | } 24 | }, 25 | "cutoutConfig": { 26 | "maxWidthPercent": "90%", 27 | "maxHeightPercent": "90%", 28 | "alignment": "center", 29 | "strokeWidth": 2, 30 | "cornerRadius": 8, 31 | "strokeColor": "FFFFFF", 32 | "outerColor": "000000", 33 | "outerAlpha": 0.3, 34 | "ratioFromSize": { 35 | "width": 50, 36 | "height": 31 37 | }, 38 | "cropPadding": { 39 | "x": -50, 40 | "y": -50 41 | }, 42 | "cropOffset": { 43 | "x": 0, 44 | "y": 0 45 | }, 46 | "feedbackStrokeColor": "0099FF" 47 | }, 48 | "scanFeedbackConfig": { 49 | "style": "contour_rect", 50 | "redrawTimeout": 100, 51 | "strokeColor": "0099FF", 52 | "fillColor": "220099FF", 53 | "beepOnResult": true, 54 | "vibrateOnResult": true, 55 | "strokeWidth": 2 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/meter_config_analog_digital.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for analog and digital meters.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "pictureResolution": "1080p" 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginConfig": { 12 | "pluginConfig": { 13 | "id": "Meter|Analog/Digital Auto", 14 | "meterConfig": { 15 | "scanMode": "auto_analog_digital_meter" 16 | }, 17 | "cancelOnResult": true 18 | }, 19 | "cutoutConfig": { 20 | "alignment": "top", 21 | "strokeWidth": 2, 22 | "strokeColor": "FFFFFF", 23 | "cornerRadius": 4, 24 | "outerColor": "000000", 25 | "outerAlpha": 0.5, 26 | "feedbackStrokeColor": "0099FF", 27 | "maxWidthPercent": "85%", 28 | "maxHeightPercent": "85%", 29 | "ratioFromSize": { 30 | "width": 2, 31 | "height": 1 32 | }, 33 | "offset": { 34 | "x": 0, 35 | "y": 120 36 | } 37 | }, 38 | "scanFeedbackConfig": { 39 | "style": "contour_rect", 40 | "strokeColor": "0099FF", 41 | "strokeWidth": 2, 42 | "fillColor": "220099FF", 43 | "cornerRadius": 2, 44 | "redrawTimeout": 200, 45 | "animationDuration": 75, 46 | "blinkAnimationOnResult": true, 47 | "beepOnResult": true, 48 | "vibrateOnResult": true 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/meter_config_serial_number.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for scanning meter serial numbers.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Meter Serial Numbers", 13 | "ocrConfig": {}, 14 | "startScanDelay": 1000, 15 | "cancelOnResult": true 16 | }, 17 | "cutoutConfig": { 18 | "alignment": "top_half", 19 | "maxWidthPercent": "80%", 20 | "maxHeightPercent": "80%", 21 | "ratioFromSize": { 22 | "width": 720, 23 | "height": 360 24 | }, 25 | "strokeWidth": 2, 26 | "strokeColor": "FFFFFF", 27 | "cornerRadius": 4, 28 | "outerColor": "000000", 29 | "outerAlpha": 0.5, 30 | "feedbackStrokeColor": "0099FF", 31 | "offset": { 32 | "x": 0, 33 | "y": -15 34 | } 35 | }, 36 | "scanFeedbackConfig": { 37 | "style": "contour_rect", 38 | "strokeColor": "0099FF", 39 | "fillColor": "220099FF", 40 | "beepOnResult": true, 41 | "vibrateOnResult": true, 42 | "blinkAnimationOnResult": true 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/ocr_config_shipping_container_horizontal.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for scanning horizontal containers.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Container|Horizontal Shipping Containers", 13 | "cancelOnResult": true, 14 | "containerConfig": { 15 | "scanMode": "HORIZONTAL" 16 | } 17 | }, 18 | "cutoutConfig": { 19 | "maxWidthPercent": "80%", 20 | "maxHeightPercent": "80%", 21 | "alignment": "top_half", 22 | "ratioFromSize": { 23 | "width": 5, 24 | "height": 1 25 | }, 26 | "strokeWidth": 2, 27 | "strokeColor": "FFFFFF", 28 | "cornerRadius": 4, 29 | "outerColor": "000000", 30 | "outerAlpha": 0.5, 31 | "feedbackStrokeColor": "0099FF", 32 | "offset": { 33 | "x": 0, 34 | "y": -15 35 | }, 36 | "cropOffset": { 37 | "x": 0, 38 | "y": -15 39 | } 40 | }, 41 | "scanFeedbackConfig": { 42 | "style": "contour_rect", 43 | "strokeColor": "0099FF", 44 | "fillColor": "220099FF", 45 | "blinkAnimationOnResult": true, 46 | "beepOnResult": true, 47 | "vibrateOnResult": true 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/ocr_config_shipping_container_vertical.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for scanning vertical containers.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Container|Vertical Shipping Containers", 13 | "containerConfig": { 14 | "scanMode": "VERTICAL" 15 | }, 16 | "cancelOnResult": true 17 | }, 18 | "cutoutConfig": { 19 | "maxWidthPercent": "10%", 20 | "alignment": "center", 21 | "ratioFromSize": { 22 | "width": 0.15, 23 | "height": 1.00 24 | }, 25 | "strokeWidth": 2, 26 | "strokeColor": "FFFFFF", 27 | "cornerRadius": 4, 28 | "outerColor": "000000", 29 | "outerAlpha": 0.5, 30 | "feedbackStrokeColor": "0099FF", 31 | "offset": { 32 | "x": 0, 33 | "y": -15 34 | }, 35 | "cropOffset": { 36 | "x": 0, 37 | "y": -15 38 | } 39 | }, 40 | "scanFeedbackConfig": { 41 | "style": "contour_rect", 42 | "strokeColor": "0099FF", 43 | "fillColor": "220099FF", 44 | "blinkAnimationOnResult": true, 45 | "beepOnResult": true, 46 | "vibrateOnResult": true 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/ocr_config_vin.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for vehicle identification numbers (VIN).", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Vehicle|Vehicle Identification Numbers", 13 | "vinConfig": {}, 14 | "cancelOnResult": true 15 | }, 16 | "cutoutConfig": { 17 | "alignment": "top_half", 18 | "maxWidthPercent": "70%", 19 | "maxHeightPercent": "70%", 20 | "ratioFromSize": { 21 | "width": 689, 22 | "height": 100 23 | }, 24 | "strokeWidth": 1, 25 | "strokeColor": "FFFFFF", 26 | "cornerRadius": 2, 27 | "outerColor": "000000", 28 | "outerAlpha": 0.3, 29 | "feedbackStrokeColor": "0099FF" 30 | }, 31 | "scanFeedbackConfig": { 32 | "animation": "traverse_multi", 33 | "animationDuration": 250, 34 | "style": "contour_rect", 35 | "strokeWidth": 2, 36 | "strokeColor": "0099FF", 37 | "beepOnResult": false, 38 | "vibrateOnResult": true, 39 | "blinkAnimationOnResult": true 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/ocr_config_vin_with_uifeedback.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for vehicle identification numbers (VIN).", 3 | "cameraConfig": { 4 | "captureResolution": "1080p" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Vehicle|Vehicle Identification Numbers", 13 | "vinConfig": { 14 | "validateCheckDigit": true 15 | }, 16 | "cancelOnResult": true 17 | }, 18 | "cutoutConfig": { 19 | "alignment": "top_half", 20 | "maxWidthPercent": "70%", 21 | "maxHeightPercent": "70%", 22 | "ratioFromSize": { 23 | "width": 689, 24 | "height": 100 25 | }, 26 | "strokeWidth": 1, 27 | "strokeColor": "FFFFFF", 28 | "cornerRadius": 2, 29 | "outerColor": "000000", 30 | "outerAlpha": 0.3, 31 | "feedbackStrokeColor": "0099FF" 32 | }, 33 | "scanFeedbackConfig": { 34 | "animation": "traverse_multi", 35 | "animationDuration": 250, 36 | "style": "contour_rect", 37 | "strokeWidth": 2, 38 | "strokeColor": "0099FF", 39 | "beepOnResult": false, 40 | "vibrateOnResult": true, 41 | "blinkAnimationOnResult": true 42 | }, 43 | "uiFeedbackConfig": { 44 | "presets": [ 45 | { 46 | "presetName": "vin_with_instruction_image_text_sound_feedback", 47 | "presetAttributes": [ 48 | { 49 | "attributeName": "instruction_text", 50 | "attributeValue": "Please make sure the entire VIN number is inside the cutout." 51 | }, 52 | { 53 | "attributeName": "lighting_toodark_image", 54 | "attributeValue": "uifeedback_default_toodark" 55 | }, 56 | { 57 | "attributeName": "lighting_toobright_image", 58 | "attributeValue": "uifeedback_default_toobright" 59 | }, 60 | { 61 | "attributeName": "distance_moveback_image", 62 | "attributeValue": "uifeedback_default_moveback" 63 | }, 64 | { 65 | "attributeName": "distance_movecloser_image", 66 | "attributeValue": "uifeedback_default_movecloser" 67 | }, 68 | { 69 | "attributeName": "format_invalid_image", 70 | "attributeValue": "uifeedback_vin_invalid" 71 | }, 72 | { 73 | "attributeName": "lighting_toodark_text", 74 | "attributeValue": "" 75 | }, 76 | { 77 | "attributeName": "lighting_toobright_text", 78 | "attributeValue": "" 79 | }, 80 | { 81 | "attributeName": "distance_moveback_text", 82 | "attributeValue": "" 83 | }, 84 | { 85 | "attributeName": "distance_movecloser_text", 86 | "attributeValue": "" 87 | }, 88 | { 89 | "attributeName": "format_invalid_text", 90 | "attributeValue": "" 91 | }, 92 | { 93 | "attributeName": "lighting_toodark_sound", 94 | "attributeValue": "info_sound_default.wav" 95 | }, 96 | { 97 | "attributeName": "lighting_toobright_sound", 98 | "attributeValue": "info_sound_default.wav" 99 | }, 100 | { 101 | "attributeName": "distance_moveback_sound", 102 | "attributeValue": "info_sound_default.wav" 103 | }, 104 | { 105 | "attributeName": "distance_movecloser_sound", 106 | "attributeValue": "info_sound_default.wav" 107 | }, 108 | { 109 | "attributeName": "format_invalid_sound", 110 | "attributeValue": "info_sound_default.wav" 111 | } 112 | ] 113 | } 114 | ] 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/odometer_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for Odometer.", 3 | "cameraConfig":{ 4 | "captureResolution" : "1080p", 5 | "zoomGesture": true 6 | }, 7 | "flashConfig" : { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginConfig" : { 12 | "pluginConfig" : { 13 | "id" : "Odometer", 14 | "odometerConfig" : { 15 | 16 | }, 17 | "cancelOnResult" : true 18 | }, 19 | "cutoutConfig" : { 20 | "alignment" : "top", 21 | "strokeWidth" : 2, 22 | "strokeColor" : "FFFFFF", 23 | "cornerRadius" : 4, 24 | "outerColor" : "000000", 25 | "outerAlpha" : 0.5, 26 | "feedbackStrokeColor" : "0099FF", 27 | "maxWidthPercent": "85%", 28 | "maxHeightPercent": "85%", 29 | "ratioFromSize": { 30 | "width": 2.75, 31 | "height": 1 32 | }, 33 | "cropOffset": { 34 | "x": 0, 35 | "y": 120 36 | }, 37 | "offset": { 38 | "x": 0, 39 | "y": 120 40 | } 41 | }, 42 | "scanFeedbackConfig" : { 43 | "style" : "contour_rect", 44 | "strokeColor" : "0099FF", 45 | "blinkAnimationOnResult": true, 46 | "beepOnResult": true, 47 | "vibrateOnResult": true 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/tire_commercial_tire_id.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for Commercial Tire with upside down support.", 3 | "cameraConfig": { 4 | "captureResolution": "1080" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Tire|Commercial Tire ID", 13 | "startScanDelay": 1000, 14 | "cancelOnResult": true, 15 | "commercialTireIdConfig": { 16 | "upsideDownMode": "AUTO", 17 | "minConfidence": 0 18 | } 19 | }, 20 | "cutoutConfig": { 21 | "alignment": "center", 22 | "maxWidthPercent": "60%", 23 | "maxHeightPercent": "60%", 24 | "ratioFromSize": { 25 | "width": 5, 26 | "height": 1 27 | }, 28 | "strokeWidth": 2, 29 | "strokeColor": "FFFFFF", 30 | "cornerRadius": 4, 31 | "outerColor": "000000", 32 | "outerAlpha": 0.5, 33 | "feedbackStrokeColor": "0099FF", 34 | "offset": { 35 | "x": 0, 36 | "y": 0 37 | } 38 | }, 39 | "scanFeedbackConfig": { 40 | "animation": "traverse_multi", 41 | "animationDuration": 250, 42 | "style": "contour_rect", 43 | "strokeWidth": 2, 44 | "strokeColor": "0099FF", 45 | "beepOnResult": false, 46 | "vibrateOnResult": true, 47 | "blinkAnimationOnResult": true 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/tire_config_tin_dot_with_uifeedback.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for DOT numbers with upside down support and UI feedback.", 3 | "cameraConfig": { 4 | "captureResolution": "1080" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Tire|TIN DOT Numbers", 13 | "tinConfig": { 14 | "scanMode": "DOT", 15 | "upsideDownMode": "AUTO" 16 | }, 17 | "cancelOnResult": true 18 | }, 19 | "cutoutConfig": { 20 | "alignment": "center", 21 | "maxWidthPercent": "60%", 22 | "maxHeightPercent": "60%", 23 | "ratioFromSize": { 24 | "width": 6.25, 25 | "height": 1 26 | }, 27 | "strokeWidth": 2, 28 | "strokeColor": "FFFFFF", 29 | "cornerRadius": 4, 30 | "outerColor": "000000", 31 | "outerAlpha": 0.5, 32 | "feedbackStrokeColor": "0099FF", 33 | "offset": { 34 | "x": 0, 35 | "y": -15 36 | } 37 | }, 38 | "scanFeedbackConfig": { 39 | "animation": "traverse_multi", 40 | "animationDuration": 250, 41 | "style": "contour_rect", 42 | "strokeWidth": 2, 43 | "strokeColor": "0099FF", 44 | "beepOnResult": false, 45 | "vibrateOnResult": true, 46 | "blinkAnimationOnResult": true 47 | }, 48 | "uiFeedbackConfig": { 49 | "presets": [ 50 | { 51 | "presetName": "tin_with_instruction_overlay_image_text_sound_feedback", 52 | "presetAttributes": [ 53 | { 54 | "attributeName": "instruction_text", 55 | "attributeValue": "Please make sure the entire DOT number is inside the cutout." 56 | }, 57 | { 58 | "attributeName": "left_overlay_image", 59 | "attributeValue": "dot_overlay" 60 | }, 61 | { 62 | "attributeName": "lighting_toodark_image", 63 | "attributeValue": "uifeedback_default_toodark" 64 | }, 65 | { 66 | "attributeName": "lighting_toobright_image", 67 | "attributeValue": "uifeedback_default_toobright" 68 | }, 69 | { 70 | "attributeName": "distance_moveback_image", 71 | "attributeValue": "uifeedback_default_moveback" 72 | }, 73 | { 74 | "attributeName": "distance_movecloser_image", 75 | "attributeValue": "uifeedback_default_movecloser" 76 | }, 77 | { 78 | "attributeName": "format_wrong_image", 79 | "attributeValue": "uifeedback_tin_wrongformat" 80 | }, 81 | { 82 | "attributeName": "date_wrong_image", 83 | "attributeValue": "uifeedback_tin_wrongformat" 84 | }, 85 | { 86 | "attributeName": "lighting_toodark_text", 87 | "attributeValue": "" 88 | }, 89 | { 90 | "attributeName": "lighting_toobright_text", 91 | "attributeValue": "" 92 | }, 93 | { 94 | "attributeName": "distance_moveback_text", 95 | "attributeValue": "" 96 | }, 97 | { 98 | "attributeName": "distance_movecloser_text", 99 | "attributeValue": "" 100 | }, 101 | { 102 | "attributeName": "format_wrong_text", 103 | "attributeValue": "" 104 | }, 105 | { 106 | "attributeName": "date_wrong_text", 107 | "attributeValue": "" 108 | }, 109 | { 110 | "attributeName": "lighting_toodark_sound", 111 | "attributeValue": "info_sound_default.wav" 112 | }, 113 | { 114 | "attributeName": "lighting_toobright_sound", 115 | "attributeValue": "info_sound_default.wav" 116 | }, 117 | { 118 | "attributeName": "distance_moveback_sound", 119 | "attributeValue": "info_sound_default.wav" 120 | }, 121 | { 122 | "attributeName": "distance_movecloser_sound", 123 | "attributeValue": "info_sound_default.wav" 124 | }, 125 | { 126 | "attributeName": "format_wrong_sound", 127 | "attributeValue": "info_sound_default.wav" 128 | }, 129 | { 130 | "attributeName": "date_wrong_sound", 131 | "attributeValue": "info_sound_default.wav" 132 | } 133 | ] 134 | } 135 | ] 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/tire_config_tin_universal_with_uifeedback.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for Tire Identification Numbers (TIN) with upside down support and UI feedback.", 3 | "cameraConfig": { 4 | "captureResolution": "1080" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Tire|Universal TIN Numbers", 13 | "tinConfig": { 14 | "scanMode": "UNIVERSAL", 15 | "upsideDownMode": "AUTO" 16 | }, 17 | "cancelOnResult": true 18 | }, 19 | "cutoutConfig": { 20 | "alignment": "center", 21 | "maxWidthPercent": "60%", 22 | "maxHeightPercent": "60%", 23 | "ratioFromSize": { 24 | "width": 6.25, 25 | "height": 1 26 | }, 27 | "strokeWidth": 2, 28 | "strokeColor": "FFFFFF", 29 | "cornerRadius": 4, 30 | "outerColor": "000000", 31 | "outerAlpha": 0.5, 32 | "feedbackStrokeColor": "0099FF", 33 | "offset": { 34 | "x": 0, 35 | "y": -15 36 | } 37 | }, 38 | "scanFeedbackConfig": { 39 | "animation": "traverse_multi", 40 | "animationDuration": 250, 41 | "style": "contour_rect", 42 | "strokeWidth": 2, 43 | "strokeColor": "0099FF", 44 | "beepOnResult": false, 45 | "vibrateOnResult": true, 46 | "blinkAnimationOnResult": true 47 | }, 48 | "uiFeedbackConfig": { 49 | "presets": [ 50 | { 51 | "presetName": "tin_with_instruction_overlay_image_text_sound_feedback", 52 | "presetAttributes": [ 53 | { 54 | "attributeName": "instruction_text", 55 | "attributeValue": "Please make sure the entire TIN number is inside the cutout." 56 | }, 57 | { 58 | "attributeName": "left_overlay_image", 59 | "attributeValue": "" 60 | }, 61 | { 62 | "attributeName": "lighting_toodark_image", 63 | "attributeValue": "uifeedback_default_toodark" 64 | }, 65 | { 66 | "attributeName": "lighting_toobright_image", 67 | "attributeValue": "uifeedback_default_toobright" 68 | }, 69 | { 70 | "attributeName": "distance_moveback_image", 71 | "attributeValue": "uifeedback_default_moveback" 72 | }, 73 | { 74 | "attributeName": "distance_movecloser_image", 75 | "attributeValue": "uifeedback_default_movecloser" 76 | }, 77 | { 78 | "attributeName": "format_wrong_image", 79 | "attributeValue": "uifeedback_tin_wrongformat" 80 | }, 81 | { 82 | "attributeName": "date_wrong_image", 83 | "attributeValue": "uifeedback_tin_wrongformat" 84 | }, 85 | { 86 | "attributeName": "lighting_toodark_text", 87 | "attributeValue": "" 88 | }, 89 | { 90 | "attributeName": "lighting_toobright_text", 91 | "attributeValue": "" 92 | }, 93 | { 94 | "attributeName": "distance_moveback_text", 95 | "attributeValue": "" 96 | }, 97 | { 98 | "attributeName": "distance_movecloser_text", 99 | "attributeValue": "" 100 | }, 101 | { 102 | "attributeName": "format_wrong_text", 103 | "attributeValue": "" 104 | }, 105 | { 106 | "attributeName": "date_wrong_text", 107 | "attributeValue": "" 108 | }, 109 | { 110 | "attributeName": "lighting_toodark_sound", 111 | "attributeValue": "info_sound_default.wav" 112 | }, 113 | { 114 | "attributeName": "lighting_toobright_sound", 115 | "attributeValue": "info_sound_default.wav" 116 | }, 117 | { 118 | "attributeName": "distance_moveback_sound", 119 | "attributeValue": "info_sound_default.wav" 120 | }, 121 | { 122 | "attributeName": "distance_movecloser_sound", 123 | "attributeValue": "info_sound_default.wav" 124 | }, 125 | { 126 | "attributeName": "format_wrong_sound", 127 | "attributeValue": "info_sound_default.wav" 128 | }, 129 | { 130 | "attributeName": "date_wrong_sound", 131 | "attributeValue": "info_sound_default.wav" 132 | } 133 | ] 134 | } 135 | ] 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/tire_config_tire_make.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for Tire Make with upside down support.", 3 | "cameraConfig": { 4 | "captureResolution": "1080" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Tire|Tire Make", 13 | "tireMakeConfig": { 14 | "upsideDownMode": "AUTO" 15 | }, 16 | "cancelOnResult": true 17 | }, 18 | "cutoutConfig": { 19 | "alignment": "center", 20 | "maxWidthPercent": "60%", 21 | "maxHeightPercent": "60%", 22 | "ratioFromSize": { 23 | "width": 5, 24 | "height": 1 25 | }, 26 | "strokeWidth": 2, 27 | "strokeColor": "FFFFFF", 28 | "cornerRadius": 4, 29 | "outerColor": "000000", 30 | "outerAlpha": 0.5, 31 | "feedbackStrokeColor": "0099FF", 32 | "offset": { 33 | "x": 0, 34 | "y": -15 35 | } 36 | }, 37 | "scanFeedbackConfig": { 38 | "animation": "traverse_multi", 39 | "animationDuration": 250, 40 | "style": "contour_rect", 41 | "strokeWidth": 2, 42 | "strokeColor": "0099FF", 43 | "beepOnResult": false, 44 | "vibrateOnResult": true, 45 | "blinkAnimationOnResult": true 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/tire_config_tire_size.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for Tire Size with upside down support and instruction label.", 3 | "cameraConfig": { 4 | "captureResolution": "1080" 5 | }, 6 | "flashConfig": { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig": { 11 | "pluginConfig": { 12 | "id": "Tire|Tire Size Specifications", 13 | "tireSizeConfig": { 14 | "upsideDownMode": "AUTO" 15 | }, 16 | "startScanDelay": 1000, 17 | "cancelOnResult": true 18 | }, 19 | "cutoutConfig": { 20 | "alignment": "center", 21 | "maxWidthPercent": "60%", 22 | "maxHeightPercent": "60%", 23 | "ratioFromSize": { 24 | "width": 25, 25 | "height": 10 26 | }, 27 | "strokeWidth": 2, 28 | "strokeColor": "FFFFFF", 29 | "cornerRadius": 4, 30 | "outerColor": "000000", 31 | "outerAlpha": 0.5, 32 | "feedbackStrokeColor": "0099FF", 33 | "offset": { 34 | "x": 0, 35 | "y": -15 36 | } 37 | }, 38 | "scanFeedbackConfig": { 39 | "animation": "traverse_multi", 40 | "animationDuration": 250, 41 | "style": "contour_rect", 42 | "strokeWidth": 2, 43 | "strokeColor": "0099FF", 44 | "beepOnResult": false, 45 | "vibrateOnResult": true, 46 | "blinkAnimationOnResult": true 47 | }, 48 | "uiFeedbackConfig": { 49 | "presets": [ 50 | { 51 | "presetName": "simple_instruction_label", 52 | "presetAttributes": [ 53 | { 54 | "attributeName": "instruction_text", 55 | "attributeValue": "Look for a standardized number sequence, like 205/55 R16" 56 | } 57 | ] 58 | } 59 | ] 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/tire_size_tin_demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Demo config for scanning tire sizes and TINs in parallel.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "pictureResolution": "1080p" 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginCompositeConfig": { 12 | "id": "Workflows|TIN / Tire Size", 13 | "processingMode": "parallel", 14 | "viewPlugins": [ 15 | { 16 | "viewPluginConfig": { 17 | "pluginConfig": { 18 | "id": "Universal TIN", 19 | "tinConfig": { 20 | "scanMode": "DOT", 21 | "upsideDownMode": "AUTO" 22 | }, 23 | "cancelOnResult": true 24 | }, 25 | "cutoutConfig": { 26 | "alignment": "center", 27 | "maxWidthPercent": "60%", 28 | "maxHeightPercent": "60%", 29 | "ratioFromSize": { 30 | "width": 5, 31 | "height": 1 32 | }, 33 | "strokeWidth": 2, 34 | "strokeColor": "FFFFFF", 35 | "cornerRadius": 4, 36 | "outerColor": "000000", 37 | "outerAlpha": 0.5, 38 | "feedbackStrokeColor": "0099FF", 39 | "offset": { 40 | "x": 0, 41 | "y": -15 42 | } 43 | }, 44 | "scanFeedbackConfig": { 45 | "animation": "traverse_multi", 46 | "animationDuration": 250, 47 | "style": "rect", 48 | "strokeWidth": 0, 49 | "strokeColor": "FF2746FF", 50 | "fillColor": "222746FF", 51 | "beepOnResult": false, 52 | "vibrateOnResult": true, 53 | "blinkAnimationOnResult": true 54 | }, 55 | "uiFeedbackConfig": { 56 | "presets": [ 57 | { 58 | "presetName": "simple_instruction_label", 59 | "presetAttributes": [ 60 | { 61 | "attributeName": "instruction_text", 62 | "attributeValue": "Position the data you wish to scan within the central cutout." 63 | } 64 | ] 65 | } 66 | ], 67 | "elements": [ 68 | { 69 | "presets": [ 70 | { 71 | "presetName": "cutout_bottom_image_element", 72 | "presetAttributes": [ 73 | { 74 | "attributeName": "image", 75 | "attributeValue": "uifeedback_inprogress_tire_tin" 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | ] 82 | } 83 | } 84 | }, 85 | { 86 | "viewPluginConfig": { 87 | "pluginConfig": { 88 | "id": "Tire Size", 89 | "tireSizeConfig": { 90 | "upsideDownMode": "AUTO" 91 | }, 92 | "cancelOnResult": true 93 | }, 94 | "cutoutConfig": { 95 | "alignment": "center", 96 | "maxWidthPercent": "60%", 97 | "maxHeightPercent": "60%", 98 | "ratioFromSize": { 99 | "width": 5, 100 | "height": 1 101 | }, 102 | "strokeWidth": 2, 103 | "strokeColor": "FFFFFF", 104 | "cornerRadius": 4, 105 | "outerColor": "000000", 106 | "outerAlpha": 0.5, 107 | "feedbackStrokeColor": "0099FF", 108 | "offset": { 109 | "x": 0, 110 | "y": -15 111 | } 112 | }, 113 | "scanFeedbackConfig": { 114 | "animation": "traverse_multi", 115 | "animationDuration": 250, 116 | "style": "contour_rect", 117 | "strokeWidth": 0, 118 | "strokeColor": "FFC2E6FF", 119 | "fillColor": "22C2E6FF", 120 | "beepOnResult": false, 121 | "vibrateOnResult": true, 122 | "blinkAnimationOnResult": true 123 | }, 124 | "uiFeedbackConfig": { 125 | "presets": [ 126 | { 127 | "presetName": "simple_instruction_label", 128 | "presetAttributes": [ 129 | { 130 | "attributeName": "instruction_text", 131 | "attributeValue": "Position the data you wish to scan within the central cutout." 132 | } 133 | ] 134 | } 135 | ], 136 | "elements": [ 137 | { 138 | "presets": [ 139 | { 140 | "presetName": "cutout_bottom_image_element", 141 | "presetAttributes": [ 142 | { 143 | "attributeName": "image", 144 | "attributeValue": "uifeedback_inprogress_tire_size" 145 | } 146 | ] 147 | } 148 | ] 149 | } 150 | ] 151 | } 152 | } 153 | } 154 | ] 155 | } 156 | } 157 | 158 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/tire_size_tin_make_demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Demo config for scanning tire sizes and TINs in parallel.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "pictureResolution": "1080p" 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginCompositeConfig": { 12 | "id": "Workflows|TIN / Tire Size / Tire Make", 13 | "processingMode": "parallel", 14 | "viewPlugins": [ 15 | { 16 | "viewPluginConfig": { 17 | "pluginConfig": { 18 | "id": "Universal TIN", 19 | "tinConfig": { 20 | "scanMode": "DOT", 21 | "upsideDownMode": "AUTO" 22 | }, 23 | "cancelOnResult": true 24 | }, 25 | "cutoutConfig": { 26 | "alignment": "center", 27 | "maxWidthPercent": "60%", 28 | "maxHeightPercent": "60%", 29 | "ratioFromSize": { 30 | "width": 5, 31 | "height": 1 32 | }, 33 | "strokeWidth": 2, 34 | "strokeColor": "FFFFFF", 35 | "cornerRadius": 4, 36 | "outerColor": "000000", 37 | "outerAlpha": 0.5, 38 | "feedbackStrokeColor": "0099FF", 39 | "offset": { 40 | "x": 0, 41 | "y": -15 42 | } 43 | }, 44 | "scanFeedbackConfig": { 45 | "animation": "traverse_multi", 46 | "animationDuration": 250, 47 | "style": "rect", 48 | "strokeWidth": 0, 49 | "strokeColor": "FF2746FF", 50 | "fillColor": "222746FF", 51 | "beepOnResult": false, 52 | "vibrateOnResult": true, 53 | "blinkAnimationOnResult": true 54 | }, 55 | "uiFeedbackConfig": { 56 | "presets": [ 57 | { 58 | "presetName": "simple_instruction_label", 59 | "presetAttributes": [ 60 | { 61 | "attributeName": "instruction_text", 62 | "attributeValue": "Position the data you wish to scan within the central cutout." 63 | } 64 | ] 65 | } 66 | ], 67 | "elements": [ 68 | { 69 | "presets": [ 70 | { 71 | "presetName": "cutout_bottom_image_element", 72 | "presetAttributes": [ 73 | { 74 | "attributeName": "image", 75 | "attributeValue": "uifeedback_inprogress_tire_tin" 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | ] 82 | } 83 | } 84 | }, 85 | { 86 | "viewPluginConfig": { 87 | "pluginConfig": { 88 | "id": "Tire Size", 89 | "tireSizeConfig": { 90 | "upsideDownMode": "AUTO" 91 | }, 92 | "cancelOnResult": true 93 | }, 94 | "cutoutConfig": { 95 | "alignment": "center", 96 | "maxWidthPercent": "60%", 97 | "maxHeightPercent": "60%", 98 | "ratioFromSize": { 99 | "width": 5, 100 | "height": 1 101 | }, 102 | "strokeWidth": 2, 103 | "strokeColor": "FFFFFF", 104 | "cornerRadius": 4, 105 | "outerColor": "000000", 106 | "outerAlpha": 0.5, 107 | "feedbackStrokeColor": "0099FF", 108 | "offset": { 109 | "x": 0, 110 | "y": -15 111 | } 112 | }, 113 | "scanFeedbackConfig": { 114 | "animation": "traverse_multi", 115 | "animationDuration": 250, 116 | "style": "contour_rect", 117 | "strokeWidth": 0, 118 | "strokeColor": "FFC2E6FF", 119 | "fillColor": "22C2E6FF", 120 | "beepOnResult": false, 121 | "vibrateOnResult": true, 122 | "blinkAnimationOnResult": true 123 | }, 124 | "uiFeedbackConfig": { 125 | "presets": [ 126 | { 127 | "presetName": "simple_instruction_label", 128 | "presetAttributes": [ 129 | { 130 | "attributeName": "instruction_text", 131 | "attributeValue": "Position the data you wish to scan within the central cutout." 132 | } 133 | ] 134 | } 135 | ], 136 | "elements": [ 137 | { 138 | "presets": [ 139 | { 140 | "presetName": "cutout_bottom_image_element", 141 | "presetAttributes": [ 142 | { 143 | "attributeName": "image", 144 | "attributeValue": "uifeedback_inprogress_tire_size" 145 | } 146 | ] 147 | } 148 | ] 149 | } 150 | ] 151 | } 152 | } 153 | }, 154 | { 155 | "viewPluginConfig": { 156 | "pluginConfig": { 157 | "id": "Tire Make", 158 | "tireMakeConfig": { 159 | "upsideDownMode": "AUTO" 160 | }, 161 | "cancelOnResult": true 162 | }, 163 | "cutoutConfig": { 164 | "alignment": "center", 165 | "maxWidthPercent": "60%", 166 | "maxHeightPercent": "60%", 167 | "ratioFromSize": { 168 | "width": 5, 169 | "height": 1 170 | }, 171 | "strokeWidth": 2, 172 | "strokeColor": "FFFFFF", 173 | "cornerRadius": 4, 174 | "outerColor": "000000", 175 | "outerAlpha": 0.5, 176 | "feedbackStrokeColor": "0099FF", 177 | "offset": { 178 | "x": 0, 179 | "y": -15 180 | } 181 | }, 182 | "scanFeedbackConfig": { 183 | "animation": "traverse_multi", 184 | "animationDuration": 250, 185 | "style": "contour_rect", 186 | "strokeWidth": 0, 187 | "strokeColor": "FF2746FF", 188 | "fillColor": "222746FF", 189 | "beepOnResult": false, 190 | "vibrateOnResult": true, 191 | "blinkAnimationOnResult": true 192 | }, 193 | "uiFeedbackConfig": { 194 | "presets": [ 195 | { 196 | "presetName": "simple_instruction_label", 197 | "presetAttributes": [ 198 | { 199 | "attributeName": "instruction_text", 200 | "attributeValue": "Position the data you wish to scan within the central cutout." 201 | } 202 | ] 203 | } 204 | ], 205 | "elements": [ 206 | { 207 | "presets": [ 208 | { 209 | "presetName": "cutout_bottom_image_element", 210 | "presetAttributes": [ 211 | { 212 | "attributeName": "image", 213 | "attributeValue": "uifeedback_inprogress_tire_make" 214 | } 215 | ] 216 | } 217 | ] 218 | } 219 | ] 220 | } 221 | } 222 | } 223 | ] 224 | } 225 | } 226 | 227 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/vehicle_config_license_plate.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for EU license plates, with instruction label.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "zoomGesture": true 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginConfig": { 12 | "pluginConfig": { 13 | "id": "Vehicle|License Plates (EU)", 14 | "licensePlateConfig": { 15 | }, 16 | "cancelOnResult": true 17 | }, 18 | "cutoutConfig": { 19 | "maxWidthPercent": "80%", 20 | "maxHeightPercent": "80%", 21 | "alignment": "top_half", 22 | "ratioFromSize": { 23 | "width": 2, 24 | "height": 1 25 | }, 26 | "strokeWidth": 2, 27 | "cornerRadius": 10, 28 | "strokeColor": "FFFFFF", 29 | "outerColor": "000000", 30 | "outerAlpha": 0.3, 31 | "feedbackStrokeColor": "0099FF" 32 | }, 33 | "scanFeedbackConfig": { 34 | "style": "rect", 35 | "strokeWidth": 2, 36 | "strokeColor": "0099FF", 37 | "fillColor": "330099FF", 38 | "cornerRadius": 0, 39 | "beepOnResult": true, 40 | "vibrateOnResult": true, 41 | "blinkAnimationOnResult": true 42 | }, 43 | "uiFeedbackConfig": { 44 | "presets": [ 45 | { 46 | "presetName": "simple_instruction_label", 47 | "presetAttributes": [ 48 | { 49 | "attributeName": "instruction_text", 50 | "attributeValue": "Place the whole plate inside the cutout" 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/vehicle_config_license_plate_eu_vis.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for EU license plates, with optional vehicle inspection sticker (VIS) detection.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "zoomGesture": true 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginConfig": { 12 | "pluginConfig": { 13 | "id": "Vehicle|License Plates (EU + VIS)", 14 | "licensePlateConfig": { 15 | "vehicleInspectionSticker": "OPTIONAL" 16 | }, 17 | "cancelOnResult": true 18 | }, 19 | "cutoutConfig": { 20 | "maxWidthPercent": "80%", 21 | "maxHeightPercent": "80%", 22 | "alignment": "top_half", 23 | "ratioFromSize": { 24 | "width": 2, 25 | "height": 1 26 | }, 27 | "strokeWidth": 2, 28 | "cornerRadius": 10, 29 | "strokeColor": "FFFFFF", 30 | "outerColor": "000000", 31 | "outerAlpha": 0.3, 32 | "feedbackStrokeColor": "0099FF" 33 | }, 34 | "scanFeedbackConfig": { 35 | "style": "rect", 36 | "strokeWidth": 2, 37 | "strokeColor": "0099FF", 38 | "fillColor": "330099FF", 39 | "cornerRadius": 0, 40 | "beepOnResult": true, 41 | "vibrateOnResult": true, 42 | "blinkAnimationOnResult": true 43 | }, 44 | "uiFeedbackConfig": { 45 | "presets": [ 46 | { 47 | "presetName": "simple_instruction_label", 48 | "presetAttributes": [ 49 | { 50 | "attributeName": "instruction_text", 51 | "attributeValue": "Place the whole plate inside the cutout" 52 | } 53 | ] 54 | } 55 | ] 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/vehicle_config_license_plate_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for US license plates, with instruction label.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "zoomGesture": true 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginConfig": { 12 | "pluginConfig": { 13 | "id": "Vehicle|License Plates (US)", 14 | "licensePlateConfig": { 15 | "scanMode": "unitedstates" 16 | }, 17 | "cancelOnResult": true 18 | }, 19 | "cutoutConfig": { 20 | "maxWidthPercent": "80%", 21 | "maxHeightPercent": "80%", 22 | "alignment": "top_half", 23 | "ratioFromSize": { 24 | "width": 2, 25 | "height": 1 26 | }, 27 | "strokeWidth": 2, 28 | "cornerRadius": 10, 29 | "strokeColor": "FFFFFF", 30 | "outerColor": "000000", 31 | "outerAlpha": 0.3, 32 | "feedbackStrokeColor": "0099FF" 33 | }, 34 | "scanFeedbackConfig": { 35 | "style": "rect", 36 | "strokeWidth": 2, 37 | "strokeColor": "0099FF", 38 | "fillColor": "330099FF", 39 | "cornerRadius": 0, 40 | "beepOnResult": true, 41 | "vibrateOnResult": true, 42 | "blinkAnimationOnResult": true 43 | }, 44 | "uiFeedbackConfig": { 45 | "presets": [ 46 | { 47 | "presetName": "simple_instruction_label", 48 | "presetAttributes": [ 49 | { 50 | "attributeName": "instruction_text", 51 | "attributeValue": "Place the whole plate inside the cutout" 52 | } 53 | ] 54 | } 55 | ] 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/vehicle_config_registration_certificate.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Optimized for vehicle registration certificates with fields like license plate, VIN, and owner details, configurable as optional or mandatory based on the use case.", 3 | "cameraConfig" : { 4 | "captureResolution" : "1080p" 5 | }, 6 | "flashConfig" : { 7 | "mode": "manual", 8 | "alignment": "bottom_right" 9 | }, 10 | "viewPluginConfig" : { 11 | "pluginConfig":{ 12 | "id":"VRC", 13 | "vehicleRegistrationCertificateConfig": { 14 | "vehicleRegistrationCertificate": { 15 | "documentNumber": {"scanOption": "optional", "minConfidence": 40}, 16 | "licensePlate": {"scanOption": "mandatory", "minConfidence": 40}, 17 | "lastName": {"scanOption": "mandatory", "minConfidence": 60}, 18 | "firstName": {"scanOption": "optional", "minConfidence": 40}, 19 | "address": {"scanOption": "mandatory", "minConfidence": 50}, 20 | "firstIssued": {"scanOption": "mandatory", "minConfidence": 60}, 21 | "manufacturerCode": {"scanOption": "mandatory", "minConfidence": 50}, 22 | "vehicleTypeCode": {"scanOption": "mandatory", "minConfidence": 50}, 23 | "vehicleIdentificationNumber": {"scanOption": "mandatory", "minConfidence": 60}, 24 | "brand": {"scanOption": "optional", "minConfidence": 40}, 25 | "vehicleType": {"scanOption": "optional", "minConfidence": 40}, 26 | "displacement": {"scanOption": "optional", "minConfidence": 40}, 27 | "tire": {"scanOption": "optional", "minConfidence": 50} 28 | } 29 | }, 30 | "cancelOnResult" : true 31 | }, 32 | "cutoutConfig" : { 33 | "maxWidthPercent": "90%", 34 | "maxHeightPercent": "80%", 35 | "alignment": "center", 36 | "strokeWidth": 3, 37 | "cornerRadius": 8, 38 | "strokeColor": "FFFFFF", 39 | "outerColor": "000000", 40 | "outerAlpha": 0.3, 41 | "ratioFromSize": { 42 | "width": 2, 43 | "height": 1 44 | }, 45 | "cropPadding": { 46 | "x": -50, 47 | "y": -50 48 | }, 49 | "cropOffset": { 50 | "x": 0, 51 | "y": 0 52 | }, 53 | "feedbackStrokeColor": "0099FF" 54 | }, 55 | "scanFeedbackConfig" : { 56 | "style": "contour_rect", 57 | "redrawTimeout": 100, 58 | "strokeColor": "0099FF", 59 | "fillColor" : "220099FF", 60 | "beepOnResult": true, 61 | "vibrateOnResult": true, 62 | "strokeWidth": 2 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/workflows_config_parallel_first_vin_barcode.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Parallel scanning optimized for VIN and barcodes, returning the first successful scan, with instruction label.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "pictureResolution": "1080p" 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginCompositeConfig": { 12 | "id": "parallel-first-vin-barcode", 13 | "processingMode": "parallelFirstScan", 14 | "viewPlugins": [ 15 | { 16 | "viewPluginConfig": { 17 | "pluginConfig": { 18 | "id": "barcode", 19 | "barcodeConfig": { 20 | "barcodeFormats": ["ALL"] 21 | } 22 | }, 23 | "scanFeedbackConfig": { 24 | "style": "rect", 25 | "strokeWidth": 2, 26 | "strokeColor": "0099FF", 27 | "fillColor": "330099FF", 28 | "cornerRadius": 0, 29 | "beepOnResult": false, 30 | "vibrateOnResult": false, 31 | "blinkAnimationOnResult": true 32 | } 33 | } 34 | }, 35 | { 36 | "viewPluginConfig": { 37 | "pluginConfig": { 38 | "id": "vin", 39 | "vinConfig": { 40 | "validateCheckDigit": true 41 | } 42 | }, 43 | "cutoutConfig": { 44 | "maxWidthPercent": "70%", 45 | "alignment": "top_half", 46 | "ratioFromSize": { "width": 689, "height": 100 }, 47 | "offset": { "x": 0, "y": 0 }, 48 | "outerColor": "000000", 49 | "outerAlpha": 0, 50 | "strokeWidth": 2, 51 | "strokeColor": "0099FF", 52 | "cornerRadius": 4, 53 | "feedbackStrokeColor": "0099FF" 54 | }, 55 | "scanFeedbackConfig": { 56 | "style": "contour_rect", 57 | "animation": "traverse_multi", 58 | "animationDuration": 250, 59 | "strokeWidth": 2, 60 | "strokeColor": "0099FF", 61 | "fillColor": "220099FF", 62 | "beepOnResult": false, 63 | "vibrateOnResult": false, 64 | "blinkAnimationOnResult": true 65 | }, 66 | "uiFeedbackConfig": { 67 | "presets": [ 68 | { 69 | "presetName": "vin_with_instruction_image_text_sound_feedback", 70 | "presetAttributes": [ 71 | { 72 | "attributeName": "instruction_text", 73 | "attributeValue": "Position the VIN within the cutout. The barcode can be anywhere inside the camera frame." 74 | }, 75 | { 76 | "attributeName": "lighting_toodark_image", 77 | "attributeValue": "uifeedback_default_toodark" 78 | }, 79 | { 80 | "attributeName": "lighting_toobright_image", 81 | "attributeValue": "uifeedback_default_toobright" 82 | }, 83 | { 84 | "attributeName": "distance_moveback_image", 85 | "attributeValue": "uifeedback_default_moveback" 86 | }, 87 | { 88 | "attributeName": "distance_movecloser_image", 89 | "attributeValue": "uifeedback_default_movecloser" 90 | }, 91 | { 92 | "attributeName": "format_invalid_image", 93 | "attributeValue": "uifeedback_vin_invalid" 94 | }, 95 | { 96 | "attributeName": "lighting_toodark_text", 97 | "attributeValue": "" 98 | }, 99 | { 100 | "attributeName": "lighting_toobright_text", 101 | "attributeValue": "" 102 | }, 103 | { 104 | "attributeName": "distance_moveback_text", 105 | "attributeValue": "" 106 | }, 107 | { 108 | "attributeName": "distance_movecloser_text", 109 | "attributeValue": "" 110 | }, 111 | { 112 | "attributeName": "format_invalid_text", 113 | "attributeValue": "" 114 | }, 115 | { 116 | "attributeName": "lighting_toodark_sound", 117 | "attributeValue": "info_sound_default.wav" 118 | }, 119 | { 120 | "attributeName": "lighting_toobright_sound", 121 | "attributeValue": "info_sound_default.wav" 122 | }, 123 | { 124 | "attributeName": "distance_moveback_sound", 125 | "attributeValue": "info_sound_default.wav" 126 | }, 127 | { 128 | "attributeName": "distance_movecloser_sound", 129 | "attributeValue": "info_sound_default.wav" 130 | }, 131 | { 132 | "attributeName": "format_invalid_sound", 133 | "attributeValue": "info_sound_default.wav" 134 | } 135 | ] 136 | } 137 | ] 138 | } 139 | } 140 | } 141 | ] 142 | } 143 | } 144 | 145 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/workflows_config_parallel_meter_barcode.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Parallel workflow optimized for scanning meters and barcodes at the same time with instruction label.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "pictureResolution": "1080p", 6 | "zoomGesture": true 7 | }, 8 | "flashConfig": { 9 | "mode": "manual_off", 10 | "alignment": "bottom_right" 11 | }, 12 | "viewPluginCompositeConfig": { 13 | "id": "parallel-meter-barcode", 14 | "processingMode": "parallel", 15 | "viewPlugins": [ 16 | { 17 | "viewPluginConfig": { 18 | "pluginConfig": { 19 | "id": "meter-auto", 20 | "meterConfig": { 21 | "scanMode": "auto_analog_digital_meter" 22 | }, 23 | "cancelOnResult": true, 24 | "startScanDelay": 0 25 | }, 26 | "cutoutConfig": { 27 | "maxWidthPercent": "85%", 28 | "alignment": "top", 29 | "ratioFromSize": { "width": 2, "height": 1 }, 30 | "cropOffset": { "x": 0, "y": 120 }, 31 | "strokeWidth": 2, 32 | "cornerRadius": 6, 33 | "strokeColor": "FFFFFF", 34 | "outerColor": "000000", 35 | "outerAlpha": 0, 36 | "offset": { "x": 0, "y": 260 } 37 | }, 38 | "scanFeedbackConfig": { 39 | "style": "rect", 40 | "strokeWidth": 2, 41 | "strokeColor": "0099FF", 42 | "fillColor": "220099FF", 43 | "cornerRadius": 2, 44 | "beepOnResult": true, 45 | "vibrateOnResult": true, 46 | "blinkAnimationOnResult": true, 47 | "redrawTimeout": 200, 48 | "animationDuration": 75 49 | }, 50 | "uiFeedbackConfig": { 51 | "presets": [ 52 | { 53 | "presetName": "simple_instruction_label", 54 | "presetAttributes": [ 55 | { 56 | "attributeName": "instruction_text", 57 | "attributeValue": "Place the meter in the cutout, barcode anywhere in frame" 58 | } 59 | ] 60 | } 61 | ] 62 | } 63 | } 64 | }, 65 | { 66 | "viewPluginConfig": { 67 | "pluginConfig": { 68 | "id": "barcode", 69 | "barcodeConfig": { 70 | "barcodeFormats": ["ALL"] 71 | }, 72 | "cancelOnResult": true, 73 | "startScanDelay": 100 74 | }, 75 | "scanFeedbackConfig": { 76 | "style": "rect", 77 | "strokeWidth": 2, 78 | "strokeColor": "0099FF", 79 | "fillColor": "220099FF", 80 | "beepOnResult": false, 81 | "vibrateOnResult": false, 82 | "blinkAnimationOnResult": false 83 | } 84 | } 85 | } 86 | ] 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/assets/viewConfigs/workflows_config_sequential.json: -------------------------------------------------------------------------------- 1 | { 2 | "scanViewConfigDescription": "Sequential workflow optimized for scanning license plates, driving licenses, and VINs with instruction label.", 3 | "cameraConfig": { 4 | "captureResolution": "1080p", 5 | "pictureResolution": "1080p" 6 | }, 7 | "flashConfig": { 8 | "mode": "manual", 9 | "alignment": "bottom_right" 10 | }, 11 | "viewPluginCompositeConfig": { 12 | "id": "Workflows|License Plate / DrivingLicense / VIN (sequential)", 13 | "processingMode": "sequential", 14 | "viewPlugins": [ 15 | { 16 | "viewPluginConfig": { 17 | "pluginConfig": { 18 | "id": "LICENSE_PLATE", 19 | "licensePlateConfig": { 20 | "scanMode": "auto" 21 | } 22 | }, 23 | "cutoutConfig": { 24 | "maxWidthPercent": "80%", 25 | "maxHeightPercent": "80%", 26 | "alignment": "top_half", 27 | "ratioFromSize": { 28 | "width": 2, 29 | "height": 1 30 | }, 31 | "strokeWidth": 2, 32 | "cornerRadius": 10, 33 | "strokeColor": "FFFFFF", 34 | "outerColor": "000000", 35 | "outerAlpha": 0.3, 36 | "feedbackStrokeColor": "0099FF" 37 | }, 38 | "scanFeedbackConfig": { 39 | "style": "rect", 40 | "strokeWidth": 2, 41 | "strokeColor": "0099FF", 42 | "fillColor": "330099FF", 43 | "cornerRadius": 0, 44 | "beepOnResult": true, 45 | "vibrateOnResult": true, 46 | "blinkAnimationOnResult": true 47 | }, 48 | "uiFeedbackConfig": { 49 | "presets": [ 50 | { 51 | "presetName": "simple_instruction_label", 52 | "presetAttributes": [ 53 | { 54 | "attributeName": "instruction_text", 55 | "attributeValue": "Position the entire License Plate within the cutout" 56 | } 57 | ] 58 | } 59 | ] 60 | } 61 | } 62 | }, 63 | { 64 | "viewPluginConfig": { 65 | "pluginConfig": { 66 | "id": "DRIVING_LICENSE", 67 | "universalIdConfig": { 68 | "allowedLayouts": { 69 | "drivingLicense": [] 70 | } 71 | } 72 | }, 73 | "cutoutConfig": { 74 | "maxWidthPercent": "90%", 75 | "maxHeightPercent": "90%", 76 | "alignment": "center", 77 | "ratioFromSize": { 78 | "width": 161, 79 | "height": 100 80 | }, 81 | "strokeWidth": 2, 82 | "cornerRadius": 4, 83 | "strokeColor": "FFFFFF", 84 | "outerColor": "000000", 85 | "outerAlpha": 0.3, 86 | "feedbackStrokeColor": "0099FF" 87 | }, 88 | "scanFeedbackConfig": { 89 | "fillColor": "220099FF", 90 | "style": "contour_point", 91 | "strokeColor": "0099FF", 92 | "strokeWidth": 2, 93 | "blinkAnimationOnResult": true, 94 | "beepOnResult": true, 95 | "vibrateOnResult": true 96 | }, 97 | "uiFeedbackConfig": { 98 | "presets": [ 99 | { 100 | "presetName": "simple_instruction_label", 101 | "presetAttributes": [ 102 | { 103 | "attributeName": "instruction_text", 104 | "attributeValue": "Position the entire Driving License within the cutout" 105 | } 106 | ] 107 | } 108 | ] 109 | } 110 | } 111 | }, 112 | { 113 | "viewPluginConfig": { 114 | "pluginConfig": { 115 | "id": "VIN", 116 | "vinConfig": { 117 | "validateCheckDigit": true 118 | } 119 | }, 120 | "cutoutConfig": { 121 | "maxWidthPercent": "70%", 122 | "alignment": "top_half", 123 | "ratioFromSize": { 124 | "width": 689, 125 | "height": 100 126 | }, 127 | "outerColor": "000000", 128 | "outerAlpha": 0.3, 129 | "strokeWidth": 2, 130 | "strokeColor": "FFFFFF", 131 | "cornerRadius": 4, 132 | "feedbackStrokeColor": "0099FF" 133 | }, 134 | "scanFeedbackConfig": { 135 | "animation": "traverse_multi", 136 | "animationDuration": 250, 137 | "style": "contour_rect", 138 | "strokeWidth": 2, 139 | "strokeColor": "0099FF", 140 | "fillColor": "220099FF", 141 | "beepOnResult": true, 142 | "vibrateOnResult": true, 143 | "blinkAnimationOnResult": true 144 | }, 145 | "uiFeedbackConfig": { 146 | "presets": [ 147 | { 148 | "presetName": "vin_with_instruction_image_text_sound_feedback", 149 | "presetAttributes": [ 150 | { 151 | "attributeName": "instruction_text", 152 | "attributeValue": "Please make sure the entire VIN number is inside the cutout." 153 | }, 154 | { 155 | "attributeName": "lighting_toodark_image", 156 | "attributeValue": "uifeedback_default_toodark" 157 | }, 158 | { 159 | "attributeName": "lighting_toobright_image", 160 | "attributeValue": "uifeedback_default_toobright" 161 | }, 162 | { 163 | "attributeName": "distance_moveback_image", 164 | "attributeValue": "uifeedback_default_moveback" 165 | }, 166 | { 167 | "attributeName": "distance_movecloser_image", 168 | "attributeValue": "uifeedback_default_movecloser" 169 | }, 170 | { 171 | "attributeName": "format_invalid_image", 172 | "attributeValue": "uifeedback_vin_invalid" 173 | }, 174 | { 175 | "attributeName": "lighting_toodark_text", 176 | "attributeValue": "" 177 | }, 178 | { 179 | "attributeName": "lighting_toobright_text", 180 | "attributeValue": "" 181 | }, 182 | { 183 | "attributeName": "distance_moveback_text", 184 | "attributeValue": "" 185 | }, 186 | { 187 | "attributeName": "distance_movecloser_text", 188 | "attributeValue": "" 189 | }, 190 | { 191 | "attributeName": "format_invalid_text", 192 | "attributeValue": "" 193 | }, 194 | { 195 | "attributeName": "lighting_toodark_sound", 196 | "attributeValue": "info_sound_default.wav" 197 | }, 198 | { 199 | "attributeName": "lighting_toobright_sound", 200 | "attributeValue": "info_sound_default.wav" 201 | }, 202 | { 203 | "attributeName": "distance_moveback_sound", 204 | "attributeValue": "info_sound_default.wav" 205 | }, 206 | { 207 | "attributeName": "distance_movecloser_sound", 208 | "attributeValue": "info_sound_default.wav" 209 | }, 210 | { 211 | "attributeName": "format_invalid_sound", 212 | "attributeValue": "info_sound_default.wav" 213 | } 214 | ] 215 | } 216 | ] 217 | } 218 | } 219 | } 220 | ] 221 | } 222 | } 223 | 224 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/CameraStateObserver.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples 2 | 3 | import android.util.Size 4 | import android.widget.Toast 5 | import androidx.lifecycle.LifecycleOwner 6 | import androidx.lifecycle.Observer 7 | import io.anyline2.view.CameraPermissionState 8 | import io.anyline2.view.CameraState 9 | import io.anyline2.view.ScanView 10 | import kotlin.math.max 11 | import kotlin.math.min 12 | 13 | /** 14 | * A helper class for observing the CameraState and notify the user when the expected is not available 15 | */ 16 | class CameraStateObserver( 17 | lifecycleOwner: LifecycleOwner, 18 | private val scanView: ScanView): Observer { 19 | 20 | var expectedViewConfigCameraSize: Size? = null 21 | set(value) { 22 | field = value 23 | value?.let { 24 | compareSizesAndNotify() 25 | } 26 | } 27 | 28 | private var actualCameraSize: Size? = null 29 | set(value) { 30 | field = value 31 | value?.let { 32 | compareSizesAndNotify() 33 | } 34 | } 35 | 36 | init { 37 | scanView.cameraState.observe(lifecycleOwner, this) 38 | } 39 | 40 | override fun onChanged(value: CameraState) { 41 | when (value) { 42 | is CameraState.NotReady -> { 43 | //waiting for camera 44 | } 45 | is CameraState.Ready -> { 46 | actualCameraSize = value.getFrameSize() 47 | } 48 | is CameraState.Error -> { 49 | if (value.cameraPermissionState is CameraPermissionState.Denied) { 50 | notifyWithToast("Camera permission was denied.") 51 | } else { 52 | notifyWithToast("Error opening camera: ${value.exception?.message}") 53 | } 54 | } 55 | } 56 | } 57 | 58 | private fun compareSizesAndNotify() { 59 | actualCameraSize?.let { actualSize -> 60 | expectedViewConfigCameraSize?.let { expectedSize -> 61 | if (max(actualSize.width, actualSize.height) != max(expectedSize.width, expectedSize.height) 62 | || min(actualSize.width, actualSize.height) != min(expectedSize.width, expectedSize.height)) { 63 | scanView.post { 64 | notifyWithToast("Expected camera resolution not available. " + 65 | "Using ${actualSize.width}x${actualSize.height} instead.") 66 | } 67 | } 68 | } 69 | } 70 | } 71 | 72 | private fun notifyWithToast(message: String, duration: Int = Toast.LENGTH_LONG) { 73 | Toast 74 | .makeText(scanView.context, message, duration) 75 | .show() 76 | } 77 | 78 | fun reset() { 79 | expectedViewConfigCameraSize = null 80 | actualCameraSize = null 81 | } 82 | } -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples 2 | 3 | import android.content.Intent 4 | import android.net.Uri 5 | import android.os.Bundle 6 | import android.text.format.DateFormat 7 | import android.view.View 8 | import androidx.appcompat.app.AppCompatActivity 9 | import at.nineyards.anyline.BuildConfig.VERSION_CODE_ANYLINE_SDK 10 | import at.nineyards.anyline.BuildConfig.VERSION_NAME_ANYLINE_SDK 11 | import com.anyline.examples.databinding.ActivityMainBinding 12 | import com.google.android.material.dialog.MaterialAlertDialogBuilder 13 | import io.anyline2.AnylineSdk 14 | import io.anyline2.init.SdkInitializationState 15 | 16 | class MainActivity : AppCompatActivity() { 17 | 18 | private lateinit var binding: ActivityMainBinding 19 | 20 | override fun onCreate(savedInstanceState: Bundle?) { 21 | super.onCreate(savedInstanceState) 22 | binding = ActivityMainBinding.inflate(layoutInflater) 23 | val view = binding.root 24 | setContentView(view) 25 | 26 | AnylineSdk.initializationState.observe(this) { sdkInitializationState -> 27 | updateUi(sdkInitializationState) 28 | } 29 | 30 | binding.startScanningButton.setOnClickListener { 31 | when (val initializationState = AnylineSdk.initializationState.value) { 32 | is SdkInitializationState.NotInitialized -> { 33 | showLicenseKeyAlertDialog(initializationState) 34 | return@setOnClickListener 35 | } 36 | else -> { 37 | startSelectConfigActivity() 38 | } 39 | } 40 | } 41 | } 42 | 43 | private fun startSelectConfigActivity() { 44 | startActivity(SelectConfigActivity.buildIntent(this)) 45 | finish() 46 | } 47 | 48 | private fun showLicenseKeyAlertDialog(sdkNotInitializedState: SdkInitializationState.NotInitialized) { 49 | val alertDialogBuilder = MaterialAlertDialogBuilder(this) 50 | .setTitle(resources.getString(R.string.license_key_not_initialized_title)) 51 | .setMessage(resources.getString(R.string.license_key_not_initialized_message)) 52 | .setNegativeButton(resources.getString(R.string.button_cancel)) { _, _ -> 53 | 54 | } 55 | .setNeutralButton(resources.getString(R.string.license_key_not_initialized_documentation_button)) { _, _ -> 56 | val intent = Intent() 57 | intent.setAction(Intent.ACTION_VIEW) 58 | intent.setData(Uri.parse(resources.getString(R.string.license_key_not_initialized_documentation_url))) 59 | startActivity(Intent.createChooser(intent, null)) 60 | } 61 | sdkNotInitializedState.lastError?.let { lastError -> 62 | if (lastError.isNetworkRelated()) { 63 | alertDialogBuilder.setPositiveButton(resources.getString(R.string.button_ignore)) { _, _ -> 64 | startSelectConfigActivity() 65 | } 66 | } 67 | } 68 | alertDialogBuilder.show() 69 | } 70 | 71 | private fun updateUi(sdkInitializationState: SdkInitializationState) { 72 | val sdkInitializationStatusText = when (sdkInitializationState) { 73 | is SdkInitializationState.NotInitialized -> { 74 | binding.sdkInitProgressBar.visibility = View.GONE 75 | 76 | sdkInitializationState.lastError?.let { 77 | "Error initializing SDK: " + (it.exception.message ?: "") 78 | } ?: "SDK not yet initialized" 79 | } 80 | is SdkInitializationState.InProgress -> { 81 | binding.sdkInitProgressBar.visibility = View.VISIBLE 82 | 83 | "SDK initialization in progress..." 84 | } 85 | is SdkInitializationState.Initialized -> { 86 | binding.sdkInitProgressBar.visibility = View.GONE 87 | 88 | val dateFormat = DateFormat.getDateFormat(this) 89 | "SDK initialization succeeded. License expires on: " + 90 | dateFormat.format(sdkInitializationState.getExpiryDate()) 91 | } 92 | } 93 | 94 | binding.versionTextview.text = 95 | "Anyline SDK Version: ${VERSION_NAME_ANYLINE_SDK} (${VERSION_CODE_ANYLINE_SDK})\n" + 96 | "New SDK App Version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\n" + 97 | "$sdkInitializationStatusText\n" 98 | } 99 | } -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples 2 | 3 | import android.app.Application 4 | import io.anyline2.AnylineSdk 5 | import io.anyline2.init.SdkInitializationConfig 6 | import io.anyline2.init.SdkInitializationListener 7 | import io.anyline2.init.SdkInitializationParameters 8 | import io.anyline2.init.SdkInitializationState 9 | import io.anyline2.init.SdkInitializationStrategy 10 | 11 | import timber.log.Timber 12 | 13 | class MainApplication: Application() { 14 | 15 | override fun onCreate() { 16 | super.onCreate() 17 | if (BuildConfig.DEBUG) { 18 | Timber.plant(Timber.DebugTree()) 19 | } 20 | 21 | AnylineSdk.init(this, SdkInitializationConfig( 22 | sdkInitializationParameters = SdkInitializationParameters( 23 | licenseKey = getString(R.string.anyline_license_key)), 24 | sdkInitializationStrategy = SdkInitializationStrategy.AsyncAuto(object: SdkInitializationListener { 25 | override fun onInitializationStarted() { 26 | Timber 27 | .tag("AnylineSdkInit") 28 | .d("Anyline SDK initialization in progress...") 29 | } 30 | 31 | override fun onInitializationFailed(state: SdkInitializationState.NotInitialized) { 32 | Timber 33 | .tag("AnylineSdkInit") 34 | .e("Anyline SDK not initialized: ${state.lastError?.exception?.message}") 35 | } 36 | 37 | override fun onInitializationSucceeded(state: SdkInitializationState.Initialized) { 38 | Timber 39 | .tag("AnylineSdkInit") 40 | .d("Anyline SDK initialized!") 41 | } 42 | })) 43 | ) 44 | } 45 | } -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/barcodeOverlay/BarcodeOverlayScanActivity.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples.barcodeOverlay 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.util.Size 7 | import android.view.MenuItem 8 | import android.view.View 9 | import androidx.appcompat.app.AlertDialog 10 | import androidx.appcompat.app.AppCompatActivity 11 | import com.anyline.examples.CameraStateObserver 12 | import com.anyline.examples.R 13 | import com.anyline.examples.databinding.ActivityScanBinding 14 | import io.anyline2.Event 15 | import io.anyline2.ScanResult 16 | import io.anyline2.sdk.extension.preferredPreviewHeight 17 | import io.anyline2.sdk.extension.preferredPreviewWidth 18 | import io.anyline2.view.ScanView 19 | import io.anyline2.viewplugin.ar.BarcodeOverlayListener 20 | import io.anyline2.viewplugin.ar.BarcodeOverlayView 21 | import io.anyline2.viewplugin.ar.OverlayViewHolder 22 | import io.anyline2.view.ScanViewLoadResult 23 | import io.anyline2.viewplugin.ScanViewPlugin 24 | 25 | class BarcodeOverlayScanActivity: AppCompatActivity(), BarcodeOverlayListener { 26 | private lateinit var binding: ActivityScanBinding 27 | private lateinit var scanView: ScanView 28 | private lateinit var cameraStateObserver: CameraStateObserver 29 | 30 | private var scanCount: Long = 0 31 | private var lastScanResult: ScanResult? = null 32 | 33 | override fun onCreate(savedInstanceState: Bundle?) { 34 | super.onCreate(savedInstanceState) 35 | 36 | binding = ActivityScanBinding.inflate(layoutInflater) 37 | 38 | setContentView(binding.root) 39 | scanView = binding.scanView 40 | scanView.setOnScanViewLoaded { result -> onScanViewLoaded(result) } 41 | 42 | cameraStateObserver = CameraStateObserver(this, scanView) 43 | 44 | supportActionBar?.setDisplayHomeAsUpEnabled(true) 45 | 46 | binding.scanAgainButton.setOnClickListener { 47 | scanView.start() 48 | lastScanResult = null 49 | 50 | binding.scanAgainButton.visibility = View.GONE 51 | binding.bottomScrollView.visibility = View.GONE 52 | binding.lastresultImageview.setImageBitmap(null) 53 | binding.lastresultImageview.visibility = View.GONE 54 | binding.textLastscannedResultValue.text = "" 55 | } 56 | } 57 | 58 | private fun onScanViewLoaded(result: ScanViewLoadResult) { 59 | when (result) { 60 | is ScanViewLoadResult.Succeeded -> { 61 | scanView.init(intent.getStringExtra(INTENT_EXTRA_VIEW_CONFIG_FILE)!!) 62 | scanView.start() 63 | title = scanView.scanViewPlugin.id() 64 | setupScanViewListeners() 65 | 66 | cameraStateObserver.apply { 67 | /* Reset CameraStateObserver and set a new expected value for the resolution 68 | * as defined in the ScanViewConfig. Use this to e.g. notify the end user 69 | * if the device doesn't support a requested 4K resolution and needs to switch 70 | * to using 1080p. 71 | */ 72 | reset() 73 | expectedViewConfigCameraSize = 74 | scanView.scanViewConfigHolder.getCameraConfig()?.let { scanViewCameraConfig -> 75 | Size( 76 | scanViewCameraConfig.preferredPreviewWidth(), 77 | scanViewCameraConfig.preferredPreviewHeight()) 78 | } ?: run { null } 79 | } 80 | } 81 | is ScanViewLoadResult.Failed -> { 82 | result.getErrorMessage()?.let { errorString -> 83 | showAlertDialog( 84 | "Error", 85 | resources.getString(R.string.scanview_load_error) + ": " + errorString 86 | ) { finish() } 87 | } 88 | } 89 | } 90 | } 91 | 92 | private fun setupScanViewListeners() { 93 | scanView.scanViewPlugin.apply { 94 | //overwrites resultReceived method 95 | resultReceived = Event { data -> 96 | scanCount += data.pluginResult.barcodeResult.barcodes.size 97 | binding.textTotalscannedCountValue.text = scanCount.toString() 98 | } 99 | 100 | enableBarcodeOverlays(activeScanViewPlugin.first()) 101 | } 102 | 103 | scanView.start() 104 | } 105 | 106 | private fun enableBarcodeOverlays(scanViewPlugin: ScanViewPlugin) { 107 | //create an instance of BarcodeOverlays which calls evalResults method 108 | //when user clicks on an overlay view 109 | scanViewPlugin.enableBarcodeOverlays(this@BarcodeOverlayScanActivity) 110 | } 111 | 112 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 113 | when (item.itemId) { 114 | android.R.id.home -> { 115 | onBackPressedDispatcher.onBackPressed() 116 | } 117 | } 118 | return super.onOptionsItemSelected(item) 119 | } 120 | 121 | private fun showAlertDialog(title: String, message: String, onDismiss: (() -> Unit)? = null) { 122 | val alertDialogBuilder = AlertDialog.Builder(this) 123 | alertDialogBuilder.setTitle(title) 124 | .setMessage(message) 125 | .setOnDismissListener { onDismiss?.invoke() } 126 | val alertDialog = alertDialogBuilder.create() 127 | alertDialog.show() 128 | } 129 | 130 | override fun onResume() { 131 | super.onResume() 132 | if (scanView.isInitialized) { 133 | //Starts scanning on Activity resume 134 | scanView.start() 135 | enableBarcodeOverlays(scanView.scanViewPlugin.activeScanViewPlugin.first()) 136 | } 137 | } 138 | 139 | override fun onPause() { 140 | if (scanView.isInitialized) { 141 | scanView.scanViewPlugin.activeScanViewPlugin.first().disableBarcodeOverlays() 142 | //Stop scanning on Activity pause 143 | scanView.stop() 144 | } 145 | super.onPause() 146 | } 147 | 148 | override fun onCreate(barcodeOverlayView: BarcodeOverlayView): List { 149 | /* 150 | * onCreate() is called every time a barcode that is not contained 151 | * on current overlays is discovered. Must return a list of Views 152 | * that will be placed near the barcode. 153 | */ 154 | val overlayViewHolderList = BarcodeOverlayViewHolderList(this@BarcodeOverlayScanActivity, barcodeOverlayView) 155 | overlayViewHolderList.forEach { overlayViewHolder -> 156 | overlayViewHolder.view?.setOnLongClickListener { 157 | binding.scanAgainButton.visibility = View.VISIBLE 158 | binding.bottomScrollView.visibility = View.VISIBLE 159 | barcodeOverlayView.visibleBarcode.getBarcodeImage()?.let { bmp -> 160 | binding.lastresultImageview.setImageBitmap(bmp) 161 | binding.lastresultImageview.visibility = View.VISIBLE 162 | } 163 | binding.textLastscannedResultValue.text = barcodeOverlayView.visibleBarcode.barcode.value 164 | scanView.stop() 165 | true 166 | } 167 | } 168 | return overlayViewHolderList 169 | } 170 | 171 | override fun onUpdate(viewHolders: List, barcodeOverlayView: BarcodeOverlayView) { 172 | /* 173 | * onUpdate() is called every time a previously detected barcode needs to be repositioned. 174 | */ 175 | val oldInfo: BarcodeOverlayViewHolderList = (viewHolders as BarcodeOverlayViewHolderList) 176 | if (oldInfo.overlayType != BarcodeOverlayViewHolderList.getOverlayTypeFromBarcodeOverlayView(barcodeOverlayView)) { 177 | // calling invalidate() makes the overlay to be disposed 178 | // and a new onCreate() will be called for a new view instance 179 | barcodeOverlayView.invalidate() 180 | } 181 | } 182 | 183 | override fun onDestroy() { 184 | BarcodeOverlayViewHolderList.resetSelectedBarcodes() 185 | super.onDestroy() 186 | } 187 | 188 | companion object { 189 | private const val INTENT_EXTRA_VIEW_CONFIG_FILE = "INTENT_EXTRA_VIEW_CONFIG_FILE" 190 | 191 | fun buildIntent(context: Context, viewConfigFile: String): Intent { 192 | val intent = Intent(context, BarcodeOverlayScanActivity::class.java) 193 | intent.putExtra(INTENT_EXTRA_VIEW_CONFIG_FILE, viewConfigFile) 194 | return intent 195 | } 196 | } 197 | 198 | } -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/barcodeOverlay/BarcodeOverlayViewHolderList.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples.barcodeOverlay 2 | 3 | 4 | import android.content.Context 5 | import android.view.Gravity 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.ImageView 9 | import android.widget.TextView 10 | import androidx.core.content.ContextCompat 11 | import com.anyline.examples.R 12 | import io.anyline.plugin.config.OverlayConfig 13 | import io.anyline.plugin.config.OverlayConfig.OverlayAnchorConfig 14 | import io.anyline.plugin.config.OverlayDimensionConfig 15 | import io.anyline.plugin.config.OverlayScaleConfig 16 | import io.anyline2.viewplugin.ar.BarcodeOverlayView 17 | import io.anyline2.viewplugin.ar.OverlayViewHolder 18 | import io.anyline2.viewplugin.ar.VisibleBarcode 19 | import java.util.ArrayList 20 | 21 | sealed class OverlayType { 22 | abstract val small: Boolean 23 | 24 | data class Selected(override val small: Boolean): OverlayType() 25 | data class NotSelected(override val small: Boolean): OverlayType() 26 | } 27 | 28 | class BarcodeOverlayViewHolderList( 29 | context: Context, 30 | barcodeOverlayView: BarcodeOverlayView): ArrayList() { 31 | 32 | val overlayType: OverlayType = getOverlayTypeFromBarcodeOverlayView(barcodeOverlayView) 33 | init { 34 | setOverlayViewHolders(context, barcodeOverlayView) 35 | } 36 | 37 | private fun setOverlayViewHolders(context: Context, barcodeOverlayView: BarcodeOverlayView) { 38 | clear() 39 | add( 40 | OverlayViewHolder( 41 | overlayView = ImageView(context).apply { 42 | scaleType = ImageView.ScaleType.CENTER_INSIDE 43 | layoutParams = ViewGroup.LayoutParams(150, 150) 44 | setImageResource(getImageResourceFromOverlayType(overlayType)) 45 | setOnClickListener { 46 | val barcodeValue = barcodeOverlayView.visibleBarcode.value 47 | Companion.setSelected(!isSelected(barcodeValue), barcodeValue, barcodeOverlayView.visibleBarcode) 48 | /* 49 | * by calling BarcodeOverlayView.invalidate() we request the BarcodeOverlayListener 50 | * to re-create the OverlayViewHolder list on the next BarcodeOverlayView update 51 | */ 52 | barcodeOverlayView.invalidate() 53 | } 54 | }, 55 | overlayConfig = OverlayConfig().apply { 56 | anchor = OverlayAnchorConfig.CENTER 57 | sizeDimension = OverlayDimensionConfig().apply { 58 | scaleX = OverlayScaleConfig().apply { 59 | scaleValue = 0.7 60 | scaleType = OverlayScaleConfig.OverlayScaleTypeConfig.OVERLAY 61 | } 62 | scaleY = OverlayScaleConfig().apply { 63 | scaleValue = 0.7 64 | scaleType = OverlayScaleConfig.OverlayScaleTypeConfig.OVERLAY 65 | } 66 | } 67 | } 68 | ) 69 | ) 70 | if (overlayType is OverlayType.Selected) { 71 | add( 72 | OverlayViewHolder( 73 | overlayView = TextView(context).apply { 74 | text = barcodeOverlayView.visibleBarcode.value 75 | textAlignment = View.TEXT_ALIGNMENT_CENTER 76 | gravity = Gravity.CENTER_HORIZONTAL + Gravity.CENTER 77 | setTextColor(ContextCompat.getColor(context, R.color.white)) 78 | setBackgroundResource(R.drawable.selected_barcode_overlay_rounded_corner) 79 | }, 80 | overlayConfig = OverlayConfig().apply { 81 | anchor = OverlayAnchorConfig.BOTTOM_CENTER 82 | 83 | sizeDimension = OverlayDimensionConfig().apply { 84 | scaleX = OverlayScaleConfig().apply { 85 | scaleValue = 1.0 86 | scaleType = OverlayScaleConfig.OverlayScaleTypeConfig.OVERLAY 87 | } 88 | scaleY = OverlayScaleConfig().apply { 89 | scaleValue = 0.3 90 | scaleType = OverlayScaleConfig.OverlayScaleTypeConfig.OVERLAY 91 | } 92 | } 93 | offsetDimension = OverlayDimensionConfig().apply { 94 | scaleY = OverlayScaleConfig().apply { 95 | scaleValue = -0.1 96 | scaleType = OverlayScaleConfig.OverlayScaleTypeConfig.OVERLAY 97 | } 98 | } 99 | } 100 | ) 101 | ) 102 | } 103 | } 104 | 105 | companion object { 106 | private val selectedBarcodeMap = mutableMapOf() 107 | 108 | private fun isSelected(barcodeValue: String): Boolean { 109 | return selectedBarcodeMap.containsKey(barcodeValue) 110 | } 111 | 112 | private fun setSelected(selected: Boolean, barcodeValue: String, visibleBarcode: VisibleBarcode) { 113 | if (selected) { 114 | selectedBarcodeMap[barcodeValue] = visibleBarcode 115 | } else { 116 | selectedBarcodeMap.remove(barcodeValue) 117 | } 118 | } 119 | 120 | fun resetSelectedBarcodes() { 121 | selectedBarcodeMap.clear() 122 | } 123 | 124 | private const val MAX_SMALL_SIZE: Int = 200 125 | 126 | fun getOverlayTypeFromBarcodeOverlayView(barcodeOverlayView: BarcodeOverlayView): OverlayType { 127 | val rect = barcodeOverlayView.visibleBarcode.imageRect 128 | val isSmall = (rect.width < MAX_SMALL_SIZE && rect.height < MAX_SMALL_SIZE) 129 | return when (isSelected(barcodeOverlayView.visibleBarcode.value)) { 130 | true -> OverlayType.Selected(isSmall) 131 | false -> OverlayType.NotSelected(isSmall) 132 | } 133 | } 134 | 135 | private fun getImageResourceFromOverlayType(overlayType: OverlayType) = when (overlayType) { 136 | is OverlayType.Selected -> { 137 | when (overlayType.small) { 138 | true -> R.drawable.ic_barcode_overlay_far_green 139 | false -> R.drawable.ic_barcode_overlay_checkmark_green 140 | } 141 | } 142 | is OverlayType.NotSelected -> { 143 | when (overlayType.small) { 144 | true -> R.drawable.ic_barcode_overlay_far_blue 145 | false -> R.drawable.ic_barcode_overlay_plus_blue 146 | } 147 | } 148 | } 149 | } 150 | } 151 | 152 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/scanViewConfig/ScanViewConfigFile.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples.scanViewConfig 2 | 3 | import android.content.Context 4 | import io.anyline.plugin.config.ScanViewConfiguration 5 | import io.anyline.plugin.config.ViewPluginCompositeConfig 6 | import io.anyline2.sdk.ScanViewConfigHolder 7 | import io.anyline2.sdk.ScanViewConfigHolder.ScanViewJsonValidationResult 8 | import org.json.JSONObject 9 | import java.io.File 10 | import java.util.regex.Pattern 11 | 12 | data class ScanViewConfigFile( 13 | val assetFolderName: String, 14 | val fileName: String, 15 | val fileContent: String, 16 | private val scanViewConfig: ScanViewConfiguration?, 17 | val errorMessage: String? = null) { 18 | 19 | enum class ScanPluginWorkflow(val description: String) { 20 | Simple("Simple"), 21 | CompositeParallel("Composite (Parallel / ParallelFirst)"), 22 | CompositeSequential("Composite (Sequential)") 23 | } 24 | 25 | enum class ScanPluginCategory(val description: String) { 26 | Vehicle("Vehicle"), 27 | MeterReading("Meter Reading"), 28 | IdentityDocuments("Identity Documents"), 29 | Barcode("Barcode"), 30 | Others("Others") 31 | } 32 | 33 | enum class ScanPluginType(val description: String, val categories: List) { 34 | Barcode("Barcode", listOf( 35 | ScanPluginCategory.Barcode 36 | )), 37 | Meter("Meter", listOf( 38 | ScanPluginCategory.MeterReading 39 | )), 40 | DigitalOdometer("Digital Odometer", listOf( 41 | ScanPluginCategory.Vehicle 42 | )), 43 | ID("ID", listOf( 44 | ScanPluginCategory.IdentityDocuments 45 | )), 46 | JapaneseLandingPermission("Japanese Landing Permission", listOf()), 47 | MRZ("MRZ", listOf( 48 | ScanPluginCategory.IdentityDocuments 49 | )), 50 | VehicleRegistrationCertificate("Vehicle Registration Certificate", listOf( 51 | ScanPluginCategory.Vehicle 52 | )), 53 | LicensePlate("License Plate", listOf( 54 | ScanPluginCategory.Vehicle 55 | )), 56 | TINDOT("TIN DOT", listOf( 57 | ScanPluginCategory.Vehicle 58 | )), 59 | TireSizeSpecification("Tire Size Specification", listOf( 60 | ScanPluginCategory.Vehicle 61 | )), 62 | CommercialTireID("Commercial Tire ID", listOf( 63 | ScanPluginCategory.Vehicle 64 | )), 65 | TireMake("Tire Make", listOf( 66 | ScanPluginCategory.Vehicle 67 | )), 68 | VIN("VIN", listOf( 69 | ScanPluginCategory.Vehicle 70 | )), 71 | ShippingContainerNumber("Shipping Container Number", listOf( 72 | ScanPluginCategory.Others 73 | )), 74 | CustomOCR("Custom OCR", listOf( 75 | ScanPluginCategory.MeterReading, 76 | ScanPluginCategory.Others 77 | )) 78 | } 79 | 80 | val description: String? 81 | val descriptionLinks: List 82 | 83 | val pluginTypeList: List 84 | var pluginWorkflow: ScanPluginWorkflow = ScanPluginWorkflow.Simple 85 | 86 | init { 87 | pluginTypeList = mutableListOf() 88 | descriptionLinks = mutableListOf() 89 | if (isValid()) { 90 | description = scanViewConfig?.scanViewConfigDescription?.let { 91 | loadLinksFromDescription( 92 | scanViewConfig.scanViewConfigDescription, 93 | descriptionLinks) 94 | } ?: run { "" } 95 | scanViewConfig?.let { scanViewConfig -> 96 | val viewPluginConfigs = 97 | scanViewConfig.viewPluginConfig?.let { viewPluginConfig -> 98 | pluginWorkflow = ScanPluginWorkflow.Simple 99 | listOf(viewPluginConfig) 100 | } ?: run { 101 | scanViewConfig.viewPluginCompositeConfig?.let { viewPluginCompositeConfig -> 102 | pluginWorkflow = when (viewPluginCompositeConfig.processingMode) { 103 | ViewPluginCompositeConfig.ProcessingMode.PARALLEL, 104 | ViewPluginCompositeConfig.ProcessingMode.PARALLEL_FIRST_SCAN -> 105 | ScanPluginWorkflow.CompositeParallel 106 | ViewPluginCompositeConfig.ProcessingMode.SEQUENTIAL -> 107 | ScanPluginWorkflow.CompositeSequential 108 | } 109 | viewPluginCompositeConfig.viewPlugins?.map { it.viewPluginConfig } 110 | } 111 | } 112 | viewPluginConfigs?.forEach { viewPluginConfig -> 113 | with(viewPluginConfig.pluginConfig) { 114 | val pluginTypeName = when { 115 | barcodeConfig != null -> ScanPluginType.Barcode 116 | meterConfig != null -> ScanPluginType.Meter 117 | odometerConfig != null -> ScanPluginType.DigitalOdometer 118 | universalIdConfig != null -> ScanPluginType.ID 119 | japaneseLandingPermissionConfig != null -> ScanPluginType.JapaneseLandingPermission 120 | mrzConfig != null -> ScanPluginType.MRZ 121 | vehicleRegistrationCertificateConfig != null -> ScanPluginType.VehicleRegistrationCertificate 122 | licensePlateConfig != null -> ScanPluginType.LicensePlate 123 | tinConfig != null -> ScanPluginType.TINDOT 124 | tireSizeConfig != null -> ScanPluginType.TireSizeSpecification 125 | commercialTireIdConfig != null -> ScanPluginType.CommercialTireID 126 | tireMakeConfig != null -> ScanPluginType.TireMake 127 | vinConfig != null -> ScanPluginType.VIN 128 | containerConfig != null -> ScanPluginType.ShippingContainerNumber 129 | ocrConfig != null -> ScanPluginType.CustomOCR 130 | 131 | else -> null 132 | } 133 | pluginTypeName?.let { 134 | pluginTypeList.add(it) 135 | } 136 | } 137 | } 138 | } 139 | } 140 | else { 141 | description = null 142 | } 143 | } 144 | 145 | fun fileNameWithPath() = "$assetFolderName${File.separatorChar}$fileName" 146 | 147 | fun isValid() = scanViewConfig != null 148 | 149 | private fun loadLinksFromDescription(originalDescription: String, containedUrls: MutableList) 150 | : String { 151 | var updatedDescription = originalDescription 152 | val urlMatcher = urlPattern.matcher(originalDescription) 153 | containedUrls.clear() 154 | while (urlMatcher.find()) { 155 | val newLink = originalDescription.substring( 156 | urlMatcher.start(0), 157 | urlMatcher.end(0)) 158 | containedUrls.add(newLink.trim()) 159 | 160 | updatedDescription = updatedDescription.removeRange( 161 | urlMatcher.start(0), 162 | urlMatcher.end(0)) 163 | } 164 | 165 | return updatedDescription 166 | } 167 | 168 | /* 169 | * Returns true when configured for a single barcode scanner without any ScanFeedbackConfig 170 | */ 171 | fun shouldUseOverlayActivity(): Boolean { 172 | return scanViewConfig?.viewPluginConfig?.let { viewPluginConfig -> 173 | viewPluginConfig.pluginConfig?.barcodeConfig != null && 174 | (scanViewConfig?.scanViewConfigDescription?.contains("overlay") ?: false) 175 | } ?: run {false } 176 | } 177 | 178 | companion object { 179 | private val urlPattern = Pattern.compile( 180 | "(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)" 181 | + "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*" 182 | + "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)", 183 | Pattern.CASE_INSENSITIVE + Pattern.MULTILINE + Pattern.DOTALL) 184 | 185 | fun loadFromFile(context: Context, assetFolderName: String, fileName: String): ScanViewConfigFile { 186 | val fileContent = context.assets.open("$assetFolderName/$fileName").bufferedReader().use { 187 | it.readText() 188 | } 189 | val scanViewJsonValidationResult = ScanViewConfigHolder.validateJsonObject(context, JSONObject(fileContent)) 190 | when (scanViewJsonValidationResult) { 191 | is ScanViewJsonValidationResult.ValidationSucceeded -> { 192 | var scanViewConfig: ScanViewConfiguration? = null 193 | scanViewJsonValidationResult.scanViewConfigHolder.modifyViewConfig { scanViewConfigContent -> 194 | scanViewConfig = scanViewConfigContent 195 | ScanViewConfigHolder.ModifyViewConfigResult.Discard 196 | } 197 | return ScanViewConfigFile(assetFolderName, 198 | fileName, 199 | fileContent, 200 | scanViewConfig) 201 | } 202 | is ScanViewJsonValidationResult.ValidationFailed -> { 203 | return ScanViewConfigFile(assetFolderName, 204 | fileName, 205 | fileContent, 206 | null, 207 | scanViewJsonValidationResult.exception.localizedMessage) 208 | } 209 | } 210 | } 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/scanViewConfig/ScanViewConfigFolder.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples.scanViewConfig 2 | 3 | import android.content.Context 4 | import java.io.File 5 | import java.io.IOException 6 | 7 | data class ScanViewConfigFolder(val assetFolderName: String, 8 | val friendlyName: String, 9 | val parent: ScanViewConfigFolder?) { 10 | 11 | private val folderList = mutableListOf() 12 | private val fileList = mutableListOf() 13 | 14 | private val allFiles: List 15 | get() { 16 | return fileList + folderList.flatMap { it.allFiles } 17 | } 18 | 19 | enum class ListOptions(val description: String) { 20 | OriginalStructure("Original folder structure"), 21 | GroupByPluginType("Group by plugin type"), 22 | GroupByCategory("Group by category"), 23 | GroupByWorkflow("Group by workflow"); 24 | 25 | companion object { 26 | fun asDescriptionList(): Array { 27 | val descriptionList = values().map { it.description } 28 | return descriptionList.toTypedArray() 29 | } 30 | } 31 | } 32 | 33 | fun asOrderedList(): List { 34 | return mutableListOf().apply { 35 | addAll(folderList) 36 | addAll(fileList) 37 | } 38 | } 39 | 40 | companion object { 41 | fun loadFromFolder(context: Context, 42 | assetFolderName: String, 43 | friendlyName: String, 44 | listOptions: ListOptions): ScanViewConfigFolder? { 45 | 46 | val scanViewConfigOriginalFolder = loadRecursivelyFromFolder(context, 47 | assetFolderName, 48 | friendlyName, 49 | null) 50 | 51 | return when (listOptions) { 52 | ListOptions.OriginalStructure -> { 53 | scanViewConfigOriginalFolder 54 | } 55 | ListOptions.GroupByPluginType -> { 56 | ScanViewConfigFolder(assetFolderName, friendlyName, null).run { 57 | scanViewConfigOriginalFolder?.allFiles?.forEach { file -> 58 | file.pluginTypeList.forEach { pluginType -> 59 | val folder = this.folderList.firstOrNull { 60 | it.friendlyName == pluginType.description 61 | } ?: ScanViewConfigFolder(file.assetFolderName, pluginType.description, this).also { 62 | folderList.add(it) 63 | } 64 | if (!folder.fileList.contains(file)) { 65 | folder.fileList.add(file) 66 | } 67 | } 68 | } 69 | this 70 | } 71 | } 72 | ListOptions.GroupByCategory -> { 73 | ScanViewConfigFolder(assetFolderName, friendlyName, null).run { 74 | scanViewConfigOriginalFolder?.allFiles?.forEach { file -> 75 | file.pluginTypeList.forEach { pluginType -> 76 | pluginType.categories.forEach { pluginCategory -> 77 | val folder = this.folderList.firstOrNull { 78 | it.friendlyName == pluginCategory.description 79 | } ?: ScanViewConfigFolder(file.assetFolderName, pluginCategory.description, this).also { 80 | folderList.add(it) 81 | } 82 | if (!folder.fileList.contains(file)) { 83 | folder.fileList.add(file) 84 | } 85 | } 86 | } 87 | } 88 | this 89 | } 90 | } 91 | ListOptions.GroupByWorkflow -> { 92 | ScanViewConfigFolder(assetFolderName, friendlyName, null).run { 93 | scanViewConfigOriginalFolder?.allFiles?.forEach { file -> 94 | val folder = this.folderList.firstOrNull { 95 | it.friendlyName == file.pluginWorkflow.description 96 | } ?: ScanViewConfigFolder(file.assetFolderName, file.pluginWorkflow.description, this).also { 97 | folderList.add(it) 98 | } 99 | if (!folder.fileList.contains(file)) { 100 | folder.fileList.add(file) 101 | } 102 | } 103 | this 104 | } 105 | } 106 | } 107 | } 108 | 109 | private fun loadRecursivelyFromFolder(context: Context, 110 | assetFolderName: String, 111 | friendlyName: String, 112 | parent: ScanViewConfigFolder?): ScanViewConfigFolder? { 113 | val scanViewConfigFolder = ScanViewConfigFolder(assetFolderName, friendlyName, parent) 114 | context.assets.list(assetFolderName)?.also { listFiles -> 115 | if (listFiles.isNotEmpty()) { 116 | listFiles.forEach { fileOrFolder -> 117 | try { 118 | val subFolder = loadRecursivelyFromFolder(context, 119 | "$assetFolderName${File.separatorChar}$fileOrFolder", 120 | fileOrFolder, 121 | scanViewConfigFolder) 122 | subFolder?.let { 123 | scanViewConfigFolder.folderList.add(it) 124 | } 125 | } 126 | catch (e: IOException) { 127 | return null 128 | } 129 | } 130 | } 131 | else { 132 | parent?.let { parentFolder -> 133 | parentFolder.fileList.add( 134 | ScanViewConfigFile.loadFromFile(context, parentFolder.assetFolderName, friendlyName)) 135 | } 136 | return null 137 | } 138 | } 139 | return scanViewConfigFolder 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/viewConfigEditor/ViewConfigEditorActivity.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples.viewConfigEditor 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.view.Menu 7 | import android.view.MenuItem 8 | import androidx.appcompat.app.AppCompatActivity 9 | import com.anyline.examples.ScanActivity 10 | import com.anyline.examples.databinding.ActivityViewConfigEditorBinding 11 | import org.json.JSONObject 12 | 13 | class ViewConfigEditorActivity : AppCompatActivity() { 14 | 15 | private lateinit var binding: ActivityViewConfigEditorBinding 16 | 17 | private var webContentAction: WebContentFragmentAction? = null 18 | 19 | override fun onCreate(savedInstanceState: Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | 22 | binding = ActivityViewConfigEditorBinding.inflate(layoutInflater) 23 | setContentView(binding.root) 24 | 25 | val webContentFragment = ViewConfigEditorFragment( 26 | ViewConfigEditorDefinition.ScanViewConfig, 27 | JSONObject(intent.getStringExtra(EXTRA_CONTENT)) 28 | ) { updatedJson -> 29 | val intent = ScanActivity.buildIntent(this@ViewConfigEditorActivity, updatedJson) 30 | startActivity(intent) 31 | this@ViewConfigEditorActivity.finish() 32 | } 33 | 34 | binding.fragmentContainerWebview.apply { 35 | supportFragmentManager.beginTransaction() 36 | .add(this.id, webContentFragment.also { 37 | webContentAction = it 38 | }) 39 | .commit() 40 | } 41 | 42 | setupToolbar() 43 | } 44 | 45 | private fun setupToolbar() { 46 | supportActionBar?.setDisplayHomeAsUpEnabled(true) 47 | title = intent.getStringExtra(EXTRA_TITLE) 48 | } 49 | 50 | override fun onCreateOptionsMenu(menu: Menu?): Boolean { 51 | return super.onCreateOptionsMenu(menu) 52 | } 53 | 54 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 55 | if (item.itemId == android.R.id.home) { 56 | onBackPressed() 57 | return true 58 | } 59 | return super.onOptionsItemSelected(item) 60 | } 61 | 62 | override fun onBackPressed() { 63 | webContentAction?.let { 64 | val canGoBack = it.goBack() 65 | if (!canGoBack) { 66 | onBackPressedDispatcher.onBackPressed() 67 | } 68 | } 69 | } 70 | 71 | companion object { 72 | 73 | private const val EXTRA_TITLE = "EXTRA_TITLE" 74 | private const val EXTRA_CONTENT = "EXTRA_CONTENT" 75 | 76 | fun buildIntent( 77 | context: Context, 78 | title: String, 79 | content: String 80 | ): Intent { 81 | return Intent( 82 | context, ViewConfigEditorActivity::class.java 83 | ).apply { 84 | this.putExtra(EXTRA_TITLE, title) 85 | this.putExtra(EXTRA_CONTENT, content) 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/viewConfigEditor/ViewConfigEditorFragment.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples.viewConfigEditor 2 | 3 | import android.content.Context 4 | import android.webkit.ConsoleMessage 5 | import android.webkit.WebResourceRequest 6 | import android.webkit.WebView 7 | import androidx.webkit.WebResourceErrorCompat 8 | import com.anyline.examples.viewConfigEditor.WebContentFragmentCallback.UrlData 9 | import org.json.JSONException 10 | import org.json.JSONObject 11 | import timber.log.Timber 12 | 13 | enum class ViewConfigEditorDefinition(val definition: String) { 14 | ScanViewConfig(""), 15 | CameraConfig("#/definitions/cameraConfig"), 16 | FlashConfig("#/definitions/flashConfig"), 17 | ViewPluginConfig("#/definitions/viewPluginConfig"), 18 | ViewPluginCompositeConfig("#/definitions/viewPluginCompositeConfig"), 19 | PluginConfig("#/definitions/viewPluginConfig/pluginConfig"), 20 | CutoutConfig("#/definitions/viewPluginConfig/definitions/cutoutConfig"), 21 | ScanFeedbackConfig("#/definitions/viewPluginConfig/definitions/scanFeedbackConfig"), 22 | UIFeedbackConfig("#/definitions/viewPluginConfig/uiFeedbackConfig") 23 | } 24 | 25 | class ViewConfigEditorFragment(viewConfigEditorDefinition: ViewConfigEditorDefinition, 26 | jsonContent: JSONObject?, 27 | val onJsonApply: ((JSONObject) -> Unit) 28 | ): WebContentFragment() { 29 | private val editorHomeUrl = "viewConfigEditor/json-editor-css.html" 30 | 31 | private val jsonSchemaRemoteUrl = "https://documentation.anyline.com/android-sdk-component/latest/_attachments/json-schemas/sdk_config.schema.json" 32 | 33 | init { 34 | webContentCallback = object : WebContentFragmentCallback { 35 | override fun getHomeUrl(context: Context): String? = null 36 | 37 | override fun getHomeUrlData(context: Context): UrlData? { 38 | val schemaContent = "{\"\$ref\": \"${jsonSchemaRemoteUrl + viewConfigEditorDefinition.definition}\"}" 39 | var htmlContent = context.assets.open(editorHomeUrl).bufferedReader().use { 40 | it.readText() 41 | } 42 | htmlContent = htmlContent.replace("schema: {}", "schema: $schemaContent") 43 | htmlContent = htmlContent.replace("starting_value = {}", "starting_value = ${jsonContent.toString()}") 44 | return UrlData(data = htmlContent, baseUrl = "file:///android_asset/viewConfigEditor/") 45 | } 46 | 47 | override fun isSwipeRefreshEnabled() = false 48 | override fun isFileChooserEnabled() = false 49 | override fun shouldOpenUrlInExternalBrowser(view: WebView, url: String) = false 50 | 51 | override fun onPageFinished(view: WebView, url: String) { 52 | Timber.tag("ViewConfigEditorFragment.onPageFinished") 53 | .d(url) 54 | } 55 | 56 | override fun onReceivedError( 57 | webView: WebView, 58 | webResourceRequest: WebResourceRequest, 59 | webResourceErrorCompat: WebResourceErrorCompat 60 | ): Boolean { 61 | return true 62 | } 63 | 64 | override fun onReceivedTitle(title: String) { 65 | //nothing to do with tile here 66 | } 67 | 68 | override fun onConsoleMessage(consoleMessage: ConsoleMessage) { 69 | val consoleMessageString = consoleMessage.message().toString() 70 | try { 71 | val consoleMessageJson = JSONObject(consoleMessageString) 72 | val readyState = consoleMessageJson.optBoolean("readyState", false) 73 | if (readyState) { 74 | this@ViewConfigEditorFragment.onEditorFinishedLoading() 75 | } 76 | consoleMessageJson.optJSONObject("content")?.let { updatedJson -> 77 | onJsonApply.invoke(updatedJson) 78 | } 79 | } 80 | catch (e: JSONException) { 81 | //ignore invalid console output 82 | } 83 | } 84 | } 85 | } 86 | 87 | fun onEditorFinishedLoading() { 88 | super.switchLoadingState(false, null) 89 | } 90 | 91 | override fun switchLoadingState(loadingState: Boolean, error: WebResourceErrorCompat?) { 92 | if (!loadingState && error == null) { 93 | //ignore finished connection state changes, only apply when editor finished loading 94 | return 95 | } 96 | super.switchLoadingState(loadingState, error) 97 | } 98 | } -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/viewConfigEditor/WebContentFragmentAction.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples.viewConfigEditor 2 | 3 | interface WebContentFragmentAction { 4 | fun goBack(): Boolean 5 | 6 | fun getCurrentUrl(): String? 7 | 8 | fun loadUrl(url: String) 9 | 10 | fun loadDataWithBaseURL(urlData: WebContentFragmentCallback.UrlData) 11 | 12 | fun reload() 13 | 14 | } -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/java/com/anyline/examples/viewConfigEditor/WebContentFragmentCallback.kt: -------------------------------------------------------------------------------- 1 | package com.anyline.examples.viewConfigEditor 2 | 3 | import android.content.Context 4 | import android.webkit.ConsoleMessage 5 | import android.webkit.WebResourceRequest 6 | import android.webkit.WebView 7 | import androidx.webkit.WebResourceErrorCompat 8 | 9 | interface WebContentFragmentCallback { 10 | data class UrlData(val data: String, 11 | val baseUrl: String?, 12 | val mimeType: String? = "text/html", 13 | val encoding: String? = "UTF-8", 14 | val historyUrl: String? = null) 15 | fun getHomeUrl(context: Context): String? 16 | fun getHomeUrlData(context: Context): UrlData? 17 | fun isSwipeRefreshEnabled(): Boolean 18 | fun isFileChooserEnabled(): Boolean 19 | fun shouldOpenUrlInExternalBrowser(view: WebView, url: String): Boolean 20 | 21 | fun onPageFinished(view: WebView, url: String) 22 | fun onReceivedError(webView: WebView, 23 | webResourceRequest: WebResourceRequest, 24 | webResourceErrorCompat: WebResourceErrorCompat): Boolean 25 | 26 | fun onReceivedTitle(title: String) 27 | fun onConsoleMessage(consoleMessage: ConsoleMessage) 28 | } -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-hdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-hdpi/ic_file.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-hdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-hdpi/ic_folder.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-mdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-mdpi/ic_file.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-mdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-mdpi/ic_folder.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-xhdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-xhdpi/ic_file.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-xhdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-xhdpi/ic_folder.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-xxhdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-xxhdpi/ic_file.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-xxhdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-xxhdpi/ic_folder.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-xxxhdpi/ic_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-xxxhdpi/ic_file.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable-xxxhdpi/ic_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable-xxxhdpi/ic_folder.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/ic_action_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/ic_action_pencil.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/ic_barcode_overlay_checkmark_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable/ic_barcode_overlay_checkmark_green.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/ic_barcode_overlay_far_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable/ic_barcode_overlay_far_blue.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/ic_barcode_overlay_far_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable/ic_barcode_overlay_far_green.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/ic_barcode_overlay_plus_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable/ic_barcode_overlay_plus_blue.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/ic_help_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/selected_barcode_overlay_rounded_corner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/uifeedback_inprogress_tire_make.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable/uifeedback_inprogress_tire_make.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/uifeedback_inprogress_tire_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable/uifeedback_inprogress_tire_size.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/uifeedback_inprogress_tire_tin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable/uifeedback_inprogress_tire_tin.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/drawable/webcontent_no_network_error_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anyline/anyline-ocr-examples-android/a25677597c638db1954ac35990029b71df530d41/AnylineExamples/app/src/main/res/drawable/webcontent_no_network_error_image.png -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 29 | 36 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /AnylineExamples/app/src/main/res/layout/activity_scan.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 22 | 23 | 34 | 35 | 44 | 45 | 52 | 65 | 73 | 80 |