/** * Docutain SDK React Native * Copyright (c) INFOSOFT Informations- und Dokumentationssysteme GmbH. All rights reserved. * * Docutain SDK React Native is a commercial product and requires a license. * Details found in the LICENSE file in the root directory of this source tree. */ package com.docutainsdk import android.app.Activity import android.content.Intent import android.net.Uri import android.util.Log import org.json.JSONObject import org.json.JSONArray import org.json.JSONException import java.io.File import android.util.Base64 import com.facebook.react.bridge.ActivityEventListener import com.facebook.react.bridge.BaseActivityEventListener import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableType import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.WritableNativeMap import de.docutain.sdk.Document import de.docutain.sdk.DocutainSDK import de.docutain.sdk.Logger import de.docutain.sdk.dataextraction.AnalyzeConfiguration import de.docutain.sdk.dataextraction.DocumentDataReader import de.docutain.sdk.ui.DocumentScanner import de.docutain.sdk.ui.BaseScannerConfiguration import de.docutain.sdk.ui.ButtonConfiguration import de.docutain.sdk.ui.ColorConfiguration import de.docutain.sdk.ui.PageEditConfiguration import de.docutain.sdk.ui.TextConfiguration import de.docutain.sdk.ui.DocutainButton import de.docutain.sdk.ui.DocutainColor import de.docutain.sdk.ui.ScanFilter import de.docutain.sdk.ui.Source import de.docutain.sdk.ui.StatusBarAppearance import de.docutain.sdk.ui.NavigationBarAppearance import de.docutain.sdk.ui.Onboarding import de.docutain.sdk.ui.scantips.ScanTips import de.docutain.sdk.ui.ScanHintPopup import de.docutain.sdk.ui.DocutainListItem import de.docutain.sdk.ui.EmptyResultScreen import de.docutain.sdk.ui.DocumentScannerConfiguration import de.docutain.sdk.ui.photopayment.PhotoPaymentResult import de.docutain.sdk.ui.photopayment.PhotoPaymentConfiguration import de.docutain.sdk.ui.photopayment.PaymentAnalyzeConfiguration class DocutainSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { private val logTag = "DocutainSdk" private val SCAN_DOCUMENT_RESULT_CODE = 1 private val START_PHOTOPAYMENT_RESULT_CODE = 2 private val canceledState = "CANCELED" private var callerContext: ReactApplicationContext; private var scanPromise : Promise? = null fun RejectOnError() { // val text = DocutainSDK.getLastError() scanPromise!!.reject(canceledState,"user canceled") } private val mActivityEventListener: ActivityEventListener = object : BaseActivityEventListener() { override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, intent: Intent?) { Log.v(logTag, "onActivityResult" ) if (requestCode == SCAN_DOCUMENT_RESULT_CODE) { if (scanPromise != null) { if(resultCode == Activity.RESULT_OK) { scanPromise!!.resolve(true) } else { RejectOnError() } scanPromise = null Log.v(logTag, if(resultCode == Activity.RESULT_OK) "scannen finished" else "scannen canceled" ) } } if (requestCode == START_PHOTOPAYMENT_RESULT_CODE) { if (scanPromise != null) { if(resultCode == Activity.RESULT_OK) { scanPromise!!.resolve(intent?.getStringExtra("analyzeData")) } else { RejectOnError() } scanPromise = null } } } } init { callerContext = reactContext callerContext.addActivityEventListener(mActivityEventListener) } override fun getName(): String { return NAME } @ReactMethod fun initSDK(licenseKey: String, promise: Promise) { Log.v(logTag, "InitSDK Start") if(!DocutainSDK.initSDK(callerContext.getApplicationContext() as android.app.Application, licenseKey)){ //init of Docutain SDK failed, get the last error message Log.e(logTag,"Initialization of the Docutain SDK failed: ${DocutainSDK.getLastError()}") //your logic to deactivate access to SDK functionality if(licenseKey == "YOUR_LICENSE_KEY_HERE"){ licenseKeyMissing = true } promise.resolve(false); return; } promise.resolve(true); } @ReactMethod fun deleteTempFiles(deleteTraceFileContent: Boolean ,promise: Promise) { Log.v(logTag, "deleteTempFiles") try { val rc = DocutainSDK.deleteTempFiles(deleteTraceFileContent) promise.resolve(rc) } catch(ex:Exception ) { Log.e(logTag, "deleteTempFiles Exception"+ ex) promise.reject(ex); } } @ReactMethod fun getLastError( promise: Promise) { Log.v(logTag, "getLastError") try { val text = DocutainSDK.getLastError() promise.resolve(text) } catch(ex:Exception ) { Log.e(logTag, "getLastError Exception"+ ex); promise.reject(ex); } } @ReactMethod fun setLogLevel(LogLevel: String, promise: Promise) { Log.v(logTag, "setLogLevel:" + LogLevel) try { val logLevel: Logger.Level = getLogLevelFromString(LogLevel); Log.d(logTag, "setLogLevel " + logLevel) Logger.setLogLevel(logLevel); promise.resolve(true) } catch(ex:Exception ) { Log.e(logTag, "setLogLevel Exception"+ ex) promise.reject(ex); } } @ReactMethod fun getTraceFile( promise: Promise) { Log.v(logTag, "getTraceFile") try { val text = Logger.getTraceFile().getPath(); promise.resolve(text) } catch(ex:Exception ) { Log.e(logTag, "getLastError Exception"+ ex) promise.reject(ex); } } @ReactMethod fun setAnalyzeConfiguration(config: ReadableMap, promise: Promise) { Log.v(logTag, "setAnalyzeConfiguration") val analyzeConfig = AnalyzeConfiguration() mapAnalyzeConfiguration(convertMapToJson(config), analyzeConfig); Log.v(logTag, "analyzeConfig.readBIC:" + analyzeConfig.readBIC) if(!DocumentDataReader.setAnalyzeConfiguration(analyzeConfig)){ Log.e(logTag,"Setting AnalyzeConfiguration failed: ${DocutainSDK.getLastError()}") promise.resolve(false); } else { promise.resolve(true); } } @ReactMethod fun scanDocument(options: ReadableMap, promise: Promise) { Log.v(logTag, "scanDocument Start") try { val currentActivity: Activity? = getCurrentActivity() if (currentActivity == null) { promise.resolve(false) return; } scanPromise = promise val nativeScanConfig = DocumentScannerConfiguration() mapDocumentScannerConfiguration(convertMapToJson(options), nativeScanConfig, true); Log.d(logTag, "allowCaptureModeSetting:" + nativeScanConfig.allowCaptureModeSetting) val intent = DocumentScanner.newScanIntent(callerContext.getApplicationContext(), nativeScanConfig) currentActivity.startActivityForResult(intent, SCAN_DOCUMENT_RESULT_CODE) Log.v(logTag, "scanDocument start OK") } catch(ex:Exception ) { Log.e(logTag, "scanDocument Exception"+ ex) promise.reject(ex); } } @ReactMethod fun loadFile(filepath: String, promise: Promise) { Log.v(logTag, "loadFile:" + filepath) try { val fileUri:Uri = Uri.parse(filepath) val rc = DocumentDataReader.loadFile(fileUri) Log.d(logTag, "loadFile rc:" + rc) promise.resolve(rc) } catch(ex:Exception ) { Log.e(logTag, "loadFile Exception"+ ex) promise.reject(ex); } } @ReactMethod fun writePDF(filepath: String, overWrite: Boolean, PageFormat: String, promise: Promise) { Log.v(logTag, "PageFormat:" + PageFormat) try { val PDFFormat: Document.PDFPageFormat = getPDFPageFormatFromString(PageFormat); Log.d(logTag, "PDFFormat:" + PDFFormat) val file = File(filepath); val rc = Document.writePDF(file,overWrite, PDFFormat, 0) promise.resolve(rc?.absolutePath) } catch(ex:Exception ) { Log.e(logTag, "writePDF Exception"+ ex) promise.reject(ex); } } @ReactMethod fun writeImage(pageNumber: Int, filepath: String, promise: Promise) { try { val file = File(filepath); val rc = Document.writeImage(pageNumber, file) promise.resolve(rc?.absolutePath) } catch(ex:Exception ) { Log.e(logTag, "writeImage Exception"+ ex) promise.reject(ex); } } @ReactMethod fun getImageBytes(pageNumber: Int, pageSourceType: String, promise: Promise) { try { val sourceType: Document.PageSourceType = getPageSourceTypeFromString(pageSourceType); val bytes = Document.getImageBytes(pageNumber, sourceType) if(bytes == null){ promise.resolve(null) } else{ promise.resolve(Base64.encodeToString(bytes, Base64.NO_WRAP)) } } catch(ex:Exception ) { Log.e(logTag, "writeImage Exception"+ ex) promise.reject(ex); } } @ReactMethod fun getText(promise: Promise) { try { promise.resolve(DocumentDataReader.getText()) } catch(ex:Exception ) { Log.e(logTag, "getText Exception"+ ex) promise.reject(ex); } } @ReactMethod fun getTextPage(pageNumber: Int, promise: Promise) { try { promise.resolve(DocumentDataReader.getText(pageNumber)) } catch(ex:Exception ) { Log.e(logTag, "getText Exception"+ ex) promise.reject(ex); } } @ReactMethod fun analyze( promise: Promise) { Log.v(logTag, "analyze") try { val text = DocumentDataReader.analyze() Log.d(logTag, "analyze:" + text) promise.resolve(text) } catch(ex:Exception ) { Log.e(logTag, "analyze Exception"+ ex) promise.reject(ex); } } @ReactMethod fun pageCount(promise: Promise) { try { promise.resolve(Document.pageCount()) } catch(ex:Exception ) { Log.e(logTag, "pageCount Exception" + ex) promise.reject(ex); } } @ReactMethod fun startPhotoPayment(options: ReadableMap, promise: Promise) { Log.v(logTag, "startPhotoPayment Start") try { val currentActivity: Activity? = getCurrentActivity() if (currentActivity == null) { promise.resolve(false) return; } scanPromise = promise val nativePhotoPaymentConfig = PhotoPaymentConfiguration() if(!mapPhotoPaymentConfiguration(convertMapToJson(options), nativePhotoPaymentConfig)) { promise.reject("DataNotValid","config data not valid"); } val intent = PhotoPaymentResult().createIntent(callerContext.getApplicationContext(), nativePhotoPaymentConfig) currentActivity.startActivityForResult(intent, START_PHOTOPAYMENT_RESULT_CODE) Log.v(logTag, "startPhotoPayment start OK") } catch(ex:Exception ) { Log.e(logTag, "startPhotoPayment Exception"+ ex) promise.reject(ex); } } @ReactMethod fun resetOnboarding(onboardingReset: Boolean, scanHintPopup: Boolean, promise: Promise) { Log.v(logTag, "resetOboarding: onboardingReset: ${onboardingReset}, scanHintPopup: ${scanHintPopup}") try { val onboarding = Onboarding(); onboarding.reset(onboardingReset, scanHintPopup) promise.resolve(true) } catch(ex:Exception ) { Log.e(logTag, "resetOboarding Exception"+ ex) promise.reject(ex); } } @ReactMethod fun onboardingDefaultItems(promise: Promise) { try { promise.resolve(defaultItemsToReadableArray(Onboarding.defaultItems)) } catch(ex:Exception ) { Log.e(logTag, "onboardingDefaultItems Exception" + ex) promise.reject(ex); } } @ReactMethod fun emptyResultScreenDefaultItems(promise: Promise) { try { promise.resolve(defaultItemsToReadableArray(EmptyResultScreen.defaultItems)) } catch(ex:Exception ) { Log.e(logTag, "emptyResultScreenDefaultItems Exception" + ex) promise.reject(ex); } } @ReactMethod fun scanTipsDefaultItems(promise: Promise) { try { promise.resolve(defaultItemsToReadableArray(ScanTips.defaultItems)) } catch(ex:Exception ) { Log.e(logTag, "scanTipsDefaultItems Exception" + ex) promise.reject(ex); } } fun defaultItemsToReadableArray(defaultItems: List) : ReadableArray { val results = Arguments.createArray() defaultItems.forEach{ var item = WritableNativeMap(); item.putString("image", it.image.toString()); item.putString("title", it.title); item.putString("message", it.message); results.pushMap(item) } return results } companion object { const val NAME = "DocutainSdk" var licenseKeyMissing = false } @Throws(JSONException::class) private fun convertArrayToJson(readableArray: ReadableArray?): JSONArray { val array = JSONArray() if(readableArray == null) return array for (i in 0 until readableArray.size()) { when (readableArray.getType(i)) { ReadableType.Null -> {} ReadableType.Boolean -> array.put(readableArray.getBoolean(i)) ReadableType.Number -> array.put(readableArray.getDouble(i)) ReadableType.String -> array.put(readableArray.getString(i)) ReadableType.Map -> array.put(convertMapToJson(readableArray.getMap(i))) ReadableType.Array -> array.put(convertArrayToJson(readableArray.getArray(i))) } } return array } @Throws(JSONException::class) private fun convertMapToJson(readableMap: ReadableMap?): JSONObject { val `object` = JSONObject() val iterator = readableMap!!.keySetIterator() while (iterator.hasNextKey()) { val key = iterator.nextKey() when (readableMap.getType(key)) { ReadableType.Null -> `object`.put(key, JSONObject.NULL) ReadableType.Boolean -> `object`.put(key, readableMap.getBoolean(key)) ReadableType.Number -> `object`.put(key, readableMap.getDouble(key)) ReadableType.String -> `object`.put(key, readableMap.getString(key)) ReadableType.Map -> `object`.put(key, convertMapToJson(readableMap.getMap(key))) ReadableType.Array -> `object`.put( key, convertArrayToJson(readableMap.getArray(key)!!) ) } } return `object` } private fun getLogLevelFromString(loglevel: String) : Logger.Level { when (loglevel.uppercase()) { "DISABLE" -> return Logger.Level.DISABLE; "ASSERT" -> return Logger.Level.ASSERT; "ERROR" -> return Logger.Level.ERROR; "WARNING" -> return Logger.Level.WARNING; "INFO" -> return Logger.Level.INFO; "DEBUG" -> return Logger.Level.DEBUG; "VERBOSE" -> return Logger.Level.VERBOSE; else -> return Logger.Level.ERROR; } } private fun getScanFilterFromString(scanFilter: String) : ScanFilter { when (scanFilter.uppercase()) { "AUTO" -> return ScanFilter.AUTO; "GRAY" -> return ScanFilter.GRAY; "BLACKWHITE" -> return ScanFilter.BLACKWHITE; "ORIGINAL" -> return ScanFilter.ORIGINAL; "TEXT" -> return ScanFilter.TEXT; "AUTO2" -> return ScanFilter.AUTO2; "ILLUSTRATION" -> return ScanFilter.ILLUSTRATION; else -> return ScanFilter.ILLUSTRATION; } } private fun getScanSourceFromString(scanSource: String) : Source { when (scanSource.uppercase()) { "CAMERA" -> return Source.CAMERA; "IMAGE" -> return Source.IMAGE; "GALLERY" -> return Source.GALLERY; "GALLERY_MULTIPLE" -> return Source.GALLERY_MULTIPLE; "CAMERA_IMPORT" -> return Source.CAMERA_IMPORT; else -> return Source.CAMERA; } } private fun getPDFPageFormatFromString(pageFormat: String) : Document.PDFPageFormat { when (pageFormat.uppercase()) { "FIT_TO_PAGES" -> return Document.PDFPageFormat.FIT_TO_PAGES; "A4" -> return Document.PDFPageFormat.A4; "A4_LANDSCAPE" -> return Document.PDFPageFormat.A4_LANDSCAPE; "A5" -> return Document.PDFPageFormat.A5; "A5_LANDSCAPE" -> return Document.PDFPageFormat.A5_LANDSCAPE; "LETTER" -> return Document.PDFPageFormat.LETTER; "LETTER_LANDSCAPE" -> return Document.PDFPageFormat.LETTER_LANDSCAPE; "LEGAL" -> return Document.PDFPageFormat.LEGAL; "LEGAL_LANDSCAPE" -> return Document.PDFPageFormat.LEGAL_LANDSCAPE; else -> return Document.PDFPageFormat.A4; } } private fun getPageSourceTypeFromString(pageSourceType: String) : Document.PageSourceType { when (pageSourceType.uppercase()) { "ORIGINAL" -> return Document.PageSourceType.ORIGINAL; "CUT_FILTER" -> return Document.PageSourceType.CUT_FILTER; "CUT_ONLY" -> return Document.PageSourceType.CUT_ONLY; else -> return Document.PageSourceType.CUT_FILTER; } } private fun getStatusBarAppearanceFromString(statusBarAppearance: String) : StatusBarAppearance { when (statusBarAppearance.uppercase()) { "LIGHT" -> return StatusBarAppearance.LIGHT; else -> return StatusBarAppearance.DARK; } } private fun getNavigationBarAppearanceFromString(navigationBarAppearance: String) : NavigationBarAppearance { when (navigationBarAppearance.uppercase()) { "LIGHT" -> return NavigationBarAppearance.LIGHT; else -> return NavigationBarAppearance.DARK; } } private fun mapAnalyzeConfiguration(config: JSONObject, analyzeConfig: AnalyzeConfiguration) { if(config.has("readBIC")) analyzeConfig.readBIC = config.getBoolean("readBIC") if(config.has("readPaymentState")) analyzeConfig.readPaymentState = config.getBoolean("readPaymentState") if(config.has("readSEPACreditor")) analyzeConfig.readSEPACreditor = config.getBoolean("readSEPACreditor") } private fun setButtonConfig(docutainButton: DocutainButton, docutainButtonEntry: JSONObject?) { if(docutainButtonEntry!=null) { if (docutainButtonEntry.has("title")) docutainButton.title = docutainButtonEntry.getString("title"); if (docutainButtonEntry.has("icon")){ val imgSource = docutainButtonEntry.getString("icon") val imgIdentifier = DocutainSDK.context.resources.getIdentifier(imgSource, "drawable", DocutainSDK.context.packageName) docutainButton.icon = imgIdentifier } } } private fun setPageEditConfig(pageEditConfig: PageEditConfiguration, optionsPageEditConfig: JSONObject?) { if(optionsPageEditConfig != null){ if (optionsPageEditConfig.has("allowPageFilter")) { pageEditConfig.allowPageFilter = optionsPageEditConfig.getBoolean("allowPageFilter") } if (optionsPageEditConfig.has("allowPageRotation")) { pageEditConfig.allowPageRotation = optionsPageEditConfig.getBoolean("allowPageRotation") } if(optionsPageEditConfig.has("allowPageArrangement")) { pageEditConfig.allowPageArrangement = optionsPageEditConfig.getBoolean("allowPageArrangement") } if(optionsPageEditConfig.has("allowPageCropping")) { pageEditConfig.allowPageCropping = optionsPageEditConfig.getBoolean("allowPageCropping") } if(optionsPageEditConfig.has("allowPageRetake")) { pageEditConfig.allowPageRetake = optionsPageEditConfig.getBoolean("allowPageRetake") } if(optionsPageEditConfig.has("allowPageAdd")) { pageEditConfig.allowPageAdd = optionsPageEditConfig.getBoolean("allowPageAdd") } if(optionsPageEditConfig.has("allowPageDeletion")) { pageEditConfig.allowPageDeletion = optionsPageEditConfig.getBoolean("allowPageDeletion") } if(optionsPageEditConfig.has("pageArrangementShowDeleteButton")) { pageEditConfig.pageArrangementShowDeleteButton = optionsPageEditConfig.getBoolean("pageArrangementShowDeleteButton") } if(optionsPageEditConfig.has("pageArrangementShowPageNumber")) { pageEditConfig.pageArrangementShowPageNumber = optionsPageEditConfig.getBoolean("pageArrangementShowPageNumber") } } } private fun setColorConfig(colorConfig: ColorConfiguration, optionsColorConfig: JSONObject?) { if(optionsColorConfig != null) { val keysIter = optionsColorConfig.keys(); while (keysIter.hasNext()) { val key = keysIter.next() val docutainColorEntry = optionsColorConfig.optJSONObject(key) if(docutainColorEntry != null){ if(docutainColorEntry.has("Light") && docutainColorEntry.has("Dark")) { val docutainColor = DocutainColor(docutainColorEntry.getString("Light"), docutainColorEntry.getString("Dark")) when (key.uppercase()) { "COLORPRIMARY" -> colorConfig.colorPrimary = docutainColor "COLORONPRIMARY" -> colorConfig.colorOnPrimary = docutainColor "COLORSECONDARY" -> colorConfig.colorSecondary = docutainColor "COLORONSECONDARY" -> colorConfig.colorOnSecondary = docutainColor "COLORSCANBUTTONSLAYOUTBACKGROUND" -> colorConfig.colorScanButtonsLayoutBackground = docutainColor "COLORSCANBUTTONSFOREGROUND" -> colorConfig.colorScanButtonsForeground = docutainColor "COLORSCANPOLYGON" -> colorConfig.colorScanPolygon = docutainColor "COLORBOTTOMBARBACKGROUND" -> colorConfig.colorBottomBarBackground = docutainColor "COLORBOTTOMBARFOREGROUND" -> colorConfig.colorBottomBarForeground = docutainColor "COLORTOPBARBACKGROUND" -> colorConfig.colorTopBarBackground = docutainColor "COLORTOPBARFOREGROUND" -> colorConfig.colorTopBarForeground = docutainColor "COLORTOPBARTITLE" -> colorConfig.colorTopBarTitle = docutainColor else -> Log.e("DocutainSdkFull", "mapDocumentScannerConfiguration color not valid "+ key) } } } } } } private fun setTextConfig(textConfig: TextConfiguration, optionsTextConfig: JSONObject?) { if(optionsTextConfig != null){ if (optionsTextConfig.has("textSizeBottomToolbar")) textConfig.textSizeBottomToolbar = optionsTextConfig.getDouble("textSizeBottomToolbar").toFloat() if (optionsTextConfig.has("textSizeTopToolbar")) textConfig.textSizeTopToolbar = optionsTextConfig.getDouble("textSizeTopToolbar").toFloat() if (optionsTextConfig.has("textSizeScanButtons")) textConfig.textSizeScanButtons = optionsTextConfig.getDouble("textSizeScanButtons").toFloat() if (optionsTextConfig.has("textSizeTitle")) textConfig.textSizeTitle = optionsTextConfig.getDouble("textSizeTitle").toFloat() if (optionsTextConfig.has("textTitleScanPage")) textConfig.textTitleScanPage = optionsTextConfig.getString("textTitleScanPage") if (optionsTextConfig.has("textTitleEditPage")) textConfig.textTitleEditPage = optionsTextConfig.getString("textTitleEditPage") if (optionsTextConfig.has("textTitleFilterPage")) textConfig.textTitleFilterPage = optionsTextConfig.getString("textTitleFilterPage") if (optionsTextConfig.has("textTitleCroppingPage")) textConfig.textTitleCroppingPage = optionsTextConfig.getString("textTitleCroppingPage") if (optionsTextConfig.has("textTitleArrangementPage")) textConfig.textTitleArrangementPage = optionsTextConfig.getString("textTitleArrangementPage") if (optionsTextConfig.has("textTitleConfirmationPage")) textConfig.textTitleConfirmationPage = optionsTextConfig.getString("textTitleConfirmationPage") if (optionsTextConfig.has("textDocumentTitle")) textConfig.textDocumentTitle = optionsTextConfig.getString("textDocumentTitle") if (optionsTextConfig.has("textFocusHint")) textConfig.textFocusHint = optionsTextConfig.getString("textFocusHint") if (optionsTextConfig.has("textFirstPageHint")) textConfig.textFirstPageHint = optionsTextConfig.getString("textFirstPageHint") if (optionsTextConfig.has("textLastPageHint")) textConfig.textLastPageHint = optionsTextConfig.getString("textLastPageHint") if (optionsTextConfig.has("textOnePageHint")) textConfig.textOnePageHint = optionsTextConfig.getString("textOnePageHint") if (optionsTextConfig.has("textScanProgress")) textConfig.textScanProgress = optionsTextConfig.getString("textScanProgress") if (optionsTextConfig.has("textDeleteDialogCurrentPage")) textConfig.textDeleteDialogCurrentPage = optionsTextConfig.getString("textDeleteDialogCurrentPage") if (optionsTextConfig.has("textDeleteDialogAllPages")) textConfig.textDeleteDialogAllPages = optionsTextConfig.getString("textDeleteDialogAllPages") if (optionsTextConfig.has("textDeleteDialogCancel")) textConfig.textDeleteDialogCancel = optionsTextConfig.getString("textDeleteDialogCancel") if (optionsTextConfig.has("textTitleScanTipsPage")) textConfig.textTitleScanTipsPage = optionsTextConfig.getString("textTitleScanTipsPage") } } private fun setButtonConfig(buttonConfig: ButtonConfiguration, optionsButtonConfig: JSONObject?) { if (optionsButtonConfig != null) { val keysIter = optionsButtonConfig.keys(); while (keysIter.hasNext()) { val key = keysIter.next() val docutainButtonEntry = optionsButtonConfig.optJSONObject(key) if (docutainButtonEntry != null) { when (key.uppercase()) { "BUTTONEDITROTATE" -> setButtonConfig( buttonConfig.buttonEditRotate, docutainButtonEntry ) "BUTTONEDITCROP" -> setButtonConfig( buttonConfig.buttonEditCrop, docutainButtonEntry ) "BUTTONEDITFILTER" -> setButtonConfig( buttonConfig.buttonEditFilter, docutainButtonEntry ) "BUTTONEDITARRANGE" -> setButtonConfig( buttonConfig.buttonEditArrange, docutainButtonEntry ) "BUTTONEDITRETAKE" -> setButtonConfig( buttonConfig.buttonEditRetake, docutainButtonEntry ) "BUTTONEDITDELETE" -> setButtonConfig( buttonConfig.buttonEditDelete, docutainButtonEntry ) "BUTTONEDITFINISH" -> setButtonConfig( buttonConfig.buttonEditFinish, docutainButtonEntry ) "BUTTONCROPEXPAND" -> setButtonConfig( buttonConfig.buttonCropExpand, docutainButtonEntry ) "BUTTONCROPSNAP" -> setButtonConfig( buttonConfig.buttonCropSnap, docutainButtonEntry ) "BUTTONCROPFINISH" -> setButtonConfig( buttonConfig.buttonCropFinish, docutainButtonEntry ) "BUTTONSCANAUTOCAPTUREON" -> setButtonConfig( buttonConfig.buttonScanAutoCaptureOn, docutainButtonEntry ) "BUTTONSCANAUTOCAPTUREOFF" -> setButtonConfig( buttonConfig.buttonScanAutoCaptureOff, docutainButtonEntry ) "BUTTONSCANTORCH" -> setButtonConfig( buttonConfig.buttonScanTorch, docutainButtonEntry ) "BUTTONSCANCAPTURE" -> setButtonConfig( buttonConfig.buttonScanCapture, docutainButtonEntry ) "BUTTONSCANFINISH" -> setButtonConfig( buttonConfig.buttonScanFinish, docutainButtonEntry ) "BUTTONCONFIRMATIONFINISH" -> setButtonConfig( buttonConfig.buttonConfirmationFinish, docutainButtonEntry ) "BUTTONEDITADDPAGE" -> setButtonConfig( buttonConfig.buttonEditAddPage, docutainButtonEntry ) "BUTTONSCANIMPORT" -> setButtonConfig( buttonConfig.buttonScanImport, docutainButtonEntry ) else -> Log.e( "DocutainSdkFull", "mapDocumentScannerConfiguration button not valid " + key ) } } } } } private fun setOnboardingConfig(scanConfig: BaseScannerConfiguration, optionsOnboarding: JSONObject) { var onboarding: Onboarding? = scanConfig.onboarding if(onboarding == null) { onboarding = Onboarding() scanConfig.onboarding = onboarding } readButtonConfig("buttonNext", onboarding.buttonNext, optionsOnboarding) readButtonConfig("buttonFinish", onboarding.buttonFinish, optionsOnboarding) readButtonConfig("buttonSkip", onboarding.buttonSkip, optionsOnboarding) if (optionsOnboarding.has("buttonBack")) { onboarding.buttonBack = DocutainButton() readButtonConfig("buttonBack", onboarding.buttonBack!!, optionsOnboarding) } if(optionsOnboarding.has("scanHintPopup")) { val optionsScanHintPopup = optionsOnboarding.optJSONObject("scanHintPopup") if(optionsScanHintPopup == null) { onboarding.scanHintPopup = null } else { var scanHintPopup: ScanHintPopup? = onboarding.scanHintPopup if(scanHintPopup == null) { scanHintPopup = ScanHintPopup() onboarding.scanHintPopup = scanHintPopup } if (optionsScanHintPopup.has("title")) scanHintPopup.title = optionsScanHintPopup.optString("title") if (optionsScanHintPopup.has("message")) scanHintPopup.message = optionsScanHintPopup.optString("message") if (optionsScanHintPopup.has("closeButton")) scanHintPopup.closeButton = optionsScanHintPopup.optString("closeButton") val imageSource = getImageSource(optionsScanHintPopup) if(imageSource != null) scanHintPopup.imageSource = imageSource } } val optionsOnboardingItems = optionsOnboarding.optJSONArray("items") if(optionsOnboardingItems != null) { val items = ArrayList() for (i in 0 until optionsOnboardingItems.length()) { val docutainListItemEntry = optionsOnboardingItems.getJSONObject(i) items.add(readDocutainListItemConfig(docutainListItemEntry)) } if(items.isNullOrEmpty()){ onboarding.items = null; } else { onboarding.items = items; } } } private fun setScanTipsConfig(scanConfig: BaseScannerConfiguration, optionsScanTips: JSONObject) { var scanTips: ScanTips? = scanConfig.scanTips if(scanTips == null) { scanTips = ScanTips() scanConfig.scanTips = scanTips } readButtonConfig("toolbarItem", scanTips.toolbarItem, optionsScanTips, true) val optionsScanTipsItems = optionsScanTips.optJSONArray("items") if(optionsScanTipsItems != null) { val items = ArrayList() for (i in 0 until optionsScanTipsItems.length()) { val docutainListItemEntry = optionsScanTipsItems.getJSONObject(i) items.add(readDocutainListItemConfig(docutainListItemEntry)) } if (items.isNullOrEmpty()) { scanTips.items = null; } else { scanTips.items = items; } } } private fun setSourceImagesConfig(scanConfig: BaseScannerConfiguration, sourceImages: JSONArray?) { if(sourceImages != null) { val sourceImageFiles = ArrayList() for (i in 0..sourceImages.length() - 1) { //needs to be an absolut path to the file val filepath = sourceImages.getString(i).replace("file://", "") sourceImageFiles.add(java.io.File(filepath)) } scanConfig.sourceImages = sourceImageFiles } } private fun mapDocumentScannerConfiguration(options: JSONObject, scanConfig: BaseScannerConfiguration, NeedToMigrate: Boolean = false): Boolean { try { setPageEditConfig(scanConfig.pageEditConfig, options.optJSONObject("pageEditConfig")) //switched to lowercase on October 7, 2024, capitalization still included for compatibility reasons //should be removed after 1-2 years and only allow lowercase if(options.has("colorConfig") || options.has("ColorConfig")) { setColorConfig(scanConfig.colorConfig, options.optJSONObject("colorConfig")?:options.optJSONObject("ColorConfig")) } if(options.has("allowCaptureModeSetting")) scanConfig.allowCaptureModeSetting = options.getBoolean("allowCaptureModeSetting") if(options.has("autoCapture")) scanConfig.autoCapture = options.getBoolean("autoCapture") if(options.has("defaultScanFilter")) scanConfig.defaultScanFilter = getScanFilterFromString(options.getString("defaultScanFilter")) if(options.has("source")) scanConfig.source = getScanSourceFromString(options.getString("source")) if(options.has("sourceImages")) setSourceImagesConfig(scanConfig, options.get("sourceImages") as JSONArray?) if(options.has("autoCrop")) scanConfig.autoCrop = options.getBoolean("autoCrop") if(options.has("multiPage")) scanConfig.multiPage = options.getBoolean("multiPage") if(options.has("preCaptureFocus")) scanConfig.preCaptureFocus = options.getBoolean("preCaptureFocus") setTextConfig(scanConfig.textConfig, options.optJSONObject("textConfig")) setButtonConfig(scanConfig.buttonConfig, options.optJSONObject("buttonConfig")) if(options.has("confirmPages")) scanConfig.confirmPages = options.getBoolean("confirmPages") if(options.has("allowPageEditing")) scanConfig.allowPageEditing = options.getBoolean("allowPageEditing") if(options.has("statusBarAppearance")) scanConfig.statusBarAppearance = getStatusBarAppearanceFromString(options.getString("statusBarAppearance")) if(options.has("navigationBarAppearance")) scanConfig.navigationBarAppearance = getNavigationBarAppearanceFromString(options.getString("navigationBarAppearance")) if(options.has("vibrateOnCapture")) scanConfig.vibrateOnCapture = options.getBoolean("vibrateOnCapture") if(options.has("onboarding")) { val value = options.optJSONObject("onboarding") if(value == null) { scanConfig.onboarding = null } else { setOnboardingConfig(scanConfig, options.optJSONObject("onboarding")!!) } } if(options.has("scanTips")) { val value = options.optJSONObject("scanTips") if(value == null) { scanConfig.scanTips = null } else { setScanTipsConfig(scanConfig, options.getJSONObject("scanTips")) } } if(NeedToMigrate && scanConfig.onboarding != null && scanConfig.onboarding!!.scanHintPopup != null) { val scanHintPopup = scanConfig.onboarding!!.scanHintPopup!!; // CheckMigration val optionsOnboarding = options.optJSONObject("onboarding") var optionsScanHintPopup : JSONObject? = null; if(optionsOnboarding != null) optionsScanHintPopup = optionsOnboarding.optJSONObject("scanHintPopup") if (options.has("onboardingImageSource") && (optionsScanHintPopup==null || !optionsScanHintPopup.has("imageSource"))) { val imgSource = options.getString("onboardingImageSource") scanHintPopup.imageSource = DocutainSDK.context.resources.getIdentifier( imgSource, "drawable", DocutainSDK.context.packageName ) } var optionsTextConfig = options.optJSONObject("textConfig") if(optionsTextConfig != null) { if (optionsTextConfig.has("textOnboardingTitle") && (optionsScanHintPopup==null || !optionsScanHintPopup.has("title"))) scanHintPopup.title = optionsTextConfig.getString("textOnboardingTitle") if (optionsTextConfig.has("textOnboardingMessage") && (optionsScanHintPopup==null || !optionsScanHintPopup.has("message"))) scanHintPopup.message = optionsTextConfig.getString("textOnboardingMessage") if (optionsTextConfig.has("textOnboardingCloseButton") && (optionsScanHintPopup==null || !optionsScanHintPopup.has("closeButton"))) scanHintPopup.closeButton = optionsTextConfig.getString("textOnboardingCloseButton") } } } catch(ex:Exception ) { Log.e(logTag, "mapDocumentScannerConfiguration Exception "+ ex) return false } return true } fun defaultItemsToJSONArray(defaultItems: List) : JSONArray { val array = JSONArray() defaultItems.forEach{ val item = JSONObject("{\"image\": "+ it.image+ ";\"title\":\""+ it.title+"\""+ ";\"message\":\""+ it.message+"\""+"}") array.put(item) } return array } private fun getImageSource(entry: JSONObject):Int? { if (entry.has("imageSource")) { val imgSource = entry.getString("imageSource") return DocutainSDK.context.resources.getIdentifier( imgSource, "drawable", DocutainSDK.context.packageName ) } return null } private fun readButtonConfig(key: String, docutainButton: DocutainButton , entry: JSONObject?, toolbarButton: Boolean=false) { if (entry != null) { val docutainButtonEntry = entry.optJSONObject(key) if (docutainButtonEntry != null) { if (docutainButtonEntry.has("title")) { docutainButton.title = docutainButtonEntry.getString("title"); if(toolbarButton) { docutainButton.icon = null; return } } if (docutainButtonEntry.has("icon")) { val imgSource = docutainButtonEntry.getString("icon") val imgIdentifier = DocutainSDK.context.resources.getIdentifier( imgSource, "drawable", DocutainSDK.context.packageName ) docutainButton.icon = imgIdentifier } } } } private fun readDocutainListItemConfig( entry: JSONObject) : DocutainListItem { var imgIdentifier = 0 if(entry.has("image")){ val imgSource = entry.getString("image") imgIdentifier = DocutainSDK.context.resources.getIdentifier( imgSource, "drawable", DocutainSDK.context.packageName ) } return DocutainListItem(imgIdentifier, entry.optString("title",""), entry.optString("message","")) } private fun mapPhotoPaymentConfiguration(data: JSONObject, photoPaymentConfig: PhotoPaymentConfiguration): Boolean { if(!mapDocumentScannerConfiguration(data, photoPaymentConfig)) return false; try { val optionsAnalyzeConfig : JSONObject? = data.optJSONObject("analyzeConfig") if (optionsAnalyzeConfig != null) { if(optionsAnalyzeConfig.has("readBIC")) photoPaymentConfig.analyzeConfig.readBIC = optionsAnalyzeConfig.getBoolean("readBIC") if(optionsAnalyzeConfig.has("readPaymentState")) photoPaymentConfig.analyzeConfig.readPaymentState = optionsAnalyzeConfig.getBoolean("readPaymentState") if(optionsAnalyzeConfig.has("readSEPACreditor")) photoPaymentConfig.analyzeConfig.readSEPACreditor = optionsAnalyzeConfig.getBoolean("readSEPACreditor") } if(data.has("emptyResultScreen")) { val optionsEmptyResultScreen = data.optJSONObject("emptyResultScreen") if(optionsEmptyResultScreen == null) { photoPaymentConfig.emptyResultScreen = null } else { var emptyResultScreen: EmptyResultScreen? = photoPaymentConfig.emptyResultScreen if (emptyResultScreen == null) { emptyResultScreen = EmptyResultScreen() photoPaymentConfig.emptyResultScreen = emptyResultScreen } if (optionsEmptyResultScreen.has("title")) emptyResultScreen.title = optionsEmptyResultScreen.getString("title") readButtonConfig( "repeatButton", emptyResultScreen.repeatButton, optionsEmptyResultScreen ) val optionsEmptyResultScreenItems = optionsEmptyResultScreen.optJSONArray("items") if (optionsEmptyResultScreenItems != null) { val items = ArrayList() for (i in 0 until optionsEmptyResultScreenItems.length()) { val docutainListItemEntry = optionsEmptyResultScreenItems.getJSONObject(i) items.add(readDocutainListItemConfig(docutainListItemEntry)) } if (items.isNullOrEmpty()) { emptyResultScreen.items = null; } else { emptyResultScreen.items = items; } } } } } catch(ex:Exception ) { Log.e(logTag, "mapPhotoPaymentConfiguration Exception "+ ex) return false } return true } }