From 4cff110b2a2cfd23c031699972c741b2a7348581 Mon Sep 17 00:00:00 2001 From: Patrick Fekete Date: Wed, 22 Jun 2022 13:59:05 +0200 Subject: [PATCH 1/3] Release version 40.0.0 --- .../app/build.gradle | 30 +- .../app/src/main/AndroidManifest.xml | 30 +- ..._authentication_arabic_id_view_config.json | 68 - ...uthentication_cyrillic_id_view_config.json | 68 - .../face_authentication_id_view_config.json | 87 - ..._registration_certificate_view_config.json | 69 + .../io/anyline/examples/MainActivity.java | 9 +- .../io/anyline/examples/ScanModuleEnum.java | 4 +- .../barcode/BarcodeListViewActivity.java | 17 +- ...fferences.java => BarcodePreferences.java} | 10 +- .../anyline/examples/barcode/BarcodeView.kt | 83 + .../examples/barcode/ScanBarcodeActivity.java | 320 ---- .../examples/barcode/ScanBarcodeActivity.kt | 346 ++++ .../ScanBarcodeWithOverlaysActivity.kt | 705 ++++++++ .../examples/barcode/VisibleBarcode.kt | 53 + .../basefragments/OthersFragment.java | 20 +- .../basefragments/ProductsFragment.java | 8 +- .../dependencyinjection/DispatchersModule.kt | 46 + ...ehicleRegistrationCertificateActivity.java | 115 ++ .../io/anyline/examples/util/Preferences.java | 15 +- .../activity_anyline_barcode_scan_view.xml | 3 - ...tivity_anyline_multi_barcode_scan_view.xml | 162 ++ .../menu_scan_change_script_face_auth.xml | 10 - .../main/res/values/example_activities.xml | 30 +- .../app/src/main/res/values/strings.xml | 13 +- .../AnylineSDK-Examples-Source/build.gradle | 16 +- .../dependencyversions.gradle | 26 + AnylineSDK/anylinesdk-38.0.1.aar | 3 - AnylineSDK/anylinesdk-40.0.0.aar | 3 + Documentation/javadoc/allclasses-index.html | 376 +++-- Documentation/javadoc/allclasses.html | 8 +- Documentation/javadoc/constant-values.html | 9 +- Documentation/javadoc/deprecated-list.html | 15 +- Documentation/javadoc/index-all.html | 176 +- .../VisualFeedbackConfig.FeedbackStyle.html | 15 +- .../io/anyline/plugin/AbstractScanPlugin.html | 92 +- .../javadoc/io/anyline/plugin/ScanPlugin.html | 54 +- .../io/anyline/plugin/barcode/Barcode.html | 40 +- .../plugin/barcode/BarcodeScanPlugin.html | 2 +- .../barcode/ScannedBarcodesListener.html | 10 + .../plugin/barcode/package-summary.html | 4 +- .../plugin/document/DocumentScanPlugin.html | 2 +- .../io/anyline/plugin/id/IdScanPlugin.html | 2 +- .../anyline/plugin/id/UniversalIdConfig.html | 2 +- ...VehicleRegistrationCertificateConfig.html} | 141 +- .../io/anyline/plugin/id/package-summary.html | 4 + .../io/anyline/plugin/id/package-tree.html | 1 + .../licenseplate/LicensePlateScanMode.html | 26 +- .../licenseplate/LicensePlateScanPlugin.html | 62 +- .../anyline/plugin/meter/MeterScanPlugin.html | 2 +- .../plugin/ocr/AnylineOcrBaseConfig.html | 2 +- .../plugin/ocr/AnylineTINConfig.ScanMode.html | 392 ----- .../ocr/AnylineTINConfig.UpsideDownMode.html | 392 ----- .../anyline/plugin/ocr/AnylineTINConfig.html | 425 ----- .../io/anyline/plugin/ocr/OcrScanPlugin.html | 2 +- .../io/anyline/plugin/ocr/OcrScanResult.html | 4 - .../anyline/plugin/ocr/package-summary.html | 24 +- .../io/anyline/plugin/ocr/package-tree.html | 9 +- .../plugin/tire/CommercialTireIdConfig.html | 30 +- .../plugin/tire/TINConfig.UpsideDownMode.html | 392 ----- .../io/anyline/plugin/tire/TINConfig.html | 53 +- ...tml => TireBaseConfig.UpsideDownMode.html} | 34 +- .../anyline/plugin/tire/TireBaseConfig.html | 89 +- .../anyline/plugin/tire/TireScanPlugin.html | 2 +- .../anyline/plugin/tire/TireSizeConfig.html | 85 +- .../anyline/plugin/tire/package-summary.html | 6 +- .../io/anyline/plugin/tire/package-tree.html | 3 +- .../javadoc/io/anyline/util/ConstantUtil.html | 20 +- .../view/CutoutConfig.CutoutStyle.html | 35 +- Documentation/javadoc/member-search-index.js | 2 +- Documentation/javadoc/member-search-index.zip | Bin 21538 -> 21430 bytes Documentation/javadoc/overview-summary.html | 2 +- Documentation/javadoc/overview-tree.html | 13 +- .../javadoc/package-search-index.zip | Bin 314 -> 314 bytes Documentation/javadoc/type-search-index.js | 2 +- Documentation/javadoc/type-search-index.zip | Bin 1772 -> 1778 bytes README.md | 12 +- com.anyline.android.sdk.swidtag | 1416 ++++++++++------- 78 files changed, 3239 insertions(+), 3619 deletions(-) delete mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_arabic_id_view_config.json delete mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_cyrillic_id_view_config.json delete mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_id_view_config.json create mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/vehicle_registration_certificate_view_config.json rename AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/{BarcodePrefferences.java => BarcodePreferences.java} (91%) create mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodeView.kt delete mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeActivity.java create mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeActivity.kt create mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeWithOverlaysActivity.kt create mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/VisibleBarcode.kt create mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/dependencyinjection/DispatchersModule.kt create mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/id/ScanVehicleRegistrationCertificateActivity.java create mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/res/layout/activity_anyline_multi_barcode_scan_view.xml delete mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/res/menu/menu_scan_change_script_face_auth.xml create mode 100644 AnylineSDK-Examples/AnylineSDK-Examples-Source/dependencyversions.gradle delete mode 100644 AnylineSDK/anylinesdk-38.0.1.aar create mode 100644 AnylineSDK/anylinesdk-40.0.0.aar rename Documentation/javadoc/io/anyline/plugin/{ocr/TINResult.html => id/VehicleRegistrationCertificateConfig.html} (51%) delete mode 100644 Documentation/javadoc/io/anyline/plugin/ocr/AnylineTINConfig.ScanMode.html delete mode 100644 Documentation/javadoc/io/anyline/plugin/ocr/AnylineTINConfig.UpsideDownMode.html delete mode 100644 Documentation/javadoc/io/anyline/plugin/ocr/AnylineTINConfig.html delete mode 100644 Documentation/javadoc/io/anyline/plugin/tire/TINConfig.UpsideDownMode.html rename Documentation/javadoc/io/anyline/plugin/tire/{TireSizeConfig.UpsideDownMode.html => TireBaseConfig.UpsideDownMode.html} (86%) diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/build.gradle b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/build.gradle index 2c44ee1b..c9872ee2 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/build.gradle +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/build.gradle @@ -8,8 +8,14 @@ apply plugin: 'kotlinx-serialization' apply plugin: 'dagger.hilt.android.plugin' buildscript { - ext.sdk_version = "38.0.1" - ext.version_code = 361 + ext { + sdk_version = "40.0.0" + app_version = "40.0.0" + version_code = 367 + + timber_version = '5.0.1' + leakcanary_version = '2.8.1' + } repositories { mavenCentral() } @@ -20,15 +26,15 @@ buildscript { } android { - compileSdkVersion 30 + compileSdkVersion versions.compileSdk buildToolsVersion '28.0.3' defaultConfig { vectorDrawables.useSupportLibrary = true - minSdkVersion 21 - targetSdkVersion 30 + minSdkVersion versions.minSdk + targetSdkVersion versions.targetSdk versionCode version_code - versionName sdk_version + versionName app_version ndk { abiFilters "armeabi-v7a", "arm64-v8a" @@ -84,18 +90,20 @@ dependencies { implementation 'androidx.multidex:multidex:2.0.1' implementation 'com.github.bumptech.glide:glide:4.11.0' + implementation "com.jakewharton.timber:timber:$timber_version" + + // debugImplementation because LeakCanary should only run in debug builds. + debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakcanary_version" + // for update manager //implementation 'com.google.android.play:core:1.9.0' //uncomment if you want to import the AnylineSdk project -// implementation project(':AnylineSdk') + //implementation project(':AnylineSdk') //include AnylineSDK from maven implementation "io.anyline:anylinesdk:$sdk_version" - // Face authentication - implementation "io.anyline:facetec-sdk:9.4.5" - //Play core library implementation 'com.google.android.play:core-ktx:1.8.1' @@ -103,7 +111,7 @@ dependencies { //Kotlin implementation "androidx.core:core-ktx:1.3.2" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}" //Kotlin coroutines implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1' diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/AndroidManifest.xml b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/AndroidManifest.xml index b610b021..a791f15c 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/AndroidManifest.xml +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/AndroidManifest.xml @@ -147,6 +147,15 @@ android:name="android.support.PARENT_ACTIVITY" android:value="io.anyline.examples.MainActivity" /> + + + + + + + - - - - - - \ No newline at end of file diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_arabic_id_view_config.json b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_arabic_id_view_config.json deleted file mode 100644 index 1db6a849..00000000 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_arabic_id_view_config.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "camera" : { - "captureResolution" : "1080p", - "zoomGesture": true - }, - "flash" : { - "mode": "manual", - "alignment": "bottom_right", - "imageOn": "flash_on", - "imageOff": "flash_off" - }, - "viewPlugin" : { - "plugin":{ - "id":"ID", - "idPlugin": { - "universalIdConfig": { - "alphabet": "arabic", - "faceDetection": true, - "allowedLayouts": { - "mrz": [], - "idFront": [] - }, - "idFront": { - "fullName": {"scanOption": 0, "minConfidence": 60}, - "dateOfBirth": {"scanOption": 0, "minConfidence": 60}, - "placeOfBirth": {"scanOption": 1, "minConfidence": 60}, - "dateOfExpiry": {"scanOption": 1, "minConfidence": 60}, - "documentNumber": {"scanOption": 0, "minConfidence": 60}, - "nationality": {"scanOption": 1, "minConfidence": 60} - } - } - } - }, - "cutoutConfig" : { - "style": "animated_rect", - "maxWidthPercent": "80%", - "maxHeightPercent": "90%", - "alignment": "center", - "strokeWidth": 8, - "cornerRadius": 8, - "strokeColor": "FFFFFF", - "outerColor": "FFFFFF", - "ratioFromSize" : { - "width": 50, - "height": 31 - }, - "cropPadding": { - "x": -50, - "y": -50 - }, - "cropOffset": { - "x": 0, - "y": 0 - }, - "feedbackStrokeColor": "0099FF" - }, - "scanFeedback" : { - "style": "CONTOUR_RECT", - "visualFeedbackRedrawTimeout": 100, - "strokeColor": "0099FF", - "fillColor" : "220099FF", - "beepOnResult": true, - "vibrateOnResult": true, - "strokeWidth": 2 - }, - "cancelOnResult" : true - } -} diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_cyrillic_id_view_config.json b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_cyrillic_id_view_config.json deleted file mode 100644 index 06c8dee8..00000000 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_cyrillic_id_view_config.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "camera" : { - "captureResolution" : "1080p", - "zoomGesture": true - }, - "flash" : { - "mode": "manual", - "alignment": "bottom_right", - "imageOn": "flash_on", - "imageOff": "flash_off" - }, - "viewPlugin" : { - "plugin":{ - "id":"ID", - "idPlugin": { - "universalIdConfig": { - "alphabet": "cyrillic", - "faceDetection": true, - "allowedLayouts": { - "mrz": [], - "idFront": [] - }, - "idFront": { - "fullName": {"scanOption": 0, "minConfidence": 60}, - "dateOfBirth": {"scanOption": 0, "minConfidence": 60}, - "placeOfBirth": {"scanOption": 1, "minConfidence": 60}, - "dateOfExpiry": {"scanOption": 1, "minConfidence": 60}, - "documentNumber": {"scanOption": 0, "minConfidence": 60}, - "nationality": {"scanOption": 1, "minConfidence": 60} - } - } - } - }, - "cutoutConfig" : { - "style": "animated_rect", - "maxWidthPercent": "80%", - "maxHeightPercent": "90%", - "alignment": "center", - "strokeWidth": 8, - "cornerRadius": 8, - "strokeColor": "FFFFFF", - "outerColor": "FFFFFF", - "ratioFromSize" : { - "width": 50, - "height": 31 - }, - "cropPadding": { - "x": -50, - "y": -50 - }, - "cropOffset": { - "x": 0, - "y": 0 - }, - "feedbackStrokeColor": "0099FF" - }, - "scanFeedback" : { - "style": "CONTOUR_RECT", - "visualFeedbackRedrawTimeout": 100, - "strokeColor": "0099FF", - "fillColor" : "220099FF", - "beepOnResult": true, - "vibrateOnResult": true, - "strokeWidth": 2 - }, - "cancelOnResult" : true - } -} diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_id_view_config.json b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_id_view_config.json deleted file mode 100644 index 731daf23..00000000 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/face_authentication_id_view_config.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "camera" : { - "captureResolution" : "1080p", - "zoomGesture": true - }, - "flash" : { - "mode": "manual", - "alignment": "bottom_right", - "imageOn": "flash_on", - "imageOff": "flash_off" - }, - "viewPlugin" : { - "plugin":{ - "id":"ID", - "idPlugin": { - "universalIdConfig": { - "faceDetection": true, - "allowedLayouts": { - "mrz": [], - "drivingLicense": [], - "idFront": [] - }, - "drivingLicense": { - "lastName": {"scanOption": 0, "minConfidence": 40}, - "firstName": {"scanOption": 0, "minConfidence": 40}, - "fullName": {"scanOption": 0, "minConfidence": 40}, - "dateOfBirth": {"scanOption": 0, "minConfidence": 50}, - "placeOfBirth": {"scanOption": 1, "minConfidence": 50}, - "dateOfIssue": {"scanOption": 0, "minConfidence": 50}, - "dateOfExpiry": {"scanOption": 1, "minConfidence": 50}, - "authority": {"scanOption": 1, "minConfidence": 30}, - "documentNumber": {"scanOption": 0, "minConfidence": 40}, - "licenseClass": {"scanOption": 1, "minConfidence": 30}, - "address": {"scanOption": 0}, - "sex": {"scanOption": 1,"minConfidence": 60} - }, - "idFront": { - "lastName": {"scanOption": 0, "minConfidence": 60}, - "firstName": {"scanOption": 0, "minConfidence": 60}, - "fullName": {"scanOption": 0, "minConfidence": 40}, - "dateOfBirth": {"scanOption": 0,"minConfidence": 60}, - "placeOfBirth": {"scanOption": 1,"minConfidence": 60}, - "dateOfIssue": {"scanOption": 0, "minConfidence": 60}, - "dateOfExpiry": {"scanOption": 1,"minConfidence": 60}, - "cardAccessNumber": {"scanOption": 1,"minConfidence": 60}, - "documentNumber": {"scanOption": 0,"minConfidence": 60}, - "nationality": {"scanOption": 1,"minConfidence": 60}, - "sex": {"scanOption": 1,"minConfidence": 60} - } - } - } - }, - "cutoutConfig" : { - "style": "animated_rect", - "maxWidthPercent": "80%", - "maxHeightPercent": "90%", - "alignment": "center", - "strokeWidth": 8, - "cornerRadius": 8, - "strokeColor": "FFFFFF", - "outerColor": "FFFFFF", - "ratioFromSize" : { - "width": 50, - "height": 31 - }, - "cropPadding": { - "x": -50, - "y": -50 - }, - "cropOffset": { - "x": 0, - "y": 0 - }, - "feedbackStrokeColor": "0099FF" - }, - "scanFeedback" : { - "style": "CONTOUR_RECT", - "visualFeedbackRedrawTimeout": 100, - "strokeColor": "0099FF", - "fillColor" : "220099FF", - "beepOnResult": true, - "vibrateOnResult": true, - "strokeWidth": 2 - }, - "cancelOnResult" : true - } -} \ No newline at end of file diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/vehicle_registration_certificate_view_config.json b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/vehicle_registration_certificate_view_config.json new file mode 100644 index 00000000..e65c89c2 --- /dev/null +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/assets/vehicle_registration_certificate_view_config.json @@ -0,0 +1,69 @@ +{ + "camera" : { + "captureResolution" : "1080p" + }, + "flash" : { + "mode": "manual", + "alignment": "bottom_right", + "imageOn": "flash_on", + "imageOff": "flash_off" + }, + "viewPlugin" : { + "plugin":{ + "id":"ID", + "idPlugin": { + "vehicleRegistrationCertificateConfig": { + "layoutVehicleCertificate": { + "documentNumber": {"scanOption": 0, "minConfidence": 50}, + "licensePlate": {"scanOption": 0, "minConfidence": 50}, + "lastName": {"scanOption": 0, "minConfidence": 50}, + "firstName": {"scanOption": 0, "minConfidence": 50}, + "address": {"scanOption": 0, "minConfidence": 50}, + "firstIssued": {"scanOption": 0, "minConfidence": 50}, + "manufacturerCode": {"scanOption": 0, "minConfidence": 50}, + "vehicleTypeCode": {"scanOption": 0, "minConfidence": 50}, + "vehicleIdentificationNumber": {"scanOption": 0, "minConfidence": 50}, + "brand": {"scanOption": 0, "minConfidence": 50}, + "vehicleType": {"scanOption": 0, "minConfidence": 50}, + "displacement": {"scanOption": 0, "minConfidence": 50}, + "tire": {"scanOption": 0, "minConfidence": 50} + } + } + } + }, + "cutoutConfig" : { + "style": "animated_rect", + "maxWidthPercent": "90%", + "maxHeightPercent": "80%", + "alignment": "center", + "strokeWidth": 3, + "cornerRadius": 8, + "strokeColor": "FFFFFF", + "outerColor": "000000", + "outerAlpha": 0.3, + "ratioFromSize": { + "width": 90, + "height": 46 + }, + "cropPadding": { + "x": -50, + "y": -50 + }, + "cropOffset": { + "x": 0, + "y": 0 + }, + "feedbackStrokeColor": "0099FF" + }, + "scanFeedback" : { + "style": "CONTOUR_RECT", + "visualFeedbackRedrawTimeout": 100, + "strokeColor": "0099FF", + "fillColor" : "220099FF", + "beepOnResult": true, + "vibrateOnResult": true, + "strokeWidth": 2 + }, + "cancelOnResult" : true + } +} \ No newline at end of file diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/MainActivity.java b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/MainActivity.java index 61ea1541..abf3262f 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/MainActivity.java +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/MainActivity.java @@ -5,7 +5,6 @@ import android.os.Bundle; import android.widget.TextView; - import androidx.appcompat.app.AlertDialog; import at.nineyards.anyline.core.LicenseException; import io.anyline.AnylineSDK; @@ -18,12 +17,8 @@ public class MainActivity extends BaseToolbarActivity { - private TextView messageCounter; - @Override protected void onCreate(Bundle savedInstanceState) { - - super.onCreate(savedInstanceState); try { @@ -50,8 +45,8 @@ public void onClick(DialogInterface dialog, int which) { //add the view pager if (getSupportFragmentManager().findFragmentById(R.id.fragment_container) == null) { getSupportFragmentManager().beginTransaction() - .add(R.id.fragment_container, - new ViewPagerFragment()).commit(); + .add(R.id.fragment_container, + new ViewPagerFragment()).commit(); } } diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/ScanModuleEnum.java b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/ScanModuleEnum.java index da31be77..5c371efe 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/ScanModuleEnum.java +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/ScanModuleEnum.java @@ -37,6 +37,7 @@ public enum ScanModule { CATTLE_TAG, ID_CARD, PASSPORT_VISA, + VEHICLE_REGISTRATION_CERTIFICATE, /** * @deprecated As the background-selection does not exist anymore, the mode should not be used anymore @@ -80,7 +81,8 @@ public static Boolean isIDScanModule (ScanModule scanModule) { scanModule == ScanModule.GERMAN_ID_FRONT || scanModule == ScanModule.UNIVERSAL_ID || scanModule == ScanModule.ID_CARD || - scanModule == ScanModule.PASSPORT_VISA; + scanModule == ScanModule.PASSPORT_VISA || + scanModule == ScanModule.VEHICLE_REGISTRATION_CERTIFICATE; } } diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodeListViewActivity.java b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodeListViewActivity.java index 2f2a9bc1..b150e4b4 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodeListViewActivity.java +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodeListViewActivity.java @@ -23,7 +23,6 @@ import android.widget.CheckedTextView; import android.widget.ListView; import android.widget.TextView; -import android.widget.Toast; import java.util.ArrayList; @@ -41,7 +40,7 @@ public class BarcodeListViewActivity extends BaseToolbarActivity { private ListView list; private ListAdapter adapter; private CheckedTextView allBarcodeTypesCheckBox; - private BarcodePrefferences barcodePrefferences; + private BarcodePreferences barcodePreferences; ArrayList preselectedItems; ArrayList preselectedItemsUponStart; // save the selected barcodes at the beginning - to check if changes occured ArrayList itemsList; @@ -51,13 +50,13 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.barcode_list_view_activity); - barcodePrefferences = BarcodePrefferences.getInstance(this); - preselectedItems = barcodePrefferences.get(); + barcodePreferences = BarcodePreferences.getInstance(this); + preselectedItems = barcodePreferences.get(); if (preselectedItems == null || preselectedItems.size() == 0) { - barcodePrefferences.setDefault(); - preselectedItems = barcodePrefferences.get(); + barcodePreferences.setDefault(); + preselectedItems = barcodePreferences.get(); } - preselectedItemsUponStart = barcodePrefferences.get(); + preselectedItemsUponStart = barcodePreferences.get(); itemsList = new ArrayList<>(); list = findViewById(R.id.listview); @@ -100,7 +99,7 @@ public void onClick(View view) { .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //barcodePrefferences.setDefault(); - preselectedItems = barcodePrefferences.getDefault(); + preselectedItems = barcodePreferences.getDefault(); adapter.notifyDataSetChanged(); } }) @@ -353,7 +352,7 @@ public boolean onOptionsItemSelected(MenuItem item) { showAlertNoBarcodeSelected(); return false; } else { - barcodePrefferences.setBarcodeTypes(preselectedItems); + barcodePreferences.setBarcodeTypes(preselectedItems); //onBackPressed(); Intent intent = new Intent(); setResult(2, intent); diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodePrefferences.java b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodePreferences.java similarity index 91% rename from AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodePrefferences.java rename to AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodePreferences.java index 6b074306..13cf6aa5 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodePrefferences.java +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodePreferences.java @@ -11,23 +11,23 @@ import java.util.ArrayList; import java.util.List; -public class BarcodePrefferences { +public class BarcodePreferences { private static final String SHARED_PREFS_ANYLINE = "AnylinePreferences"; - private static BarcodePrefferences instance; + private static BarcodePreferences instance; private final SharedPreferences prefs; private final SharedPreferences.Editor editor; @SuppressLint("CommitPrefEdits") - private BarcodePrefferences(Context context) { + private BarcodePreferences(Context context) { prefs = context.getSharedPreferences(SHARED_PREFS_ANYLINE, Context.MODE_PRIVATE); editor = prefs.edit(); } - public static BarcodePrefferences getInstance(Context context) { + public static BarcodePreferences getInstance(Context context) { if (instance == null) { - instance = new BarcodePrefferences(context); + instance = new BarcodePreferences(context); } return instance; } diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodeView.kt b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodeView.kt new file mode 100644 index 00000000..2fd7f52d --- /dev/null +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/BarcodeView.kt @@ -0,0 +1,83 @@ +package io.anyline.examples.barcode + +import android.graphics.Color +import android.widget.TextView + +/** + * Keeps a [VisibleBarcode] tied to its [TextView] + * + * Contains + * - [visibleBarcode], as the main data point + * - [textView], so we know what view belongs to this VisibleBarcode + * - [removalCounter], which indicates a view should be removed if it reaches 0. This prevents + * unnecessary removing & adding of the view when it just didn't appear in a result + * - [mockServerCallStatus], to decide how to represent the view + */ +data class BarcodeView( + var visibleBarcode: VisibleBarcode, + val textView: TextView, + var mockServerCallStatus: MockServerCallStatus = MockServerCallStatus.WAITING, + var removalCounter: Int = 5 +) { + /** + * A [ScanResult] is not guaranteed to contain every Barcode currently visible on screen. + * This workaround gives some leeway to decide if it should be decrease the counter or indicate + * that it needs to be removed. + * + * Returns + * - [false], if the [removalCounter] is greater than 0 + * - [true], if the [removalCounter] reaches 0 + */ + fun shouldBeRemovedOrDecreasesCounter(): Boolean = if (removalCounter <= 0) { + true + } else { + removalCounter-- + false + } + + /** + * Return the appropriate color for a MockServerCallStatus + */ + fun getMockServerCallBackgroundColor(): Int { + val color = when (mockServerCallStatus) { + MockServerCallStatus.WAITING -> Color.BLUE + MockServerCallStatus.SUCCESS -> Color.GREEN + MockServerCallStatus.ERROR -> Color.RED + } + return color + } + + companion object { + /** + * Turns a Barcode value into a Human-Readable String for the Murelli Drink. For testing only! + */ + fun getMurelliFlavor(value: String): String { + return when (value) { + "90145322" -> "Orange-Maracuja" + "90145339" -> "Cola-Mix" + "90145346" -> "Raspberry" + "9014500002878" -> "Cola" + "9014500003004" -> "Apple-Pear" + else -> value + } + } + + /** + * Turns a Barcode value int a hex color value. For testing only! + */ + fun getMurelliColor(value: String): String { + return when (value) { + "90145322" -> "#9F5690" + "90145339" -> "#A06E3C" + "90145346" -> "#963246" + "9014500002878" -> "#323232" + "9014500003004" -> "#A0AA6E" + else -> "Unknown" + } + } + } + + enum class MockServerCallStatus { + WAITING, SUCCESS, ERROR + } +} \ No newline at end of file diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeActivity.java b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeActivity.java deleted file mode 100644 index 877c0835..00000000 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeActivity.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Anyline - * ScanBarcodeActivity.java - * - * Copyright (c) 2015 9yards GmbH - * - * Created by martin at 2015-07-03 - */ - -package io.anyline.examples.barcode; - -import android.content.Intent; -import android.os.Bundle; -import android.os.CountDownTimer; -import android.view.Gravity; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.Switch; -import android.widget.TextView; - -import androidx.lifecycle.MutableLiveData; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -import io.anyline.camera.CameraController; -import io.anyline.camera.CameraOpenListener; -import io.anyline.examples.R; -import io.anyline.examples.ScanActivity; -import io.anyline.examples.ScanModuleEnum; -import io.anyline.plugin.barcode.Barcode; -import io.anyline.plugin.barcode.BarcodeFormat; -import io.anyline.plugin.barcode.BarcodeScanPlugin; -import io.anyline.plugin.barcode.BarcodeScanViewPlugin; -import io.anyline.view.CutoutConfig; -import io.anyline.view.FlashView; -import io.anyline.view.ScanView; - -//import io.anyline.examples.baseactivities.BarcodeListView; - -/** - * Example activity for the Anyline-Barcode-Module - */ -public class ScanBarcodeActivity extends ScanActivity implements CameraOpenListener { - - private static final String TAG = ScanBarcodeActivity.class.getSimpleName(); - private ScanView barcodeScanView; - private BarcodePrefferences barcodePrefferences; - private TextView resultText; - private ArrayList preselectedItems; - private ArrayList defaultItems; - private LinearLayout barcodeContiner; - private Switch barcodeSwitch; - private BarcodeScanViewPlugin scanViewPlugin; - private Button scanButton; - MutableLiveData listen = new MutableLiveData<>(); - - BarcodeScanPlugin scanPlugin = null; - private boolean resultScreenShown = false; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getLayoutInflater().inflate(R.layout.activity_anyline_barcode_scan_view, - (ViewGroup) findViewById(R.id.scan_view_placeholder)); - - barcodePrefferences = BarcodePrefferences.getInstance(this); - preselectedItems = barcodePrefferences.getArrayString(); - resultText = (TextView) findViewById(R.id.text_result); - barcodeContiner = findViewById(R.id.barcode_switch_container); - barcodeSwitch = (Switch) findViewById(R.id.barcode_scanner_switch); - barcodeScanView = (ScanView) findViewById(R.id.scan_view); - scanButton = findViewById(R.id.stop_scanning_button); - // add a camera open listener that will be called when the camera is opened or an error occurred - // this is optional (if not set a RuntimeException will be thrown if an error occurs) - barcodeScanView.setCameraOpenListener(this); - // the view can be configured via a json file in the assets, and this config is set here - // (alternatively it can be configured via xml, see the Energy Example for that) - - barcodeScanView.setScanConfig("barcode_view_config.json"); - - scanPlugin = new BarcodeScanPlugin(getApplicationContext(), "barcode"); - scanViewPlugin = new BarcodeScanViewPlugin(getApplicationContext(), scanPlugin, barcodeScanView.getScanViewPluginConfig()); - scanPlugin.setCancelOnResult(false); - if (preselectedItems.size() == 0) { - barcodePrefferences.setDefault(); - preselectedItems = barcodePrefferences.getArrayString(); - } - scanViewPlugin.setMultiBarcode(false); - scanPlugin.enablePDF417Parsing(); - setBarcodeTypes(preselectedItems); - - FlashView flashView = barcodeScanView.getFlashView(); - ((ViewGroup) flashView.getParent()).removeView(flashView); - - //build a linear layout for making it possible to arrange the flash as we want to - LinearLayout mainLayout = (LinearLayout) findViewById(R.id.main_layout_linear); - mainLayout.setVisibility(View.VISIBLE); - //set all parameters for the flashview - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); - params.gravity = Gravity.CENTER_VERTICAL; - params.weight = 1.0f; - params.rightMargin = 100; - params.topMargin = 50; - flashView.setLayoutParams(params); - - //add the flash view to the main layout of the buttons - mainLayout.addView(flashView); - - barcodeScanView.setScanViewPlugin(scanViewPlugin); - - scanViewPlugin.addScannedBarcodesListener(scanResult -> { - listen.postValue(true); - - if (scanViewPlugin != null && scanViewPlugin.isMultiBarcodeEnabled()) { - scanButton.setVisibility(View.VISIBLE); - scanButton.setOnClickListener(view -> { - String path = setupImagePath(scanResult.getCutoutImage()); - barcodeScanView.stop(); - startScanResultIntent(getResources().getString(R.string.category_barcodes), getBarcodeResult(scanResult.getResult()), path); - setupScanProcessView(ScanBarcodeActivity.this, scanResult, getScanModule()); - finish(); - }); - } else { - if (scanResult.getResult().size() != 1) return; - if (!resultScreenShown) { - String path = setupImagePath(scanResult.getCutoutImage()); - barcodeScanView.stop(); - resultScreenShown = true; - startScanResultIntent(getResources().getString(R.string.category_barcodes), getBarcodeResult(scanResult.getResult()), path); - setupScanProcessView(ScanBarcodeActivity.this, scanResult, getScanModule()); - finish(); - } - } - }); - - CountDownTimer countDown = new CountDownTimer(2000, 1000) { - - public void onTick(long millisUntilFinished) { - } - - public void onFinish() { - scanButton.setVisibility(View.INVISIBLE); - } - - }.start(); - - listen.observe(this, changedValue -> { - if (changedValue) { - scanButton.setVisibility(View.VISIBLE); - } else { - countDown.start(); - } - }); - - barcodeSwitch.setOnCheckedChangeListener((compoundButton, isChecked) -> { - barcodeScanView.stop(); - scanViewPlugin.setMultiBarcode(isChecked); - barcodeScanView.start(); - }); - } - - @Override - protected ScanView getScanView() { - return null; - } - - - @Override - protected ScanModuleEnum.ScanModule getScanModule() { - return ScanModuleEnum.ScanModule.BARCODE; - } - - @Override - protected void onResume() { - super.onResume(); - CutoutConfig config = scanViewPlugin.getScanViewPluginConfig().getCutoutConfig(); - - barcodeScanView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - barcodeScanView.getViewTreeObserver().removeOnGlobalLayoutListener(this); - - float ratio = (float) barcodeScanView.getWidth() / barcodeScanView.getHeight(); - - config.setWidth(barcodeScanView.getWidth()); - config.setRatio(ratio); - barcodeScanView.updateCutoutView(); - } - }); - - resultText.setText(""); - barcodeScanView.start(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - // check if the request code is same as what is passed here it is 2 - if (requestCode == 2) { - barcodeScanView.stop(); - preselectedItems = barcodePrefferences.getArrayString(); - - if (preselectedItems.size() > 0 && !preselectedItems.contains("ALL")) { - setBarcodeTypes(preselectedItems); - } - barcodeScanView.start(); - } - } - - private void setBarcodeTypes(ArrayList preselectedItems) { - BarcodeFormat barcodeFormatEAN8 = preselectedItems.contains("UPC/EAN") ? BarcodeFormat.EAN_8 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatEAN13 = preselectedItems.contains("UPC/EAN") ? BarcodeFormat.EAN_13 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatUPCA = preselectedItems.contains("UPC/EAN") ? BarcodeFormat.UPC_A : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatUPCE = preselectedItems.contains("UPC/EAN") ? BarcodeFormat.UPC_E : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatGS1_Databar = preselectedItems.contains("GS1 Databar & Composite Codes") ? BarcodeFormat.RSS_14 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatComposite = preselectedItems.contains("GS1 Databar & Composite Codes") ? BarcodeFormat.RSS_EXPANDED : BarcodeFormat.UNKNOWN; - - BarcodeFormat barcodeFormatCode128 = preselectedItems.contains("Code 128") ? BarcodeFormat.CODE_128 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatGS1_128 = preselectedItems.contains("GS1-128") ? BarcodeFormat.GS1_128 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatISTB_128 = preselectedItems.contains("ISBT 128") ? BarcodeFormat.ISBT_128 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatCode39 = preselectedItems.contains("Code 39") ? BarcodeFormat.CODE_39 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatTRIOPTIC = preselectedItems.contains("Trioptic Code 39") ? BarcodeFormat.TRIOPTIC : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatCode32 = preselectedItems.contains("Code 32") ? BarcodeFormat.CODE_32 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatCode93 = preselectedItems.contains("Code 93") ? BarcodeFormat.CODE_93 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatITF = preselectedItems.contains("Interleaved 2 of 5") ? BarcodeFormat.ITF : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatMatrix = preselectedItems.contains("Matrix 2 of 5") ? BarcodeFormat.MATRIX_2_5 : BarcodeFormat.UNKNOWN; - - BarcodeFormat barcodeFormatDiscrete = preselectedItems.contains("Code 25") ? BarcodeFormat.DISCRETE_2_5 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatCodabar = preselectedItems.contains("Codabar") ? BarcodeFormat.CODABAR : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatMSI = preselectedItems.contains("MSI") ? BarcodeFormat.MSI : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatCode11 = preselectedItems.contains("Code 11") ? BarcodeFormat.CODE_11 : BarcodeFormat.UNKNOWN; - - BarcodeFormat barcodeFormatUSPostnet = preselectedItems.contains("US Postnet") ? BarcodeFormat.US_POSTNET : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatUSPlanet = preselectedItems.contains("US Planet") ? BarcodeFormat.US_PLANET : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatUKPostal = preselectedItems.contains("UK Postal") ? BarcodeFormat.POST_UK : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatUSPS = preselectedItems.contains("USPS 4CB / OneCode / Intelligent Mail") ? BarcodeFormat.USPS_4CB : BarcodeFormat.UNKNOWN; - - BarcodeFormat barcodeFormatPDF = preselectedItems.contains("PDF417") ? BarcodeFormat.PDF_417 : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatMicroPDF417 = preselectedItems.contains("MicroPDF417") ? BarcodeFormat.MICRO_PDF : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatDataMatrix = preselectedItems.contains("Data Matrix") ? BarcodeFormat.DATA_MATRIX : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatQR = preselectedItems.contains("QR Code") ? BarcodeFormat.QR_CODE : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatMicroQR = preselectedItems.contains("MicroQR") ? BarcodeFormat.MICRO_QR : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatGS1 = preselectedItems.contains("GS1 QR Code") ? BarcodeFormat.GS1_QR_CODE : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatAZTEC = preselectedItems.contains("Aztec") ? BarcodeFormat.AZTEC : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatMaxiCode = preselectedItems.contains("MaxiCode") ? BarcodeFormat.MAXICODE : BarcodeFormat.UNKNOWN; - BarcodeFormat barcodeFormatOneDInversed = preselectedItems.contains("One D Inverse") ? BarcodeFormat.ONE_D_INVERSE : BarcodeFormat.UNKNOWN; - - scanPlugin.setBarcodeFormats(barcodeFormatDiscrete, barcodeFormatAZTEC, barcodeFormatPDF, barcodeFormatCodabar, barcodeFormatCode39, barcodeFormatCode93, barcodeFormatCode128, barcodeFormatDataMatrix, barcodeFormatEAN8, barcodeFormatEAN13, barcodeFormatQR, barcodeFormatUPCA, barcodeFormatUPCE, barcodeFormatGS1_128, barcodeFormatISTB_128, barcodeFormatTRIOPTIC, barcodeFormatCode32, barcodeFormatITF, barcodeFormatMatrix, barcodeFormatMSI, barcodeFormatCode11, - barcodeFormatUSPostnet, barcodeFormatUSPlanet, barcodeFormatUKPostal, barcodeFormatUSPS, barcodeFormatMicroPDF417, barcodeFormatMicroQR, barcodeFormatGS1, barcodeFormatGS1_Databar, barcodeFormatComposite, barcodeFormatMaxiCode, - barcodeFormatOneDInversed); - } - - @Override - protected void onPause() { - super.onPause(); - //stop the scanning - barcodeScanView.stop(); - //scan button should not be present when the device is on pause - scanButton.setVisibility(View.INVISIBLE); - - //release the camera (must be called in onPause, because there are situations where - // it cannot be auto-detected that the camera should be released) - barcodeScanView.releaseCameraInBackground(); - } - - @Override - public void onCameraOpened(CameraController cameraController, int width, int height) { - //the camera is opened async and this is called when the opening is finished - } - - @Override - public void onCameraError(Exception e) { - //This is called if the camera could not be opened. - // (e.g. If there is no camera or the permission is denied) - // This is useful to present an alternative way to enter the required data if no camera exists. - throw new RuntimeException(e); - } - - protected HashMap getBarcodeResult(List result) { - LinkedHashMap barcodeResult = new LinkedHashMap<>(); - - for (int i = 0; i < result.size(); i++) { - barcodeResult.put("HEADER" + (i + 1), getString(R.string.category_barcodes) + " " + (i + 1)); - Barcode barcode = result.get(i); - - barcodeResult.put(getString(R.string.barcode_result) + i, (barcode.getValue() == null || barcode.getValue().isEmpty()) ? getResources().getString(R.string.not_available) : barcode.getValue()); - barcodeResult.put(getString(R.string.barcode_result_base64) + i, (barcode.getBase64() == null || barcode.getBase64().isEmpty()) ? getResources().getString(R.string.not_available) : barcode.getBase64()); - barcodeResult.put(getString(R.string.barcode_format) + i, (barcode.getBarcodeFormat() == null) ? getResources().getString(R.string.not_available) : barcode.getBarcodeFormat().toString()); - barcodeResult.put(getString(R.string.barcode_result_pdf417) + i, (barcode.getParsedPDF417() == null || barcode.getParsedPDF417().getBody() == null) ? getResources().getString(R.string.not_available) : result.get(i).getParsedPDF417().getBody()); - } - return barcodeResult; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuItem edit_item = menu.add(0, 0, 0, ""); - edit_item.setIcon(R.drawable.ic_settings); - edit_item.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - - if (id == 0) { - Intent intent = new Intent(ScanBarcodeActivity.this, BarcodeListViewActivity.class); - startActivityForResult(intent, 2);// Activity is started with requestCode 2 - } - return super.onOptionsItemSelected(item); - } -} diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeActivity.kt b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeActivity.kt new file mode 100644 index 00000000..e4987ec6 --- /dev/null +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeActivity.kt @@ -0,0 +1,346 @@ +/* + * Anyline + * ScanBarcodeActivity.java + * + * Copyright (c) 2015 9yards GmbH + * + * Created by martin at 2015-07-03 + */ +package io.anyline.examples.barcode + +import android.content.Intent +import android.os.Bundle +import android.view.* +import android.view.ViewTreeObserver.OnGlobalLayoutListener +import android.widget.Button +import android.widget.CompoundButton +import android.widget.LinearLayout +import android.widget.TextView +import io.anyline.camera.CameraController +import io.anyline.camera.CameraOpenListener +import io.anyline.examples.R +import io.anyline.examples.ScanActivity +import io.anyline.examples.ScanModuleEnum.ScanModule +import io.anyline.examples.databinding.ActivityAnylineBarcodeScanViewBinding +import io.anyline.plugin.barcode.* +import io.anyline.view.ScanView + + +/** + * Example activity for the Anyline-Barcode-Module + */ +class ScanBarcodeActivity : ScanActivity(), CameraOpenListener { + + private lateinit var binding: ActivityAnylineBarcodeScanViewBinding + + private lateinit var scanView: ScanView + private lateinit var scanViewPlugin: BarcodeScanViewPlugin + private lateinit var scanPlugin: BarcodeScanPlugin + + private lateinit var barcodePreferences: BarcodePreferences + private lateinit var resultText: TextView + private lateinit var preselectedItems: ArrayList + private lateinit var scanButton: Button + private var resultScreenShown = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityAnylineBarcodeScanViewBinding.inflate( + layoutInflater, + findViewById(R.id.scan_view_placeholder) as ViewGroup, + true + ) + barcodePreferences = BarcodePreferences.getInstance(this) + preselectedItems = barcodePreferences.arrayString + resultText = binding.textResult + + scanButton = binding.stopScanningButton + + scanView = binding.scanView + // add a camera open listener that will be called when the camera is opened or an error occurred + // this is optional (if not set a RuntimeException will be thrown if an error occurs) + scanView.setCameraOpenListener(this) + // the view can be configured via a json file in the assets, and this config is set here + // (alternatively it can be configured via xml, see the Energy Example for that) + scanView.setScanConfig("barcode_view_config.json") + + scanPlugin = BarcodeScanPlugin(applicationContext, "barcode") + scanPlugin.setCancelOnResult(false) + if (preselectedItems.size == 0) { + barcodePreferences.setDefault() + preselectedItems = barcodePreferences.arrayString + } + scanPlugin.enablePDF417Parsing() + + scanViewPlugin = BarcodeScanViewPlugin( + applicationContext, + scanPlugin, + scanView.scanViewPluginConfig + ) + scanViewPlugin.setMultiBarcode(false) + + setBarcodeTypes(preselectedItems) + val flashView = scanView.flashView + (flashView.parent as ViewGroup).removeView(flashView) + + //build a linear layout for making it possible to arrange the flash as we want to + val mainLayout = binding.mainLayoutLinear + mainLayout.visibility = View.VISIBLE + //set all parameters for the flashview + val params = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT + ) + params.gravity = Gravity.CENTER_VERTICAL + params.weight = 1.0f + params.rightMargin = 100 + params.topMargin = 50 + flashView.layoutParams = params + + //add the flash view to the main layout of the buttons + mainLayout.addView(flashView) + scanView.scanViewPlugin = scanViewPlugin + + scanViewPlugin.addScannedBarcodesListener { scanResult: BarcodeScanResult -> + showScanButton(true) + + if (scanViewPlugin.isMultiBarcodeEnabled) { // Continue scanning + scanButton.visibility = View.VISIBLE + scanButton.setOnClickListener { view: View? -> + val path = setupImagePath(scanResult.cutoutImage) + scanView.stop() + startScanResultIntent( + resources.getString(R.string.category_barcodes), + getBarcodeResult(scanResult.result), + path + ) + setupScanProcessView(this@ScanBarcodeActivity, scanResult, scanModule) + finish() + } + } else { // Stop after getting one result + if (scanResult.result.size != 1) return@addScannedBarcodesListener + if (!resultScreenShown) { + val path = setupImagePath(scanResult.cutoutImage) + scanView.stop() + resultScreenShown = true + startScanResultIntent( + resources.getString(R.string.category_barcodes), + getBarcodeResult(scanResult.result), + path + ) + setupScanProcessView(this@ScanBarcodeActivity, scanResult, scanModule) + finish() + } + } + } + + binding.barcodeScannerSwitch.setOnCheckedChangeListener { compoundButton: CompoundButton?, isChecked: Boolean -> + scanView.stop() + showScanButton(false) + scanViewPlugin.setMultiBarcode(isChecked) + scanView.start() + } + } + + private fun showScanButton(show: Boolean) { + scanButton.visibility = if (show) View.VISIBLE else View.INVISIBLE + } + + override fun onResume() { + super.onResume() + val config = scanViewPlugin.scanViewPluginConfig.cutoutConfig + scanView.viewTreeObserver.addOnGlobalLayoutListener(object : + OnGlobalLayoutListener { + override fun onGlobalLayout() { + scanView.viewTreeObserver.removeOnGlobalLayoutListener(this) + val ratio = scanView.width.toFloat() / scanView.height + config.width = scanView.width + config.ratio = ratio + scanView.updateCutoutView() + } + }) + resultText.text = "" + scanView.start() + } + + override fun onPause() { + super.onPause() + //stop the scanning + scanView.stop() + //scan button should not be present when the device is on pause + scanButton.visibility = View.INVISIBLE + + //release the camera (must be called in onPause, because there are situations where + // it cannot be auto-detected that the camera should be released) + scanView.releaseCameraInBackground() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + // check if the request code is same as what is passed here it is 2 + if (requestCode == 2) { + scanView.stop() + preselectedItems = barcodePreferences.arrayString + if (preselectedItems.size > 0 && !preselectedItems.contains("ALL")) { + setBarcodeTypes(preselectedItems) + } + scanView.start() + } + } + + override fun getScanView(): ScanView? { + return null + } + + override fun getScanModule(): ScanModule { + return ScanModule.BARCODE + } + + override fun onCameraOpened(cameraController: CameraController, width: Int, height: Int) { + //the camera is opened async and this is called when the opening is finished + } + + override fun onCameraError(e: Exception) { + //This is called if the camera could not be opened. + // (e.g. If there is no camera or the permission is denied) + // This is useful to present an alternative way to enter the required data if no camera exists. + throw RuntimeException(e) + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + val edit_item = menu.add(0, 0, 0, "") + edit_item.setIcon(R.drawable.ic_settings) + edit_item.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val id = item.itemId + if (id == 0) { + val intent = Intent(this@ScanBarcodeActivity, BarcodeListViewActivity::class.java) + startActivityForResult(intent, 2) // Activity is started with requestCode 2 + } + return super.onOptionsItemSelected(item) + } + + private fun setBarcodeTypes(preselectedItems: ArrayList) { + val barcodeFormatEAN8 = + if (preselectedItems.contains("UPC/EAN")) BarcodeFormat.EAN_8 else BarcodeFormat.UNKNOWN + val barcodeFormatEAN13 = + if (preselectedItems.contains("UPC/EAN")) BarcodeFormat.EAN_13 else BarcodeFormat.UNKNOWN + val barcodeFormatUPCA = + if (preselectedItems.contains("UPC/EAN")) BarcodeFormat.UPC_A else BarcodeFormat.UNKNOWN + val barcodeFormatUPCE = + if (preselectedItems.contains("UPC/EAN")) BarcodeFormat.UPC_E else BarcodeFormat.UNKNOWN + val barcodeFormatGS1_Databar = + if (preselectedItems.contains("GS1 Databar & Composite Codes")) BarcodeFormat.RSS_14 else BarcodeFormat.UNKNOWN + val barcodeFormatComposite = + if (preselectedItems.contains("GS1 Databar & Composite Codes")) BarcodeFormat.RSS_EXPANDED else BarcodeFormat.UNKNOWN + val barcodeFormatCode128 = + if (preselectedItems.contains("Code 128")) BarcodeFormat.CODE_128 else BarcodeFormat.UNKNOWN + val barcodeFormatGS1_128 = + if (preselectedItems.contains("GS1-128")) BarcodeFormat.GS1_128 else BarcodeFormat.UNKNOWN + val barcodeFormatISTB_128 = + if (preselectedItems.contains("ISBT 128")) BarcodeFormat.ISBT_128 else BarcodeFormat.UNKNOWN + val barcodeFormatCode39 = + if (preselectedItems.contains("Code 39")) BarcodeFormat.CODE_39 else BarcodeFormat.UNKNOWN + val barcodeFormatTRIOPTIC = + if (preselectedItems.contains("Trioptic Code 39")) BarcodeFormat.TRIOPTIC else BarcodeFormat.UNKNOWN + val barcodeFormatCode32 = + if (preselectedItems.contains("Code 32")) BarcodeFormat.CODE_32 else BarcodeFormat.UNKNOWN + val barcodeFormatCode93 = + if (preselectedItems.contains("Code 93")) BarcodeFormat.CODE_93 else BarcodeFormat.UNKNOWN + val barcodeFormatITF = + if (preselectedItems.contains("Interleaved 2 of 5")) BarcodeFormat.ITF else BarcodeFormat.UNKNOWN + val barcodeFormatMatrix = + if (preselectedItems.contains("Matrix 2 of 5")) BarcodeFormat.MATRIX_2_5 else BarcodeFormat.UNKNOWN + val barcodeFormatDiscrete = + if (preselectedItems.contains("Code 25")) BarcodeFormat.DISCRETE_2_5 else BarcodeFormat.UNKNOWN + val barcodeFormatCodabar = + if (preselectedItems.contains("Codabar")) BarcodeFormat.CODABAR else BarcodeFormat.UNKNOWN + val barcodeFormatMSI = + if (preselectedItems.contains("MSI")) BarcodeFormat.MSI else BarcodeFormat.UNKNOWN + val barcodeFormatCode11 = + if (preselectedItems.contains("Code 11")) BarcodeFormat.CODE_11 else BarcodeFormat.UNKNOWN + val barcodeFormatUSPostnet = + if (preselectedItems.contains("US Postnet")) BarcodeFormat.US_POSTNET else BarcodeFormat.UNKNOWN + val barcodeFormatUSPlanet = + if (preselectedItems.contains("US Planet")) BarcodeFormat.US_PLANET else BarcodeFormat.UNKNOWN + val barcodeFormatUKPostal = + if (preselectedItems.contains("UK Postal")) BarcodeFormat.POST_UK else BarcodeFormat.UNKNOWN + val barcodeFormatUSPS = + if (preselectedItems.contains("USPS 4CB / OneCode / Intelligent Mail")) BarcodeFormat.USPS_4CB else BarcodeFormat.UNKNOWN + val barcodeFormatPDF = + if (preselectedItems.contains("PDF417")) BarcodeFormat.PDF_417 else BarcodeFormat.UNKNOWN + val barcodeFormatMicroPDF417 = + if (preselectedItems.contains("MicroPDF417")) BarcodeFormat.MICRO_PDF else BarcodeFormat.UNKNOWN + val barcodeFormatDataMatrix = + if (preselectedItems.contains("Data Matrix")) BarcodeFormat.DATA_MATRIX else BarcodeFormat.UNKNOWN + val barcodeFormatQR = + if (preselectedItems.contains("QR Code")) BarcodeFormat.QR_CODE else BarcodeFormat.UNKNOWN + val barcodeFormatMicroQR = + if (preselectedItems.contains("MicroQR")) BarcodeFormat.MICRO_QR else BarcodeFormat.UNKNOWN + val barcodeFormatGS1 = + if (preselectedItems.contains("GS1 QR Code")) BarcodeFormat.GS1_QR_CODE else BarcodeFormat.UNKNOWN + val barcodeFormatAZTEC = + if (preselectedItems.contains("Aztec")) BarcodeFormat.AZTEC else BarcodeFormat.UNKNOWN + val barcodeFormatMaxiCode = + if (preselectedItems.contains("MaxiCode")) BarcodeFormat.MAXICODE else BarcodeFormat.UNKNOWN + val barcodeFormatOneDInversed = + if (preselectedItems.contains("One D Inverse")) BarcodeFormat.ONE_D_INVERSE else BarcodeFormat.UNKNOWN + scanPlugin.setBarcodeFormats( + barcodeFormatDiscrete, + barcodeFormatAZTEC, + barcodeFormatPDF, + barcodeFormatCodabar, + barcodeFormatCode39, + barcodeFormatCode93, + barcodeFormatCode128, + barcodeFormatDataMatrix, + barcodeFormatEAN8, + barcodeFormatEAN13, + barcodeFormatQR, + barcodeFormatUPCA, + barcodeFormatUPCE, + barcodeFormatGS1_128, + barcodeFormatISTB_128, + barcodeFormatTRIOPTIC, + barcodeFormatCode32, + barcodeFormatITF, + barcodeFormatMatrix, + barcodeFormatMSI, + barcodeFormatCode11, + barcodeFormatUSPostnet, + barcodeFormatUSPlanet, + barcodeFormatUKPostal, + barcodeFormatUSPS, + barcodeFormatMicroPDF417, + barcodeFormatMicroQR, + barcodeFormatGS1, + barcodeFormatGS1_Databar, + barcodeFormatComposite, + barcodeFormatMaxiCode, + barcodeFormatOneDInversed + ) + } + + protected fun getBarcodeResult(result: List): HashMap { + val barcodeResult = LinkedHashMap() + for (i in result.indices) { + barcodeResult["HEADER" + (i + 1)] = + getString(R.string.category_barcodes) + " " + (i + 1) + val barcode = result[i] + barcodeResult[getString(R.string.barcode_result) + i] = + barcode.value.ifEmpty { resources.getString(R.string.not_available) } + barcodeResult[getString(R.string.barcode_result_base64) + i] = + if (barcode.base64 == null || barcode.base64.isEmpty()) resources.getString(R.string.not_available) else barcode.base64 + barcodeResult[getString(R.string.barcode_format) + i] = + barcode.barcodeFormat.toString() + barcodeResult[getString(R.string.barcode_result_pdf417) + i] = + if (barcode.parsedPDF417 == null || barcode.parsedPDF417.body == null) resources.getString( + R.string.not_available + ) else result[i].parsedPDF417.body + } + return barcodeResult + } +} \ No newline at end of file diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeWithOverlaysActivity.kt b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeWithOverlaysActivity.kt new file mode 100644 index 00000000..cbd482af --- /dev/null +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/ScanBarcodeWithOverlaysActivity.kt @@ -0,0 +1,705 @@ +/* + * Anyline + * ScanBarcodeActivity.java + * + * Copyright (c) 2015 9yards GmbH + * + * Created by martin at 2015-07-03 + */ +package io.anyline.examples.barcode + +import android.content.Intent +import android.graphics.* +import android.graphics.drawable.BitmapDrawable +import android.os.Bundle +import android.view.* +import android.view.ViewTreeObserver.OnGlobalLayoutListener +import android.widget.* +import androidx.lifecycle.lifecycleScope +import dagger.hilt.android.AndroidEntryPoint +import io.anyline.camera.CameraController +import io.anyline.camera.CameraOpenListener +import io.anyline.examples.R +import io.anyline.examples.ScanActivity +import io.anyline.examples.ScanModuleEnum.ScanModule +import io.anyline.examples.databinding.ActivityAnylineMultiBarcodeScanViewBinding +import io.anyline.examples.dependencyinjection.IoDispatcher +import io.anyline.plugin.barcode.* +import io.anyline.view.ScanView +import kotlinx.coroutines.* +import timber.log.Timber +import javax.inject.Inject + + +/** + * Shows Multiple Continuous Barcode Scanning with Overlays. Exists as hidden functionality. + * Details in the following Ticket and (especially!) PR: + * Ticket: https://anyline.atlassian.net/browse/SDKY-190 + * PR: https://bitbucket.org/9yardsgmbh/anylineexamples-android/pull-requests/96 + */ +@AndroidEntryPoint +class ScanBarcodeWithOverlaysActivity : ScanActivity(), CameraOpenListener { + + private lateinit var binding: ActivityAnylineMultiBarcodeScanViewBinding + + private lateinit var scanView: ScanView + private lateinit var scanViewPlugin: BarcodeScanViewPlugin + private lateinit var scanPlugin: BarcodeScanPlugin + + private lateinit var barcodePreferences: BarcodePreferences + private lateinit var resultText: TextView + private lateinit var preselectedItems: ArrayList + private lateinit var scanButton: Button + private var resultScreenShown = false + + @IoDispatcher + @Inject + lateinit var ioDispatcher: CoroutineDispatcher + + private val currentlyVisibleBarcodeViewMap = mutableMapOf() + + private var lastResultTimeMillis = 0L + + /** + * + * @param savedInstanceState + */ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityAnylineMultiBarcodeScanViewBinding.inflate( + layoutInflater, + findViewById(R.id.scan_view_placeholder) as ViewGroup, + true + ) + barcodePreferences = BarcodePreferences.getInstance(this) + preselectedItems = barcodePreferences.arrayString + resultText = binding.textResult + + scanButton = binding.stopScanningButton + + scanView = binding.scanView + // add a camera open listener that will be called when the camera is opened or an error occurred + // this is optional (if not set a RuntimeException will be thrown if an error occurs) + scanView.setCameraOpenListener(this) + // the view can be configured via a json file in the assets, and this config is set here + // (alternatively it can be configured via xml, see the Energy Example for that) + scanView.setScanConfig("barcode_view_config.json") + + scanPlugin = BarcodeScanPlugin(applicationContext, "barcode") + scanPlugin.setCancelOnResult(false) + if (preselectedItems.size == 0) { + barcodePreferences.setDefault() + preselectedItems = barcodePreferences.arrayString + } + scanPlugin.enablePDF417Parsing() + + scanViewPlugin = BarcodeScanViewPlugin( + applicationContext, + scanPlugin, + scanView.scanViewPluginConfig + ) + scanViewPlugin.setMultiBarcode(true) // We keep this true for this mode + + setBarcodeTypes(preselectedItems) + val flashView = scanView.flashView + (flashView.parent as ViewGroup).removeView(flashView) + + //build a linear layout for making it possible to arrange the flash as we want to + val mainLayout = binding.mainLayoutLinear + mainLayout.visibility = View.VISIBLE + //set all parameters for the flashview + val params = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT + ) + params.gravity = Gravity.CENTER_VERTICAL + params.weight = 1.0f + params.rightMargin = 100 + params.topMargin = 50 + flashView.layoutParams = params + + //add the flash view to the main layout of the buttons + mainLayout.addView(flashView) + scanView.scanViewPlugin = scanViewPlugin + + /* Launch a coroutine that checks in periodic time intervals if new results came in, + * and if there were no new results for a specified time frame, it clears the overlays. */ + lifecycleScope.launch { + while(true) { + delay(500) + if (System.currentTimeMillis() - lastResultTimeMillis > 1000L) { + if (binding.viewCanvasSwitch.isChecked) { + resetViewOverlay() + } else { + resetCanvasOverlay() + } + } + } + } + + scanViewPlugin.addScannedBarcodesListener { scanResult: BarcodeScanResult -> + lastResultTimeMillis = System.currentTimeMillis() + + lifecycleScope.launch { + handleVisibleBarcodes(scanResult) + } + + showScanButton(true) + if (scanViewPlugin.isMultiBarcodeEnabled) { // Continue scanning + scanButton.visibility = View.VISIBLE + scanButton.setOnClickListener { view: View? -> + val path = setupImagePath(scanResult.cutoutImage) + scanView.stop() + startScanResultIntent( + resources.getString(R.string.category_barcodes), + getBarcodeResult(scanResult.result), + path + ) + setupScanProcessView(this@ScanBarcodeWithOverlaysActivity, scanResult, scanModule) + finish() + } + } else { // Stop after getting one result + if (scanResult.result.size != 1) return@addScannedBarcodesListener + if (!resultScreenShown) { + val path = setupImagePath(scanResult.cutoutImage) + scanView.stop() + resultScreenShown = true + startScanResultIntent( + resources.getString(R.string.category_barcodes), + getBarcodeResult(scanResult.result), + path + ) + setupScanProcessView(this@ScanBarcodeWithOverlaysActivity, scanResult, scanModule) + finish() + } + } + } + + binding.barcodeScannerSwitch.setOnCheckedChangeListener { compoundButton: CompoundButton?, isChecked: Boolean -> + scanView.stop() + showScanButton(false) + scanViewPlugin.setMultiBarcode(isChecked) + scanView.start() + } + } + + private fun showScanButton(show: Boolean) { + scanButton.visibility = if (show) View.VISIBLE else View.INVISIBLE + } + + /** + * Takes in a [BarcodeScanResult] and handles logic that decides what overlays to draw on screen. + * + * Launch with CoroutineScope to allow server call mocking. This changes color of the + * background when Views (as opposed to Canvas) are being used: + * - [MockServerCallStatus.WAITING] -> View background is Blue + * - [MockServerCallStatus.SUCCESS] -> View background is Green + * - [MockServerCallStatus.ERROR] -> View background is Red + */ + private suspend fun handleVisibleBarcodes(scanResult: BarcodeScanResult) { + val scanResultVisibleBarcodes = getVisibleBarcodes(scanResult) + + if (binding.viewCanvasSwitch.isChecked) { + // Draw Barcode Overlays using Views + resetCanvasOverlay() + + /** + * scanResultVisibleBarcodes: all Barcodes found with this scanResult + * currentlyVisibleBarcodeViewMap: (from previous result) newlyVisibleBV + alreadyVisibleBV + * previouslyVisibleBarcodeViewMap: currentlyVisibleBV - scanResultVisibleB + * newlyVisibleBarcodeViewMap: scanResultVisibleB - currentlyVisibleBV + * alreadyVisibleBarcodeViewMap: scanResultVisibleB ∩ currentlyVisibleBV + */ + + val previouslyVisibleBarcodeViewMap = filterToPreviouslyVisibleBarcodeViewMap( + currentlyVisibleBarcodeViewMap, + scanResultVisibleBarcodes + ) + + val newlyVisibleBarcodeViewMap = filterToNewlyVisibleBarcodeViewMap( + scanResultVisibleBarcodes, + currentlyVisibleBarcodeViewMap + ) + + val alreadyVisibleBarcodeViewMap = filterToAlreadyVisibleBarcodeViewMap( + currentlyVisibleBarcodeViewMap, + scanResultVisibleBarcodes + ) + + checkAndRemoveViewsFromBarcodeViewMaps( + previouslyVisibleBarcodeViewMap, + currentlyVisibleBarcodeViewMap + ) + + currentlyVisibleBarcodeViewMap.putAll(newlyVisibleBarcodeViewMap) + currentlyVisibleBarcodeViewMap.putAll(alreadyVisibleBarcodeViewMap) + + // Draw all Barcodes that we want visible at this point + drawBarcodeViewOverlay(currentlyVisibleBarcodeViewMap.values.toList()) + } else { + // Draw Barcode Overlays using a Canvas + resetViewOverlay() + drawCanvasOverlay(scanResultVisibleBarcodes) + } + } + + /** + * Take a Map and return those values from it, that are not present in + * a given List. + * + * previouslyVisibleBarcodeViewMap = currentlyVisibleBarcodeViewMap - scanResultVisibleBarcodes + */ + private fun filterToPreviouslyVisibleBarcodeViewMap( + currentlyVisibleBarcodeViewMap: Map, + scanResultVisibleBarcodes: List + ): MutableMap { + return currentlyVisibleBarcodeViewMap.filterNot { currentlyVisible -> + // Filter all from currentlyVisibleBVM that are NOT in scanResultVisibleBarcodes + scanResultVisibleBarcodes.any { it.value == currentlyVisible.value.visibleBarcode.value } + }.toMutableMap() + } + + /** + * Take a List and from the values that are not present in a given + * Map create a Map. Creates Views for the + * VisibleBarcodes in the process. + * + * newlyVisibleBarcodeViewMap = scanResultVisibleBarcodes - currentlyVisibleBarcodeViewMap + */ + private suspend fun filterToNewlyVisibleBarcodeViewMap( + scanResultVisibleBarcodes: List, + currentlyVisibleBarcodeViewMap: Map + ): Map { + return scanResultVisibleBarcodes.filterNot { visibleBarcode -> + // Filter all from scanResultVisibleBarcodes that are NOT in currentlyVisibleBVM + currentlyVisibleBarcodeViewMap.any { it.key == visibleBarcode.value } + }.map { newBarcode -> + // Create new Views for every VisibleBarcode that's new + val barcodeView = BarcodeView( + newBarcode, + createViewOverlay(newBarcode) + ) + + // Start the mock server call + mockServerCall(barcodeView) + + barcodeView + }.associateBy { barcodeView -> + // Create Map + barcodeView.visibleBarcode.value + } + } + + /** + * Mock a server call. Generate a random Long between 0-mockServerCallPeriodMillis to simulate + * the time (in milliseconds) how long the server call takes. A call under + * mockTimeoutDefinitionMillis is considered successful, anything above is considered a + * Failure/Error. Delays the Coroutine for the random time, then updates the given + * barcodeView.mockServerCallStatus with the result. + */ + private suspend fun mockServerCall( + barcodeView: BarcodeView, + mockServerCallPeriodMillis: Long = 7000, + mockTimeoutDefinitionMillis: Long = 5000 + ) { + CoroutineScope(ioDispatcher).launch { + val delayTimeMillis = (0..mockServerCallPeriodMillis).random().toLong() + delay(delayTimeMillis) + if (delayTimeMillis < mockTimeoutDefinitionMillis) { + barcodeView.mockServerCallStatus = BarcodeView.MockServerCallStatus.SUCCESS + } else { + barcodeView.mockServerCallStatus = BarcodeView.MockServerCallStatus.ERROR + } + } + } + + /** + * Take a Map and return those values from it that are present in a given + * List. Update the VisibleBarcode with the value from the List in the process. + * + * alreadyVisibleBarcodeViewMap = scanResultVisibleB ∩ currentlyVisibleBV + */ + private fun filterToAlreadyVisibleBarcodeViewMap( + currentlyVisibleBarcodeViewMap: Map, + scanResultVisibleBarcodes: List + ): Map { + return currentlyVisibleBarcodeViewMap.filter { currentlyVisibleBarcodeView -> + // Filter all from currentlyVisibleBVM that are in scanResultVisibleBarcodes + scanResultVisibleBarcodes.any { it.value == currentlyVisibleBarcodeView.key } + }.map { oldEntry -> + // Get the matching existing View and update the VisibleBarcode with the new one + oldEntry.value.visibleBarcode = scanResultVisibleBarcodes.find { + it.value == oldEntry.key + } ?: oldEntry.value.visibleBarcode + + oldEntry.value + }.associateBy { barcodeView -> + // Create Map + barcodeView.visibleBarcode.value + } + } + + /** + * Checks if Views need to be removed from previouslyVisibleBarcodeViewMap and + * currentlyVisibleBarcodeViewMap and removes the entries and the View if necessary. + */ + private fun checkAndRemoveViewsFromBarcodeViewMaps( + previouslyVisibleBarcodeViewMap: MutableMap, + currentlyVisibleBarcodeViewMap: MutableMap + ) { + // Check & remove Views from previouslyVisibleBVM & currentlyVisibleBVM + previouslyVisibleBarcodeViewMap.entries.removeIf { entry -> + val remove = entry.value.shouldBeRemovedOrDecreasesCounter() + if (remove) { + // Remove Entry from currentlyVisibleBarcodeViewMap + currentlyVisibleBarcodeViewMap.remove(entry.key) + // Remove ViewOverlay + removeViewOverlay(mutableMapOf(entry.toPair())) + } + // Remove Entry from previouslyVisibleBarcodeViewMap + remove + } + } + + /** + * Build the list of [VisibleBarcode] from a [BarcodeScanResult] + */ + private fun getVisibleBarcodes(scanResult: BarcodeScanResult): List { + val visibleBarcodesList = mutableListOf() + scanResult.result.forEach { barcode -> + val visibleBarcode = VisibleBarcode.fromOriginalBarcode( + barcode, + scanResult + ) + visibleBarcodesList.add(visibleBarcode) + } + return visibleBarcodesList + } + + /** + * Overlays using Views: Remove the given Views from Layout + */ + private fun removeViewOverlay(viewsToRemove: MutableMap) { + viewsToRemove.forEach { + binding.overlayFramelayout.removeView(it.value.textView) + } + } + + /** + * Overlays using Views: Clear everything related to Overlays using Views + */ + private fun resetViewOverlay() { + currentlyVisibleBarcodeViewMap.clear() + binding.overlayFramelayout.removeAllViews() + } + + /** + * Overlays using Views: Create necessary Views for Overlays using Views + */ + private fun createViewOverlay(visibleBarcode: VisibleBarcode): TextView { + val barcodeOverlayView = TextView(this) + binding.overlayFramelayout.addView(barcodeOverlayView) + return barcodeOverlayView + } + + /** + * Overlays using Views: Update Views (Position, etc) when showing Overlays using Views + */ + private fun drawBarcodeViewOverlay(barcodeViewsList: List) { + barcodeViewsList.forEach { barcodeView -> + var normalizedTop: Double = barcodeView.visibleBarcode.normalizedCoordinates[0].y + var normalizedBottom: Double = barcodeView.visibleBarcode.normalizedCoordinates[0].y + var normalizedLeft: Double = barcodeView.visibleBarcode.normalizedCoordinates[0].x + var normalizedRight: Double = barcodeView.visibleBarcode.normalizedCoordinates[0].x + barcodeView.visibleBarcode.normalizedCoordinates.forEach { point -> + normalizedTop = point.y.coerceAtMost(normalizedTop) + normalizedBottom = point.y.coerceAtLeast(normalizedBottom) + normalizedLeft = point.x.coerceAtMost(normalizedLeft) + normalizedRight = point.x.coerceAtLeast(normalizedRight) + } + + val normalizedWidth = normalizedRight - normalizedLeft + val normalizedHeight = normalizedBottom - normalizedTop + + val width = (normalizedWidth * binding.drawOverlayImageview.width).toInt() + val height = (normalizedHeight * binding.drawOverlayImageview.height).toInt() + + val left = (normalizedLeft * binding.drawOverlayImageview.width).toInt() + val top = (normalizedTop * binding.drawOverlayImageview.height).toInt() + + val barcodeOverlayView = barcodeView.textView + + // Color the background with the appropriate color based on the Murelli Flavor (Testing only!) +// val backgroundColor = BarcodeView.getMurelliColor(barcodeView.visibleBarcode.value) +// val colorInt = Color.parseColor(backgroundColor) +// barcodeOverlayView.setBackgroundColor(colorInt) + + // Color the background with the appropriate color based on the mockServerCallStatus + barcodeOverlayView.setBackgroundColor(barcodeView.getMockServerCallBackgroundColor()) + + barcodeOverlayView.text = BarcodeView.getMurelliFlavor(barcodeView.visibleBarcode.value) //barcodeView.visibleBarcode.value + barcodeOverlayView.setTextColor(Color.WHITE) + barcodeOverlayView.layoutParams = FrameLayout.LayoutParams(width, height).apply { + leftMargin = left + topMargin = top + } + } + } + + /** + * Overlays using Canvas: Clear Canvas + */ + private fun resetCanvasOverlay() { + val drawImageView = binding.drawOverlayImageview + val bitmap = Bitmap.createBitmap(drawImageView.width, drawImageView.height, Bitmap.Config.ARGB_8888) + drawImageView.setImageDrawable(BitmapDrawable(resources, bitmap)) + } + + /** + * Overlays using Canvas: Draw Overlays as Paths (Polygons) on Canvas + */ + private fun drawCanvasOverlay(visibleBarcodesList: List) { + val drawImageView = binding.drawOverlayImageview + val bitmap = Bitmap.createBitmap(drawImageView.width, drawImageView.height, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + val bluePaint = Paint().apply { color = Color.BLUE } + val whitePaint = Paint().apply { + color = Color.WHITE + style = Paint.Style.FILL + } + + visibleBarcodesList.forEachIndexed { barcodeIndex, visibleBarcode -> + val scaledCoordinates = visibleBarcode.normalizedCoordinates.map { point -> + io.anyline.opencv.core.Point( + point.x * drawImageView.width, + point.y * drawImageView.height + ) + } + val drawPath = drawPolygon(scaledCoordinates) + canvas.drawPath(drawPath, whitePaint) + } + + // Draw Circles in the Edges (so we can see the Frame Edges on Screen and confirm it's correct)) + val edgeRadius = 50F + canvas.drawCircle(0F, 0F, edgeRadius, bluePaint) + canvas.drawCircle(0F, drawImageView.height.toFloat(), edgeRadius, bluePaint) + canvas.drawCircle(drawImageView.width.toFloat(), 0F, edgeRadius, bluePaint) + canvas.drawCircle(drawImageView.width.toFloat(), drawImageView.height.toFloat(), edgeRadius, bluePaint) + + drawImageView.setImageDrawable(BitmapDrawable(resources, bitmap)) + } + + /** + * Takes a list of [io.anyline.opencv.core.Point] and returns a [Path] based on these Points. + */ + private fun drawPolygon(points: List): Path { + val drawPath = Path() + points.forEachIndexed { pointIndex, point -> + when (pointIndex) { + 0 -> drawPath.moveTo(point.x.toFloat(), point.y.toFloat()) + else -> drawPath.lineTo(point.x.toFloat(), point.y.toFloat()) + } + } + val lastPoint = points[0] + drawPath.lineTo(lastPoint.x.toFloat(), lastPoint.y.toFloat()) + return drawPath + } + + override fun onResume() { + super.onResume() + val config = scanViewPlugin.scanViewPluginConfig.cutoutConfig + scanView.viewTreeObserver.addOnGlobalLayoutListener(object : + OnGlobalLayoutListener { + override fun onGlobalLayout() { + scanView.viewTreeObserver.removeOnGlobalLayoutListener(this) + val ratio = scanView.width.toFloat() / scanView.height + config.width = scanView.width + config.ratio = ratio + scanView.updateCutoutView() + } + }) + resultText.text = "" + scanView.start() + } + + override fun onPause() { + super.onPause() + //stop the scanning + scanView.stop() + //scan button should not be present when the device is on pause + scanButton.visibility = View.INVISIBLE + + //release the camera (must be called in onPause, because there are situations where + // it cannot be auto-detected that the camera should be released) + scanView.releaseCameraInBackground() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + // check if the request code is same as what is passed here it is 2 + if (requestCode == 2) { + scanView.stop() + preselectedItems = barcodePreferences.arrayString + if (preselectedItems.size > 0 && !preselectedItems.contains("ALL")) { + setBarcodeTypes(preselectedItems) + } + scanView.start() + } + } + + override fun getScanView(): ScanView? { + return null + } + + override fun getScanModule(): ScanModule { + return ScanModule.BARCODE + } + + override fun onCameraOpened(cameraController: CameraController, width: Int, height: Int) { + //the camera is opened async and this is called when the opening is finished + } + + override fun onCameraError(e: Exception) { + //This is called if the camera could not be opened. + // (e.g. If there is no camera or the permission is denied) + // This is useful to present an alternative way to enter the required data if no camera exists. + throw RuntimeException(e) + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + val edit_item = menu.add(0, 0, 0, "") + edit_item.setIcon(R.drawable.ic_settings) + edit_item.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val id = item.itemId + if (id == 0) { + val intent = Intent(this@ScanBarcodeWithOverlaysActivity, BarcodeListViewActivity::class.java) + startActivityForResult(intent, 2) // Activity is started with requestCode 2 + } + return super.onOptionsItemSelected(item) + } + + private fun setBarcodeTypes(preselectedItems: ArrayList) { + val barcodeFormatEAN8 = + if (preselectedItems.contains("UPC/EAN")) BarcodeFormat.EAN_8 else BarcodeFormat.UNKNOWN + val barcodeFormatEAN13 = + if (preselectedItems.contains("UPC/EAN")) BarcodeFormat.EAN_13 else BarcodeFormat.UNKNOWN + val barcodeFormatUPCA = + if (preselectedItems.contains("UPC/EAN")) BarcodeFormat.UPC_A else BarcodeFormat.UNKNOWN + val barcodeFormatUPCE = + if (preselectedItems.contains("UPC/EAN")) BarcodeFormat.UPC_E else BarcodeFormat.UNKNOWN + val barcodeFormatGS1_Databar = + if (preselectedItems.contains("GS1 Databar & Composite Codes")) BarcodeFormat.RSS_14 else BarcodeFormat.UNKNOWN + val barcodeFormatComposite = + if (preselectedItems.contains("GS1 Databar & Composite Codes")) BarcodeFormat.RSS_EXPANDED else BarcodeFormat.UNKNOWN + val barcodeFormatCode128 = + if (preselectedItems.contains("Code 128")) BarcodeFormat.CODE_128 else BarcodeFormat.UNKNOWN + val barcodeFormatGS1_128 = + if (preselectedItems.contains("GS1-128")) BarcodeFormat.GS1_128 else BarcodeFormat.UNKNOWN + val barcodeFormatISTB_128 = + if (preselectedItems.contains("ISBT 128")) BarcodeFormat.ISBT_128 else BarcodeFormat.UNKNOWN + val barcodeFormatCode39 = + if (preselectedItems.contains("Code 39")) BarcodeFormat.CODE_39 else BarcodeFormat.UNKNOWN + val barcodeFormatTRIOPTIC = + if (preselectedItems.contains("Trioptic Code 39")) BarcodeFormat.TRIOPTIC else BarcodeFormat.UNKNOWN + val barcodeFormatCode32 = + if (preselectedItems.contains("Code 32")) BarcodeFormat.CODE_32 else BarcodeFormat.UNKNOWN + val barcodeFormatCode93 = + if (preselectedItems.contains("Code 93")) BarcodeFormat.CODE_93 else BarcodeFormat.UNKNOWN + val barcodeFormatITF = + if (preselectedItems.contains("Interleaved 2 of 5")) BarcodeFormat.ITF else BarcodeFormat.UNKNOWN + val barcodeFormatMatrix = + if (preselectedItems.contains("Matrix 2 of 5")) BarcodeFormat.MATRIX_2_5 else BarcodeFormat.UNKNOWN + val barcodeFormatDiscrete = + if (preselectedItems.contains("Code 25")) BarcodeFormat.DISCRETE_2_5 else BarcodeFormat.UNKNOWN + val barcodeFormatCodabar = + if (preselectedItems.contains("Codabar")) BarcodeFormat.CODABAR else BarcodeFormat.UNKNOWN + val barcodeFormatMSI = + if (preselectedItems.contains("MSI")) BarcodeFormat.MSI else BarcodeFormat.UNKNOWN + val barcodeFormatCode11 = + if (preselectedItems.contains("Code 11")) BarcodeFormat.CODE_11 else BarcodeFormat.UNKNOWN + val barcodeFormatUSPostnet = + if (preselectedItems.contains("US Postnet")) BarcodeFormat.US_POSTNET else BarcodeFormat.UNKNOWN + val barcodeFormatUSPlanet = + if (preselectedItems.contains("US Planet")) BarcodeFormat.US_PLANET else BarcodeFormat.UNKNOWN + val barcodeFormatUKPostal = + if (preselectedItems.contains("UK Postal")) BarcodeFormat.POST_UK else BarcodeFormat.UNKNOWN + val barcodeFormatUSPS = + if (preselectedItems.contains("USPS 4CB / OneCode / Intelligent Mail")) BarcodeFormat.USPS_4CB else BarcodeFormat.UNKNOWN + val barcodeFormatPDF = + if (preselectedItems.contains("PDF417")) BarcodeFormat.PDF_417 else BarcodeFormat.UNKNOWN + val barcodeFormatMicroPDF417 = + if (preselectedItems.contains("MicroPDF417")) BarcodeFormat.MICRO_PDF else BarcodeFormat.UNKNOWN + val barcodeFormatDataMatrix = + if (preselectedItems.contains("Data Matrix")) BarcodeFormat.DATA_MATRIX else BarcodeFormat.UNKNOWN + val barcodeFormatQR = + if (preselectedItems.contains("QR Code")) BarcodeFormat.QR_CODE else BarcodeFormat.UNKNOWN + val barcodeFormatMicroQR = + if (preselectedItems.contains("MicroQR")) BarcodeFormat.MICRO_QR else BarcodeFormat.UNKNOWN + val barcodeFormatGS1 = + if (preselectedItems.contains("GS1 QR Code")) BarcodeFormat.GS1_QR_CODE else BarcodeFormat.UNKNOWN + val barcodeFormatAZTEC = + if (preselectedItems.contains("Aztec")) BarcodeFormat.AZTEC else BarcodeFormat.UNKNOWN + val barcodeFormatMaxiCode = + if (preselectedItems.contains("MaxiCode")) BarcodeFormat.MAXICODE else BarcodeFormat.UNKNOWN + val barcodeFormatOneDInversed = + if (preselectedItems.contains("One D Inverse")) BarcodeFormat.ONE_D_INVERSE else BarcodeFormat.UNKNOWN + scanPlugin.setBarcodeFormats( + barcodeFormatDiscrete, + barcodeFormatAZTEC, + barcodeFormatPDF, + barcodeFormatCodabar, + barcodeFormatCode39, + barcodeFormatCode93, + barcodeFormatCode128, + barcodeFormatDataMatrix, + barcodeFormatEAN8, + barcodeFormatEAN13, + barcodeFormatQR, + barcodeFormatUPCA, + barcodeFormatUPCE, + barcodeFormatGS1_128, + barcodeFormatISTB_128, + barcodeFormatTRIOPTIC, + barcodeFormatCode32, + barcodeFormatITF, + barcodeFormatMatrix, + barcodeFormatMSI, + barcodeFormatCode11, + barcodeFormatUSPostnet, + barcodeFormatUSPlanet, + barcodeFormatUKPostal, + barcodeFormatUSPS, + barcodeFormatMicroPDF417, + barcodeFormatMicroQR, + barcodeFormatGS1, + barcodeFormatGS1_Databar, + barcodeFormatComposite, + barcodeFormatMaxiCode, + barcodeFormatOneDInversed + ) + } + + protected fun getBarcodeResult(result: List): HashMap { + val barcodeResult = LinkedHashMap() + for (i in result.indices) { + barcodeResult["HEADER" + (i + 1)] = + getString(R.string.category_barcodes) + " " + (i + 1) + val barcode = result[i] + barcodeResult[getString(R.string.barcode_result) + i] = + barcode.value.ifEmpty { resources.getString(R.string.not_available) } + barcodeResult[getString(R.string.barcode_result_base64) + i] = + if (barcode.base64 == null || barcode.base64.isEmpty()) resources.getString(R.string.not_available) else barcode.base64 + barcodeResult[getString(R.string.barcode_format) + i] = + barcode.barcodeFormat.toString() + barcodeResult[getString(R.string.barcode_result_pdf417) + i] = + if (barcode.parsedPDF417 == null || barcode.parsedPDF417.body == null) resources.getString( + R.string.not_available + ) else result[i].parsedPDF417.body + } + return barcodeResult + } +} \ No newline at end of file diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/VisibleBarcode.kt b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/VisibleBarcode.kt new file mode 100644 index 00000000..694a4b01 --- /dev/null +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/barcode/VisibleBarcode.kt @@ -0,0 +1,53 @@ +package io.anyline.examples.barcode + +import io.anyline.opencv.core.Point +import io.anyline.plugin.barcode.Barcode +import io.anyline.plugin.barcode.BarcodeScanResult + +/** + * Represents one currently visible Barcode on screen. + * + * Contains + * - [value] to identify the Barcode + * - [coordinates], the original barcodes as reported in the BarcodeScanResult: List of 4 Points, + * x & y value ranging 0-imageSize (Integer) + * - [normalizedCoordinates], the coordinates normalized to the image size: List of 4 Points, + * x & y value ranging 0-1 (Double) + * - [imageSize], size of the image: 1 Point, x & y value contain width & height + * - [originalBarcode], the original Barcode this VisibleBarcode has been constructed from + * - [originalScanResult], the original BarcodeScanResult that contains the Barcode + * + * Use [fromOriginalBarcode] to construct [VisibleBarcode] from [Barcode] and [BarcodeScanResult]. + */ +data class VisibleBarcode( + val value: String, + val coordinates: List, + val normalizedCoordinates: List, + val imageSize: Point, + val originalBarcode: Barcode, + val originalScanResult: BarcodeScanResult +) { + companion object { + fun fromOriginalBarcode( + barcode: Barcode, + scanResult: BarcodeScanResult + ): VisibleBarcode { + val coordinates = barcode.coordinates + + val originalWidth: Double = scanResult.cutoutImage?.width?.toDouble() ?: 0.0 + val originalHeight: Double = scanResult.cutoutImage?.height?.toDouble() ?: 0.0 + val normalizedCoordinates = coordinates.map { point -> + Point(point.x / originalWidth, point.y / originalHeight) + } + val imageSize = Point(originalWidth, originalHeight) + return VisibleBarcode( + barcode.value, + coordinates, + normalizedCoordinates, + imageSize, + barcode, + scanResult + ) + } + } +} \ No newline at end of file diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/basefragments/OthersFragment.java b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/basefragments/OthersFragment.java index 27741a46..eb32479b 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/basefragments/OthersFragment.java +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/basefragments/OthersFragment.java @@ -3,7 +3,9 @@ import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; + import androidx.fragment.app.Fragment; + import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -14,10 +16,10 @@ public class OthersFragment extends BaseFragment implements BaseGridListAdapter.OnItemClickListener { - public static final String MRO = "MRO_FRAGMENT"; + public static final String VEHICLE = "VEHICLE_FRAGMENT"; public static final String DOCUMENT_IDENTITY_FRAGMENT = "DOCUMENT_IDENTITY_FRAGMENT"; - private boolean isMRO = false; + private boolean isVehicle = false; private boolean isIdentityDocument = false; private String[] classes; @@ -31,7 +33,7 @@ public OthersFragment() { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { - isMRO = getArguments().getBoolean(MRO); + isVehicle = getArguments().getBoolean(VEHICLE); isIdentityDocument = getArguments().getBoolean(DOCUMENT_IDENTITY_FRAGMENT); } } @@ -40,17 +42,17 @@ public void onCreate(Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Resources res = getContext().getResources(); - if(isIdentityDocument){ + if (isIdentityDocument) { classes = res.getStringArray(R.array.example_identity_documents_classes); names = res.getStringArray(R.array.example_identity_documents_names); - }else if(isMRO){ + } else if (isVehicle) { - classes = res.getStringArray(R.array.example_mro_classes); - names = res.getStringArray(R.array.example_mro_names); + classes = res.getStringArray(R.array.example_vehicle_classes); + names = res.getStringArray(R.array.example_vehicle_names); - }else { + } else { classes = res.getStringArray(R.array.example_others_classes); names = res.getStringArray(R.array.example_others_names); @@ -67,7 +69,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa public void onItemClick(int position) { try { - if(mAdapter.getItemViewType(position) == 1) { + if (mAdapter.getItemViewType(position) == 1) { Fragment fragment = null; switch (mAdapter.getItemName(position)) { diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/basefragments/ProductsFragment.java b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/basefragments/ProductsFragment.java index ab3a5e58..7a6c8645 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/basefragments/ProductsFragment.java +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/basefragments/ProductsFragment.java @@ -58,12 +58,12 @@ public void onItemClick(int position) { replaceFragment(fragment, "OTHERS_FRAGMENT"); break; - case "MRO": + case "Vehicle": fragment = new OthersFragment(); - Bundle mroArgs = new Bundle(); - mroArgs.putBoolean(OthersFragment.MRO, true); - fragment.setArguments(mroArgs); + Bundle vehicleArgs = new Bundle(); + vehicleArgs.putBoolean(OthersFragment.VEHICLE, true); + fragment.setArguments(vehicleArgs); replaceFragment(fragment, "OTHERS_FRAGMENT"); break; diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/dependencyinjection/DispatchersModule.kt b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/dependencyinjection/DispatchersModule.kt new file mode 100644 index 00000000..25e8890b --- /dev/null +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/dependencyinjection/DispatchersModule.kt @@ -0,0 +1,46 @@ +package io.anyline.examples.dependencyinjection + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import javax.inject.Qualifier + +/** + * Define different Dispatchers to be injected using Dagger. + * [@Qualifier] defines the different Dispatchers so Dagger knows which one to use. + * + * We do this, because using Dispatchers (i.e. Dispatchers.IO) should not be hardcoded, so + * they can be injected during Tests. + * + * Reference: https://www.valueof.io/blog/injecting-coroutines-dispatchers-with-dagger + */ +@Module +@InstallIn(SingletonComponent::class) +object DispatchersModule { + @DefaultDispatcher + @Provides + fun providesDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default + + @IoDispatcher + @Provides + fun providesIoDispatcher(): CoroutineDispatcher = Dispatchers.IO + + @MainDispatcher + @Provides + fun providesMainDispatcher(): CoroutineDispatcher = Dispatchers.Main +} + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class DefaultDispatcher + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class IoDispatcher + +@Retention(AnnotationRetention.BINARY) +@Qualifier +annotation class MainDispatcher diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/id/ScanVehicleRegistrationCertificateActivity.java b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/id/ScanVehicleRegistrationCertificateActivity.java new file mode 100644 index 00000000..fab25349 --- /dev/null +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/id/ScanVehicleRegistrationCertificateActivity.java @@ -0,0 +1,115 @@ +package io.anyline.examples.id; + +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.Toast; + +import androidx.appcompat.app.ActionBar; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Set; + +import io.anyline.examples.R; +import io.anyline.examples.ScanActivity; +import io.anyline.examples.ScanModuleEnum; +import io.anyline.plugin.ScanResult; +import io.anyline.plugin.ScanResultListener; +import io.anyline.plugin.ScanRunSkippedListener; +import io.anyline.plugin.ScanRunSkippedReason; +import io.anyline.plugin.id.ID; +import io.anyline.plugin.id.IdScanViewPlugin; +import io.anyline.plugin.id.Identification; +import io.anyline.view.ScanView; + +public class ScanVehicleRegistrationCertificateActivity extends ScanActivity { + + ScanView scanView; + private int orientation; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getLayoutInflater().inflate(R.layout.activity_anyline_scan_view, findViewById(R.id.scan_view_placeholder)); + + orientation = this.getResources().getConfiguration().orientation; + + setUpOrientationButton(); + init(); + + ActionBar actionBar = getSupportActionBar(); + if(actionBar != null){ + actionBar.setTitle("Vehicle Registration Certificate"); + } + } + + private void setUpOrientationButton() { + Button btn = findViewById(R.id.screen_orientation_button); + btn.setVisibility(View.VISIBLE); + + btn.setOnClickListener(v -> { + if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { + orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } else { + orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + }); + } + + void init(){ + scanView = findViewById(R.id.scan_view); + scanView.init("vehicle_registration_certificate_view_config.json"); + IdScanViewPlugin idScanViewPlugin = (IdScanViewPlugin) scanView.getScanViewPlugin(); + + idScanViewPlugin.addScanResultListener((ScanResultListener>) idScanResult -> { + Identification identification = (Identification) idScanResult.getResult(); + HashMap data = (HashMap) identification.getResultData(); + String imagePath = setupImagePath(idScanResult.getCutoutImage()); + Intent intent = new Intent(ScanVehicleRegistrationCertificateActivity.this, ScanUniversalIdResultActivity.class); + + // convert linkedHashmap into two arrays as LinkedHashMap cannot pe passed from one activity to the other: + Set setKeys = data.keySet(); + String[] arrayKeys = setKeys.toArray(new String[setKeys.size()]); + Collection values = data.values(); + String[] arrayValues = values.toArray(new String[values.size()]); + + intent.putExtra("resultDataKeys", arrayKeys); + intent.putExtra("resultDataValues", arrayValues); + +// intent.putExtra("resultData", data); + intent.putExtra("scan_full_picture_path", imagePath); + startActivity(intent); + + setupScanProcessView(ScanVehicleRegistrationCertificateActivity.this, idScanResult, getScanModule()); + + }); + } + + + @Override + protected void onResume() { + super.onResume(); + scanView.start(); + } + + @Override + protected void onStop() { + super.onStop(); + scanView.stop(); + } + + @Override + protected ScanView getScanView() { + return scanView; + } + + @Override + protected ScanModuleEnum.ScanModule getScanModule() { + return ScanModuleEnum.ScanModule.VEHICLE_REGISTRATION_CERTIFICATE; + } +} diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/util/Preferences.java b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/util/Preferences.java index fedd82ac..b5bca5f5 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/util/Preferences.java +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/java/io/anyline/examples/util/Preferences.java @@ -1,5 +1,7 @@ package io.anyline.examples.util; +import static io.anyline.reporter.ReportingService.PREFS_NAME; + import android.content.Context; import android.content.SharedPreferences; @@ -7,8 +9,6 @@ import java.util.Calendar; import java.util.UUID; -import static io.anyline.reporter.ReportingService.PREFS_NAME; - /** * Simple {@link SharedPreferences} manager *

@@ -21,7 +21,6 @@ public class Preferences { private static final String SHARED_PREFS_ANYLINE = "AnylinePreferences"; private static final String PREF_EMAIL = "user_email"; private static final String PREFS_FIRST_START = "first_start"; - private static final String SHARED_PREFS_EMAIL_FACE_AUTHENTICATION = "email_face_authentication_collected"; private static final String PREFS_USER_REGISTERED = "user_registered"; public static final String PREFS_PROJECT_NAME = "projectName"; @@ -126,16 +125,6 @@ public void setUserRegistered(boolean registered) { .apply(); } - public void setEmailForFaceAuthenticationCollected() { - preferences.edit() - .putBoolean(SHARED_PREFS_EMAIL_FACE_AUTHENTICATION, true) - .apply(); - } - - public boolean wasEmailForFaceAuthenticationCollected() { - return preferences.contains(SHARED_PREFS_EMAIL_FACE_AUTHENTICATION); - } - public String getUuid() { String uuidPrefs = reportingPreferences.getString(PREF_UUID, ""); diff --git a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/res/layout/activity_anyline_barcode_scan_view.xml b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/res/layout/activity_anyline_barcode_scan_view.xml index 99cc53f0..c1eeb055 100644 --- a/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/res/layout/activity_anyline_barcode_scan_view.xml +++ b/AnylineSDK-Examples/AnylineSDK-Examples-Source/app/src/main/res/layout/activity_anyline_barcode_scan_view.xml @@ -4,12 +4,9 @@ android:layout_width="match_parent" android:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools" - tools:viewBindingIgnore="true" - tools:context="io.anyline.examples.barcode.ScanBarcodeActivity" android:id="@+id/main_layout"> - + + + + + + + + + + + + + + +