From 337ac5d9ea3ba732c81caa7a5679f5f513d14a7a Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 29 Apr 2020 22:08:38 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/devkit/extensions/CardConfig.kt | 139 --------------- .../managers/PersonalizationItemsManager.kt | 7 +- .../personalize/converter/DefaultValues.kt | 5 +- .../PersonalizationConfigToCardConfig.kt | 7 +- .../converter/PersonalizationJsonConverter.kt | 167 +++++++++--------- .../personalize/dto/PersonalizationConfig.kt | 6 +- .../personalize/dto/PersonalizationJson.kt | 13 +- .../personalize/ui/PersonalizationFragment.kt | 16 +- .../res/layout/fg_personalization_footer.xml | 16 +- 9 files changed, 131 insertions(+), 245 deletions(-) delete mode 100644 tangem-devkit/src/main/java/com/tangem/devkit/extensions/CardConfig.kt diff --git a/tangem-devkit/src/main/java/com/tangem/devkit/extensions/CardConfig.kt b/tangem-devkit/src/main/java/com/tangem/devkit/extensions/CardConfig.kt deleted file mode 100644 index fb3fefaeed..0000000000 --- a/tangem-devkit/src/main/java/com/tangem/devkit/extensions/CardConfig.kt +++ /dev/null @@ -1,139 +0,0 @@ -package com.tangem.devkit.extensions - -import android.app.Application -import android.content.Context -import com.tangem.commands.* -import com.tangem.commands.personalization.entities.CardConfig -import com.tangem.commands.personalization.entities.NdefRecord -import java.util.* - -fun CardConfig.Companion.create(application: Application): CardConfig { - - val preferences = application.getSharedPreferences("prefs", Context.MODE_PRIVATE) - - val signingMethodMaskBuilder = SigningMethodMaskBuilder() - if (preferences.getBoolean("personalization_SigningMethod_0", false)) { - signingMethodMaskBuilder.add(SigningMethod.SignHash) - } - if (preferences.getBoolean("personalization_SigningMethod_1", false)) { - signingMethodMaskBuilder.add(SigningMethod.SignRaw) - } - if (preferences.getBoolean("personalization_SigningMethod_2", false)) { - signingMethodMaskBuilder.add(SigningMethod.SignHashValidateByIssuer) - } - if (preferences.getBoolean("personalization_SigningMethod_3", false)) { - signingMethodMaskBuilder.add(SigningMethod.SignRawValidateByIssuer) - } - if (preferences.getBoolean("personalization_SigningMethod_4", false)) { - signingMethodMaskBuilder.add(SigningMethod.SignHashValidateByIssuerWriteIssuerData) - } - if (preferences.getBoolean("personalization_SigningMethod_5", false)) { - signingMethodMaskBuilder.add(SigningMethod.SignRawValidateByIssuerWriteIssuerData) - } - if (preferences.getBoolean("personalization_SigningMethod_6", false)) { - signingMethodMaskBuilder.add(SigningMethod.SignHash) - } - val signingMethod = signingMethodMaskBuilder.build() - - val isNote = preferences.getBoolean("personalization_ProductMask_IsNote", true) - val isTag = preferences.getBoolean("personalization_ProductMask_IsTag", false) - val isIdCard = preferences.getBoolean("personalization_ProductMask_IsIDCard", false) - - val productMaskBuilder = ProductMaskBuilder() - if (isNote) productMaskBuilder.add(Product.Note) - if (isTag) productMaskBuilder.add(Product.Tag) - if (isIdCard) productMaskBuilder.add(Product.IdCard) - val productMask = productMaskBuilder.build() - - var tokenSymbol: String? = null - var tokenContractAddress: String? = null - var tokenDecimal: Int? = null - if (preferences.getBoolean("personalization_isToken", false)) { - tokenSymbol = preferences.getString("personalization_token_symbol", "") - tokenContractAddress = preferences.getString("personalization_token_contract_address", "") - tokenDecimal = preferences.getString("personalization_token_decimal", "")!!.toInt() - } - - val cardData = CardData( - blockchainName = preferences.getString("personalization_Blockchain", "BTC"), - batchId = preferences.getString("personalization_card_batch", "FFFF"), - productMask = productMask, - tokenSymbol = tokenSymbol, - tokenContractAddress = tokenContractAddress, - tokenDecimal = tokenDecimal, - issuerName = null, - manufactureDateTime = Calendar.getInstance().time, - manufacturerSignature = null) - - - val ndefAar = preferences.getString("personalization_NDEF_AAR", "Release APP") - val ndefUri = preferences.getString("personalization_NDEF_URI", "https://tangem.com") - - val ndefs = mutableListOf() - if (!ndefUri.isNullOrEmpty()) { - ndefs.add(NdefRecord(NdefRecord.Type.URI, ndefUri)) - } - if (ndefAar != "None") { - val type = NdefRecord.Type.AAR - val value = when (ndefAar) { - "Debug APP" -> { - "com.tangem.wallet.debug" - } - "Release APP" -> { - "com.tangem.wallet" - } - "--- CUSTOM ---" -> { - preferences.getString("personalization_NDEF_CUSTOM_AAR", "com.tangem.wallet")!! - } - else -> "" - } - ndefs.add(NdefRecord(type, value)) - } - - return CardConfig( - cardData = cardData, - curveID = EllipticCurve.byName(preferences.getString("personalization_CurveId", "secp256k1")!!) - ?: EllipticCurve.Secp256k1, - signingMethods = signingMethod, - createWallet = preferences.getBoolean("personalization_CreateWallet", true), - maxSignatures = preferences.getString("personalization_MaxSignatures", "1000")!!.toInt(), - isReusable = preferences.getBoolean("personalization_SettingsMask_IsReusable", true), - protocolAllowUnencrypted = preferences.getBoolean("personalization_SettingsMask_AllowEncryption_None", true), - protocolAllowStaticEncryption = preferences.getBoolean("personalization_SettingsMask_AllowEncryption_Fast", true), - useActivation = preferences.getBoolean("personalization_SettingsMask_NeedActivation", false), - - useOneCommandAtTime = preferences.getBoolean("personalization_SettingsMask_OneApduAtOnce", false), - useCvc = preferences.getBoolean("personalization_SettingsMask_UseCVC", false), - useBlock = preferences.getBoolean("personalization_SettingsMask_UseBlock", false), - allowSwapPin = preferences.getBoolean("personalization_SettingsMask_AllowSwapPIN", true), - allowSwapPin2 = preferences.getBoolean("personalization_SettingsMask_AllowSwapPIN2", true), - useNdef = preferences.getBoolean("personalization_SettingsMask_UseNDEF", true), - useDynamicNdef = preferences.getBoolean("personalization_SettingsMask_UseDynamicNDEF", true), - protectIssuerDataAgainstReplay = preferences.getBoolean("personalization_SettingsMask_ProtectIssuerDataAgainstReplay", true), - forbidDefaultPin = preferences.getBoolean("personalization_SettingsMask_ForbidDefaultPIN", false), - smartSecurityDelay = preferences.getBoolean("personalization_SettingsMask_SmartSecurityDelay", false), - pauseBeforePin2 = preferences.getString("personalization_PauseBeforePIN2", "15")!!.toInt() * 1000, - allowSelectBlockchain = preferences.getBoolean("personalization_SettingsMask_AllowSelectBlockchain", false), - forbidPurgeWallet = preferences.getBoolean("personalization_SettingsMask_ForbidPurgeWallet", false) - ?: false, - disablePrecomputedNdef = preferences.getBoolean("personalization_SettingsMask_DisablePrecomputedNDEF", false) - ?: false, - skipSecurityDelayIfValidatedByIssuer = preferences.getBoolean("personalization_SettingsMask_SkipSecurityDelayIfValidatedByIssuer", true), - skipCheckPIN2andCVCIfValidatedByIssuer = preferences.getBoolean("personalization_SettingsMask_SkipCheckPIN2andCVCIfValidatedByIssuer", true), - - skipSecurityDelayIfValidatedByLinkedTerminal = preferences.getBoolean("personalization_SettingsMask_SkipSecurityDelayIfValidatedByLinkedTerminal", true), - restrictOverwriteIssuerDataEx = preferences.getBoolean("personalization_SettingsMask_RestrictOverwriteIssuerDataEx", true), - - requireTerminalTxSignature = preferences.getBoolean("personalization_SettingsMask_RequireTerminalTxSignature", false), - requireTerminalCertSignature = preferences.getBoolean("personalization_SettingsMask_RequireTerminalCertSignature", false), - checkPin3onCard = preferences.getBoolean("personalization_SettingsMask_CheckPIN3onCard", true), - - cvc = preferences.getString("personalization_cvc", "000") ?: "000", - pin = preferences.getString("personalization_pin", "000000") ?: "000000", - pin2 = preferences.getString("personalization_pin2", "000") ?: "000", - pin3 = preferences.getString("personalization_pin3", "123") ?: "123", - hexCrExKey = preferences.getString("personalization_CrEx_Key", "00112233445566778899AABBCCDDEEFFFFEEDDCCBBAA998877665544332211000000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF"), - - ndefRecords = ndefs - ) -} \ No newline at end of file diff --git a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/domain/paramsManager/managers/PersonalizationItemsManager.kt b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/domain/paramsManager/managers/PersonalizationItemsManager.kt index 8de004804e..90a1ceab7b 100644 --- a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/domain/paramsManager/managers/PersonalizationItemsManager.kt +++ b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/domain/paramsManager/managers/PersonalizationItemsManager.kt @@ -2,7 +2,6 @@ package com.tangem.devkit.ucase.domain.paramsManager.managers import androidx.lifecycle.Lifecycle import androidx.lifecycle.OnLifecycleEvent -import com.google.gson.Gson import com.tangem.TangemSdk import com.tangem.devkit.commons.Store import com.tangem.devkit.ucase.domain.actions.PersonalizeAction @@ -35,20 +34,20 @@ class PersonalizationItemsManager( if (jsonString.isEmpty()) return val jsonDto = try { - Gson().fromJson(jsonString, PersonalizationJson::class.java) + PersonalizationJson.getJsonConverter().fromJson(jsonString, PersonalizationJson::class.java) } catch (ex: Exception) { Log.e(this, "Can't convert imported string to Json object. Error: $ex") return } val config = PersonalizationJsonConverter().aToB(jsonDto) - setItems(converter.convert(config)) + updateByItemList(converter.convert(config)) } fun exportJsonConfig(): String { val config = converter.convert(itemList, PersonalizationConfig.default()) val jsonDto = PersonalizationJsonConverter().bToA(config) - val jsonString = Gson().toJson(jsonDto) + val jsonString = PersonalizationJson.getJsonConverter().toJson(jsonDto) return jsonString } diff --git a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/DefaultValues.kt b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/DefaultValues.kt index bf12a14dd4..7135d43975 100644 --- a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/DefaultValues.kt +++ b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/DefaultValues.kt @@ -5,6 +5,7 @@ import com.tangem.devkit._arch.structure.Id import com.tangem.devkit._arch.structure.abstraction.KeyValue import com.tangem.devkit.ucase.variants.personalize.* import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationConfig +import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationJson import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder /** @@ -92,7 +93,7 @@ internal class Helper { fun listOfBlockchain(): List { return mutableListOf( - KeyValue("--- CUSTOM ---", ""), + KeyValue(PersonalizationJson.CUSTOM, PersonalizationJson.CUSTOM), KeyValue("BTC", "BTC"), KeyValue("BTC/test", "BTC/test"), KeyValue("ETH", "ETH"), @@ -113,7 +114,7 @@ internal class Helper { fun aarList(): List { return mutableListOf( - KeyValue("--- CUSTOM ---", ""), + KeyValue(PersonalizationJson.CUSTOM, PersonalizationJson.CUSTOM), KeyValue("Release APP", "com.tangem.wallet"), KeyValue("Debug APP", "com.tangem.wallet.debug"), KeyValue("None", "") diff --git a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/PersonalizationConfigToCardConfig.kt b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/PersonalizationConfigToCardConfig.kt index f69b90978d..8d7c430b72 100644 --- a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/PersonalizationConfigToCardConfig.kt +++ b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/PersonalizationConfigToCardConfig.kt @@ -7,6 +7,7 @@ import com.tangem.commands.ProductMaskBuilder import com.tangem.commands.personalization.entities.CardConfig import com.tangem.commands.personalization.entities.NdefRecord import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationConfig +import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationJson import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter import java.util.* @@ -29,7 +30,7 @@ class PersonalizationConfigToCardConfig : Converter null - "--- CUSTOM ---" -> NdefRecord(NdefRecord.Type.AAR, from.aarCustom) + PersonalizationJson.CUSTOM -> NdefRecord(NdefRecord.Type.AAR, from.aarCustom) else -> NdefRecord(NdefRecord.Type.AAR, from.aar) }?.let { ndefs.add(it) } diff --git a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/PersonalizationJsonConverter.kt b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/PersonalizationJsonConverter.kt index 1326011b73..dc23f3b81e 100644 --- a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/PersonalizationJsonConverter.kt +++ b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/converter/PersonalizationJsonConverter.kt @@ -5,7 +5,6 @@ import com.tangem.commands.SigningMethod import com.tangem.commands.SigningMethodMask import com.tangem.commands.personalization.entities.NdefRecord import com.tangem.devkit._arch.structure.abstraction.TwoWayConverter -import com.tangem.devkit.ucase.variants.personalize.dto.CardData import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationConfig import com.tangem.devkit.ucase.variants.personalize.dto.PersonalizationJson import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter @@ -21,85 +20,77 @@ class PersonalizationJsonConverter : TwoWayConverter { - override fun convert(from: PersonalizationJson): PersonalizationConfig { + + override fun convert(jsonDto: PersonalizationJson): PersonalizationConfig { val config = PersonalizationConfig.default() config.apply { - // Card number - series = from.series - startNumber = from.startNumber - - // Common - curveID = EllipticCurve.byName(from.curveID)?.curve ?: "" + series = jsonDto.series + startNumber = jsonDto.startNumber + curveID = EllipticCurve.byName(jsonDto.curveID)?.curve ?: "" blockchainCustom = "" - MaxSignatures = from.MaxSignatures - createWallet = from.createWallet != 0L - - // Sign hash external properties -// pinLessFloorLimit = 100000L - hexCrExKey = from.hexCrExKey - requireTerminalTxSignature = from.requireTerminalTxSignature - requireTerminalCertSignature = from.requireTerminalCertSignature - checkPIN3onCard = from.checkPIN3onCard - - // Product mask - cardData = from.cardData - - // Settings mask - isReusable = from.isReusable - useActivation = from.useActivation - forbidPurgeWallet = from.forbidPurgeWallet - allowSelectBlockchain = from.allowSelectBlockchain - useBlock = from.useBlock - useOneCommandAtTime = from.useOneCommandAtTime - useCVC = from.useCVC - allowSwapPIN = from.allowSwapPIN - allowSwapPIN2 = from.allowSwapPIN2 - forbidDefaultPIN = from.forbidDefaultPIN - smartSecurityDelay = from.smartSecurityDelay - protectIssuerDataAgainstReplay = from.protectIssuerDataAgainstReplay - skipSecurityDelayIfValidatedByIssuer = from.skipSecurityDelayIfValidatedByIssuer - skipCheckPIN2andCVCIfValidatedByIssuer = from.skipCheckPIN2andCVCIfValidatedByIssuer - skipSecurityDelayIfValidatedByLinkedTerminal = from.skipSecurityDelayIfValidatedByLinkedTerminal - restrictOverwriteIssuerDataEx = from.restrictOverwriteIssuerDataEx - - // Settings mask - protocol encryption - protocolAllowUnencrypted = from.protocolAllowUnencrypted - protocolAllowStaticEncryption = from.protocolAllowStaticEncryption - - // Settings mask - useNDEF = from.useNDEF - useDynamicNDEF = from.useDynamicNDEF - disablePrecomputedNDEF = from.disablePrecomputedNDEF - - // Pins - PIN = from.PIN - PIN2 = from.PIN2 - PIN3 = from.PIN3 - CVC = from.CVC - pauseBeforePIN2 = from.pauseBeforePIN2 - - count = from.count - issuerName = from.issuerName - issuerData = from.issuerData + MaxSignatures = jsonDto.MaxSignatures + createWallet = jsonDto.createWallet != 0L + hexCrExKey = jsonDto.hexCrExKey + requireTerminalTxSignature = jsonDto.requireTerminalTxSignature + requireTerminalCertSignature = jsonDto.requireTerminalCertSignature + checkPIN3onCard = jsonDto.checkPIN3onCard + isReusable = jsonDto.isReusable + useActivation = jsonDto.useActivation + forbidPurgeWallet = jsonDto.forbidPurgeWallet + allowSelectBlockchain = jsonDto.allowSelectBlockchain + useBlock = jsonDto.useBlock + useOneCommandAtTime = jsonDto.useOneCommandAtTime + useCVC = jsonDto.useCVC + allowSwapPIN = jsonDto.allowSwapPIN + allowSwapPIN2 = jsonDto.allowSwapPIN2 + forbidDefaultPIN = jsonDto.forbidDefaultPIN + smartSecurityDelay = jsonDto.smartSecurityDelay + protectIssuerDataAgainstReplay = jsonDto.protectIssuerDataAgainstReplay + skipSecurityDelayIfValidatedByIssuer = jsonDto.skipSecurityDelayIfValidatedByIssuer + skipCheckPIN2andCVCIfValidatedByIssuer = jsonDto.skipCheckPIN2andCVCIfValidatedByIssuer + skipSecurityDelayIfValidatedByLinkedTerminal = jsonDto.skipSecurityDelayIfValidatedByLinkedTerminal + restrictOverwriteIssuerDataEx = jsonDto.restrictOverwriteIssuerDataEx + protocolAllowUnencrypted = jsonDto.protocolAllowUnencrypted + protocolAllowStaticEncryption = jsonDto.protocolAllowStaticEncryption + useNDEF = jsonDto.useNDEF + useDynamicNDEF = jsonDto.useDynamicNDEF + disablePrecomputedNDEF = jsonDto.disablePrecomputedNDEF + PIN = jsonDto.PIN + PIN2 = jsonDto.PIN2 + PIN3 = jsonDto.PIN3 + CVC = jsonDto.CVC + pauseBeforePIN2 = jsonDto.pauseBeforePIN2 + count = jsonDto.count + issuerName = jsonDto.issuerName + issuerData = jsonDto.issuerData // numberFormat = from.numberFormat +// pinLessFloorLimit = 100000L } - fillToken(config, from.cardData) - fillSigningMethod(config, from.SigningMethod) - fillNdef(config, from.ndef) + fillCardData(jsonDto, config) + fillSigningMethod(jsonDto, config) + fillNdef(jsonDto, config) return config } - private fun fillToken(config: PersonalizationConfig, cardData: CardData) { - config.itsToken = cardData.token_contract_address.isNotEmpty() || cardData.token_symbol.isNotEmpty() - config.cardData.token_contract_address = cardData.token_contract_address - config.cardData.token_symbol = cardData.token_symbol - config.cardData.token_decimal = cardData.token_decimal + private fun fillCardData(jsonDto: PersonalizationJson, config: PersonalizationConfig) { + val jsonCardData = jsonDto.cardData + + // copy whole object and then checking tricky places + config.cardData = jsonCardData + + config.itsToken = jsonCardData.token_contract_address.isNotEmpty() || jsonCardData.token_symbol.isNotEmpty() + + val selectedBlockchain = Helper.listOfBlockchain().firstOrNull { it.value == jsonCardData.blockchain } + if (selectedBlockchain == null) { + config.cardData.blockchain = PersonalizationJson.CUSTOM + config.blockchainCustom = jsonCardData.blockchain + } } - private fun fillSigningMethod(config: PersonalizationConfig, signingMethod: Long) { - val mask = SigningMethodMask(signingMethod.toInt()) + private fun fillSigningMethod(jsonDto: PersonalizationJson, config: PersonalizationConfig) { + val mask = SigningMethodMask(jsonDto.SigningMethod.toInt()) if (mask.contains(SigningMethod.SignHash)) config.SigningMethod0 = true if (mask.contains(SigningMethod.SignRaw)) config.SigningMethod1 = true if (mask.contains(SigningMethod.SignHashValidateByIssuer)) config.SigningMethod2 = true @@ -108,8 +99,8 @@ internal class JsonToConfig : Converter) { - ndef.forEach { record -> + private fun fillNdef(jsonDto: PersonalizationJson, config: PersonalizationConfig) { + jsonDto.ndef.forEach { record -> when (record.type) { NdefRecord.Type.URI -> config.uri = record.value NdefRecord.Type.AAR -> config.aar = record.value @@ -121,6 +112,7 @@ internal class JsonToConfig : Converter { + override fun convert(from: PersonalizationConfig): PersonalizationJson { val jsonDto = PersonalizationJson() jsonDto.apply { @@ -163,27 +155,44 @@ internal class ConfigToJson : Converter() var cardData = CardData() + var releaseVersion = false var numberFormat = "" + + companion object { + const val CUSTOM = "--- CUSTOM ---" + + fun getJsonConverter(): Gson { + val builder = GsonBuilder().setPrettyPrinting() + return builder.create() + } + } } \ No newline at end of file diff --git a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/ui/PersonalizationFragment.kt b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/ui/PersonalizationFragment.kt index 45033f5484..76d0116ae3 100644 --- a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/ui/PersonalizationFragment.kt +++ b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/variants/personalize/ui/PersonalizationFragment.kt @@ -39,7 +39,6 @@ import com.tangem.devkit.ucase.variants.personalize.ui.presets.PersonalizationPr import com.tangem.devkit.ucase.variants.personalize.ui.presets.RvPresetNamesAdapter import com.tangem.devkit.ucase.variants.personalize.ui.widgets.PersonalizationItemBuilder import com.tangem.devkit.ucase.variants.responses.ui.ResponseFragment -import ru.dev.gbixahue.eu4d.lib.android._android.views.afterTextChanged import ru.dev.gbixahue.eu4d.lib.android._android.views.inflate import ru.dev.gbixahue.eu4d.lib.android.global.log.Log import ru.dev.gbixahue.eu4d.lib.android.global.threading.post @@ -131,19 +130,22 @@ class PersonalizationFragment : BaseCardActionFragment(), PersonalizationPresetV } fun initImportExportJson(parent: ViewGroup) { - val tvJsonImport = parent.findViewById(R.id.et_json_import) - tvJsonImport.afterTextChanged { personalizationItemsManager.importJsonConfig(it) } + val tvJsonExport = parent.findViewById(R.id.et_json_export) + val btnExportJson = parent.findViewById