Updated on 2026-08-14
This commit is contained in:
parent
8de6a51871
commit
d382162bef
13 changed files with 136 additions and 99 deletions
|
|
@ -12,6 +12,7 @@ dependencies {
|
|||
implementation 'net.i2p.crypto:eddsa:0.3.0'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
|
||||
testImplementation "com.google.truth:truth:1.0"
|
||||
implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.61"
|
||||
}
|
||||
|
||||
sourceCompatibility = "8"
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ class CardManager(
|
|||
if (error is TaskError) {
|
||||
callback(TaskEvent.Completion(error))
|
||||
} else {
|
||||
callback(TaskEvent.Completion(TaskError.GenericError(error.message)))
|
||||
Log.e(this::class.simpleName!!, error.message ?: "")
|
||||
callback(TaskEvent.Completion(TaskError.UnknownError()))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ interface CardManagerDelegate {
|
|||
/**
|
||||
* It is called when some error occur during NFC session.
|
||||
*/
|
||||
fun onError(error: TaskError? = null)
|
||||
fun onError(error: TaskError)
|
||||
|
||||
/**
|
||||
* It is called when a user is expected to enter pin code.
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class SignCommand(private val hashes: Array<ByteArray>)
|
|||
|
||||
private fun checkForErrors() {
|
||||
if (hashes.isEmpty()) throw TaskError.EmptyHashes()
|
||||
if (hashes.size > 10) throw TaskError.TooMuchHashes()
|
||||
if (hashes.size > 10) throw TaskError.TooMuchHashesInOneTransaction()
|
||||
if (hashes.any { it.size != hashSizes }) throw TaskError.HashSizeMustBeEqual()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.common.tlv
|
||||
|
||||
import com.tangem.Log
|
||||
import com.tangem.commands.*
|
||||
import com.tangem.common.extensions.*
|
||||
import com.tangem.tasks.TaskError
|
||||
|
|
@ -11,7 +12,8 @@ class TlvEncoder {
|
|||
if (value != null) {
|
||||
return Tlv(tag, encodeValue(value, tag))
|
||||
} else {
|
||||
throw TaskError.SerializeCommandError("Encoding error. Value for tag $tag is null")
|
||||
Log.e(this::class.simpleName!!, "Encoding error. Value for tag $tag is null")
|
||||
throw TaskError.SerializeCommandError()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +37,8 @@ class TlvEncoder {
|
|||
}
|
||||
TlvValueType.BoolValue -> {
|
||||
typeCheck<T, Boolean>(tag)
|
||||
throw ConversionException("Usopported operation: Boolean to ByteArray for tag $tag")
|
||||
Log.e(this::class.simpleName!!, "Unsupported operation: Boolean to ByteArray for tag $tag")
|
||||
throw TaskError.ConvertError()
|
||||
}
|
||||
TlvValueType.ByteArray -> {
|
||||
typeCheck<T, ByteArray>(tag)
|
||||
|
|
@ -75,7 +78,10 @@ class TlvEncoder {
|
|||
}
|
||||
|
||||
private inline fun <reified T, reified ExpectedT> typeCheck(tag: TlvTag) {
|
||||
if (T::class != ExpectedT::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
if (T::class != ExpectedT::class){
|
||||
Log.e(this::class.simpleName!!,
|
||||
"Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
throw TaskError.WrongType()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +1,14 @@
|
|||
package com.tangem.common.tlv
|
||||
|
||||
import com.tangem.Log
|
||||
import com.tangem.commands.*
|
||||
import com.tangem.common.extensions.toDate
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.common.extensions.toInt
|
||||
import com.tangem.common.extensions.toUtf8
|
||||
import com.tangem.tasks.TaskError
|
||||
import java.util.*
|
||||
|
||||
|
||||
open class TlvMapperException(message: String?) : Exception(message)
|
||||
|
||||
class MissingTagException(message: String? = null) : TlvMapperException(message)
|
||||
class WrongTypeException(message: String? = null) : TlvMapperException(message)
|
||||
class ConversionException(message: String? = null) : TlvMapperException(message)
|
||||
|
||||
/**
|
||||
* Maps value fields in [Tlv] from raw [ByteArray] to concrete classes
|
||||
* according to their [TlvTag] and corresponding [TlvValueType].
|
||||
|
|
@ -33,7 +28,7 @@ class TlvMapper(val tlvList: List<Tlv>) {
|
|||
inline fun <reified T> mapOptional(tag: TlvTag): T? =
|
||||
try {
|
||||
map<T>(tag)
|
||||
} catch (exception: MissingTagException) {
|
||||
} catch (exception: TaskError.MissingTag) {
|
||||
null
|
||||
}
|
||||
|
||||
|
|
@ -46,85 +41,108 @@ class TlvMapper(val tlvList: List<Tlv>) {
|
|||
*
|
||||
* @return [Tlv] value converted to a nullable type [T].
|
||||
*
|
||||
* @throws [MissingTagException] if no [Tlv] is found by the Tag.
|
||||
* @throws [TaskError.MissingTag] exception if no [Tlv] is found by the Tag.
|
||||
*/
|
||||
inline fun <reified T> map(tag: TlvTag): T {
|
||||
val tlvValue: ByteArray = tlvList.find { it.tag == tag }?.value
|
||||
?: if (tag.valueType() == TlvValueType.BoolValue && T::class == Boolean::class) {
|
||||
return false as T
|
||||
} else {
|
||||
throw MissingTagException("Tag $tag not found")
|
||||
Log.e(this::class.simpleName!!, "Tag $tag not found")
|
||||
throw TaskError.MissingTag()
|
||||
}
|
||||
|
||||
return when (tag.valueType()) {
|
||||
TlvValueType.HexString -> {
|
||||
if (T::class != String::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
typeCheck<T, String>(tag)
|
||||
tlvValue.toHexString() as T
|
||||
}
|
||||
TlvValueType.Utf8String -> {
|
||||
if (T::class != String::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
typeCheck<T, String>(tag)
|
||||
tlvValue.toUtf8() as T
|
||||
}
|
||||
TlvValueType.IntValue -> {
|
||||
if (T::class != Integer::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
typeCheck<T, Int>(tag)
|
||||
try {
|
||||
tlvValue.toInt() as T
|
||||
} catch (exception: IllegalArgumentException) {
|
||||
throw ConversionException(exception.message)
|
||||
Log.e(this::class.simpleName!!, exception.message ?: "")
|
||||
throw TaskError.ConvertError()
|
||||
}
|
||||
}
|
||||
TlvValueType.BoolValue -> {
|
||||
if (T::class != Boolean::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
typeCheck<T, Boolean>(tag)
|
||||
true as T
|
||||
}
|
||||
TlvValueType.ByteArray -> {
|
||||
if (T::class != ByteArray::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
typeCheck<T, ByteArray>(tag)
|
||||
tlvValue as T
|
||||
}
|
||||
TlvValueType.EllipticCurve -> {
|
||||
if (T::class != EllipticCurve::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
EllipticCurve.byName(tlvValue.toUtf8()) as? T
|
||||
?: throw ConversionException("Unknown Elliptic Curve value: ${tlvValue.toUtf8()}")
|
||||
typeCheck<T, EllipticCurve>(tag)
|
||||
try {
|
||||
EllipticCurve.byName(tlvValue.toUtf8()) as T
|
||||
} catch (exception: Exception) {
|
||||
logException(tag, tlvValue.toUtf8(), exception)
|
||||
throw TaskError.ConvertError()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
TlvValueType.DateTime -> {
|
||||
if (T::class != Date::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
typeCheck<T, Date>(tag)
|
||||
try {
|
||||
tlvValue.toDate() as T
|
||||
} catch (exception: Exception) {
|
||||
throw ConversionException("Converting to date with the following exception: " + exception.message)
|
||||
logException(tag, tlvValue.toHexString(), exception)
|
||||
throw TaskError.ConvertError()
|
||||
}
|
||||
}
|
||||
TlvValueType.ProductMask -> {
|
||||
if (T::class != ProductMask::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
ProductMask.byCode(tlvValue.first()) as? T
|
||||
?: throw ConversionException("Unknown Product Mask Code: ${tlvValue.first()}.")
|
||||
typeCheck<T, ProductMask>(tag)
|
||||
try {
|
||||
ProductMask.byCode(tlvValue.first()) as T
|
||||
} catch (exception: Exception) {
|
||||
logException(tag, tlvValue.first().toString(), exception)
|
||||
throw TaskError.ConvertError()
|
||||
}
|
||||
}
|
||||
TlvValueType.SettingsMask -> {
|
||||
if (T::class != SettingsMask::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
typeCheck<T, SettingsMask>(tag)
|
||||
SettingsMask(tlvValue.toInt()) as T
|
||||
}
|
||||
TlvValueType.CardStatus -> {
|
||||
if (T::class != CardStatus::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
CardStatus.byCode(tlvValue.toInt()) as T
|
||||
?: throw ConversionException("Unknown Card Status with code of: ${tlvValue.toInt()}")
|
||||
typeCheck<T, CardStatus>(tag)
|
||||
try {
|
||||
CardStatus.byCode(tlvValue.toInt()) as T
|
||||
} catch (exception: Exception) {
|
||||
logException(tag, tlvValue.toInt().toString(), exception)
|
||||
throw TaskError.ConvertError()
|
||||
}
|
||||
}
|
||||
TlvValueType.SigningMethod -> {
|
||||
if (T::class != SigningMethod::class)
|
||||
throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
SigningMethod(tlvValue.toInt()) as T
|
||||
?: throw ConversionException("Unknown Signing Method with code of: ${tlvValue.toInt()}")
|
||||
typeCheck<T, SigningMethod>(tag)
|
||||
try {
|
||||
SigningMethod(tlvValue.toInt()) as T
|
||||
} catch (exception: Exception) {
|
||||
logException(tag, tlvValue.toInt().toString(), exception)
|
||||
throw TaskError.ConvertError()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun logException(tag: TlvTag, value: String, exception: Exception) {
|
||||
Log.e(this::class.simpleName!!,
|
||||
"Unknown ${tag.name} with value of: value, \n${exception.message}")
|
||||
}
|
||||
|
||||
inline fun <reified T, reified ExpectedT> typeCheck(tag: TlvTag) {
|
||||
if (T::class != ExpectedT::class) {
|
||||
Log.e(this::class.simpleName!!,
|
||||
"Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}")
|
||||
throw TaskError.WrongType()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ internal class ScanTask : Task<ScanEvent>() {
|
|||
if (currentCard != null) callback(TaskEvent.Event(ScanEvent.OnReadEvent(currentCard)))
|
||||
|
||||
if (currentCard == null) {
|
||||
completeNfcSession(true, TaskError.MissingPreflightRead())
|
||||
completeNfcSession(TaskError.MissingPreflightRead())
|
||||
callback(TaskEvent.Completion(TaskError.MissingPreflightRead()))
|
||||
|
||||
} else if (currentCard.cardData?.productMask == ProductMask.Tag) {
|
||||
|
|
@ -47,7 +47,7 @@ internal class ScanTask : Task<ScanEvent>() {
|
|||
callback(TaskEvent.Completion())
|
||||
|
||||
} else if (currentCard.curve == null || currentCard.walletPublicKey == null) {
|
||||
completeNfcSession(true, TaskError.CardError())
|
||||
completeNfcSession(TaskError.CardError())
|
||||
callback(TaskEvent.Completion(TaskError.CardError()))
|
||||
|
||||
} else {
|
||||
|
|
@ -57,8 +57,8 @@ internal class ScanTask : Task<ScanEvent>() {
|
|||
sendCommand(checkWalletCommand, cardEnvironment) { result ->
|
||||
when (result) {
|
||||
is CompletionResult.Failure -> {
|
||||
if (result.error !is TaskError.UserCancelledError) {
|
||||
completeNfcSession(true, result.error)
|
||||
if (result.error !is TaskError.UserCancelled) {
|
||||
completeNfcSession(result.error)
|
||||
}
|
||||
callback(TaskEvent.Completion(result.error))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ class SingleCommandTask<Event : CommandResponse>(
|
|||
callback(TaskEvent.Completion())
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
if (result.error !is TaskError.UserCancelledError) {
|
||||
completeNfcSession(true, result.error)
|
||||
if (result.error !is TaskError.UserCancelled) {
|
||||
completeNfcSession(result.error)
|
||||
}
|
||||
callback(TaskEvent.Completion(result.error))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,33 +16,41 @@ import com.tangem.common.apdu.StatusWord
|
|||
* An error class that represent typical errors that may occur when performing Tangem SDK tasks.
|
||||
* Errors are propagated back to the caller in callbacks.
|
||||
*/
|
||||
sealed class TaskError(description: String? = null) : Exception(description) {
|
||||
class UnknownStatus(sw: Int) : TaskError("Unknown StatusWord: $sw")
|
||||
class MappingError : TaskError()
|
||||
class GenericError(description: String? = null) : TaskError(description)
|
||||
class UserCancelledError() : TaskError()
|
||||
class Busy() : TaskError()
|
||||
class TagLost() : TaskError()
|
||||
sealed class TaskError(val code: Int): Exception() {
|
||||
|
||||
class ErrorProcessingCommand(description: String? = null) : TaskError(description)
|
||||
class InvalidState : TaskError()
|
||||
class InsNotSupported : TaskError()
|
||||
class InvalidParams : TaskError()
|
||||
class NeedEncryption : TaskError()
|
||||
class NeedPause : TaskError()
|
||||
//Errors in serializing APDU
|
||||
class SerializeCommandError: TaskError(1001)
|
||||
class EncodingError: TaskError(1002)
|
||||
class MissingTag: TaskError(1003)
|
||||
class WrongType: TaskError(1004)
|
||||
class ConvertError: TaskError(1005)
|
||||
|
||||
class VefificationFailed : TaskError()
|
||||
class CardError : TaskError()
|
||||
class ReaderError() : TaskError()
|
||||
class SerializeCommandError(description: String? = null) : TaskError(description)
|
||||
//Card errors
|
||||
class UnknownStatus: TaskError(2001)
|
||||
class ErrorProcessingCommand: TaskError(2002)
|
||||
class MissingPreflightRead: TaskError(2003)
|
||||
class InvalidState: TaskError(2004)
|
||||
class InsNotSupported: TaskError(2005)
|
||||
class InvalidParams: TaskError(2006)
|
||||
class NeedEncryption: TaskError(2007)
|
||||
|
||||
class CardIsMissing() : TaskError()
|
||||
class EmptyHashes() : TaskError()
|
||||
class TooMuchHashes() : TaskError()
|
||||
class HashSizeMustBeEqual() : TaskError()
|
||||
//Scan errors
|
||||
class VerificationFailed: TaskError(3000)
|
||||
class CardError: TaskError(3001)
|
||||
class WrongCard: TaskError(3002)
|
||||
class TooMuchHashesInOneTransaction: TaskError(3003)
|
||||
class EmptyHashes: TaskError(3004)
|
||||
class HashSizeMustBeEqual: TaskError(3005)
|
||||
|
||||
class WrongCard() : TaskError()
|
||||
class MissingPreflightRead() : TaskError()
|
||||
class Busy: TaskError(4000)
|
||||
class UserCancelled: TaskError(4001)
|
||||
class UnsupportedDevice: TaskError(4002)
|
||||
|
||||
//NFC error
|
||||
class NfcReaderError: TaskError(5002)
|
||||
class TagLost: TaskError(5003)
|
||||
|
||||
class UnknownError: TaskError(6000)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -100,9 +108,9 @@ abstract class Task<T> {
|
|||
* @param withError True when there is an error
|
||||
* @param taskError The error to be shown by [CardManagerDelegate]
|
||||
*/
|
||||
protected fun completeNfcSession(withError: Boolean = false, taskError: TaskError? = null) {
|
||||
protected fun completeNfcSession(taskError: TaskError? = null) {
|
||||
reader?.closeSession()
|
||||
if (withError) {
|
||||
if (taskError != null) {
|
||||
delegate?.onError(taskError)
|
||||
} else {
|
||||
delegate?.onNfcSessionCompleted()
|
||||
|
|
@ -153,7 +161,10 @@ abstract class Task<T> {
|
|||
}
|
||||
}
|
||||
StatusWord.InvalidParams -> callback(CompletionResult.Failure(TaskError.InvalidParams()))
|
||||
StatusWord.Unknown -> callback(CompletionResult.Failure(TaskError.UnknownStatus(result.data.sw)))
|
||||
StatusWord.Unknown -> {
|
||||
Log.e(this::class.simpleName!!, "Unknown status error: ${result.data.sw}")
|
||||
callback(CompletionResult.Failure(TaskError.UnknownStatus()))
|
||||
}
|
||||
StatusWord.ErrorProcessingCommand -> callback(CompletionResult.Failure(TaskError.ErrorProcessingCommand()))
|
||||
StatusWord.InvalidState -> callback(CompletionResult.Failure(TaskError.InvalidState()))
|
||||
|
||||
|
|
@ -169,10 +180,10 @@ abstract class Task<T> {
|
|||
}
|
||||
}
|
||||
is CompletionResult.Failure ->
|
||||
if (result.error is TaskError.TagLost) {
|
||||
if (result.error == TaskError.TagLost()) {
|
||||
delegate?.onTagLost()
|
||||
} else if (result.error is TaskError.UserCancelledError) {
|
||||
callback(CompletionResult.Failure(TaskError.UserCancelledError()))
|
||||
} else if (result.error is TaskError.UserCancelled) {
|
||||
callback(CompletionResult.Failure(TaskError.UserCancelled()))
|
||||
reader?.closeSession()
|
||||
}
|
||||
}
|
||||
|
|
@ -184,7 +195,7 @@ abstract class Task<T> {
|
|||
sendCommand(ReadCommand(), environment) { readResult ->
|
||||
when (readResult) {
|
||||
is CompletionResult.Failure -> {
|
||||
completeNfcSession(true, readResult.error)
|
||||
completeNfcSession(readResult.error)
|
||||
callback(TaskEvent.Completion(readResult.error))
|
||||
}
|
||||
is CompletionResult.Success -> {
|
||||
|
|
@ -193,7 +204,7 @@ abstract class Task<T> {
|
|||
securityDelayDuration = readResult.data.pauseBeforePin2 ?: 0
|
||||
|
||||
if (environment.cardId != null && environment.cardId != receivedCardId) {
|
||||
completeNfcSession(true, TaskError.WrongCard())
|
||||
completeNfcSession(TaskError.WrongCard())
|
||||
callback(TaskEvent.Completion(TaskError.WrongCard()))
|
||||
return@sendCommand
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.common.tlv
|
|||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.commands.*
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.tasks.TaskError
|
||||
import org.junit.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import java.util.*
|
||||
|
|
@ -34,21 +35,21 @@ class TlvMapperTest {
|
|||
|
||||
@Test
|
||||
fun `map when value is null throws MissingTagException`() {
|
||||
assertThrows<MissingTagException> {
|
||||
assertThrows<TaskError.MissingTag> {
|
||||
tlvMapper.map<String>(TlvTag.TokenSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `map optional to wrong type throws WrongTypeException`() {
|
||||
assertThrows<WrongTypeException> {
|
||||
assertThrows<TaskError.WrongType> {
|
||||
tlvMapper.mapOptional<String?>(TlvTag.CardData)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `map to wrong type throws WrongTypeException`() {
|
||||
assertThrows<WrongTypeException> {
|
||||
assertThrows<TaskError.WrongType> {
|
||||
tlvMapper.map<String>(TlvTag.CardData)
|
||||
}
|
||||
}
|
||||
|
|
@ -125,7 +126,7 @@ class TlvMapperTest {
|
|||
@Test
|
||||
fun `map Enum with unknown code throws ConversionException error`() {
|
||||
val localMapper = TlvMapper(listOf(Tlv(TlvTag.ProductMask, byteArrayOf(5))))
|
||||
assertThrows<ConversionException> {
|
||||
assertThrows<TaskError.ConvertError> {
|
||||
localMapper.map<ProductMask>(TlvTag.ProductMask)
|
||||
}
|
||||
}
|
||||
|
|
@ -162,7 +163,7 @@ class TlvMapperTest {
|
|||
@Test
|
||||
fun `map Int with wrong value throws ConversionException`() {
|
||||
val localMapper = TlvMapper(listOf(Tlv(TlvTag.SignedHashes, byteArrayOf(1, 2, 3, 4, 5))))
|
||||
assertThrows<ConversionException> {
|
||||
assertThrows<TaskError.ConvertError> {
|
||||
localMapper.map<Int>(TlvTag.SignedHashes)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
is TaskEvent.Completion -> {
|
||||
if (taskEvent.error != null) {
|
||||
if (taskEvent.error is TaskError.UserCancelledError) {
|
||||
if (taskEvent.error is TaskError.UserCancelled) {
|
||||
// Handle case when user cancelled manually
|
||||
}
|
||||
// Handle other errors
|
||||
|
|
|
|||
|
|
@ -114,14 +114,14 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel
|
|||
postUI(300) { readingDialog?.dismiss() }
|
||||
}
|
||||
|
||||
override fun onError(error: TaskError?) {
|
||||
override fun onError(error: TaskError) {
|
||||
postUI {
|
||||
readingDialog?.lTouchCard?.hide()
|
||||
readingDialog?.flSecurityDelay?.hide()
|
||||
readingDialog?.flCompletion?.hide()
|
||||
readingDialog?.flError?.show()
|
||||
readingDialog?.tvTaskTitle?.text = activity.getText(R.string.dialog_error)
|
||||
readingDialog?.tvTaskText?.text = if (error != null) error::class.simpleName else ""
|
||||
readingDialog?.tvTaskText?.text = "${error::class.simpleName}: ${error.code}"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class NfcReader : CardReader {
|
|||
// Stops reading and sends failure callback to a task
|
||||
// if reading is cancelled (when user closes nfc bottom sheet dialog).
|
||||
closeSession()
|
||||
callback?.invoke(CompletionResult.Failure(TaskError.UserCancelledError()))
|
||||
callback?.invoke(CompletionResult.Failure(TaskError.UserCancelled()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ class NfcReader : CardReader {
|
|||
|
||||
private fun transceiveData() {
|
||||
if (readingCancelled) {
|
||||
callback?.invoke(CompletionResult.Failure(TaskError.UserCancelledError()))
|
||||
callback?.invoke(CompletionResult.Failure(TaskError.UserCancelled()))
|
||||
return
|
||||
}
|
||||
if (data == null) return
|
||||
|
|
@ -109,9 +109,8 @@ class NfcReader : CardReader {
|
|||
val response = SlixTagReader().transceive(nfcV)
|
||||
when (response) {
|
||||
is SlixReadResult.Failure -> {
|
||||
callback?.invoke(CompletionResult.Failure(
|
||||
TaskError.ErrorProcessingCommand(response.exception.message))
|
||||
)
|
||||
Log.e(this::class.simpleName!!, "${response.exception.message}")
|
||||
callback?.invoke(CompletionResult.Failure(TaskError.ErrorProcessingCommand()))
|
||||
}
|
||||
is SlixReadResult.Success -> {
|
||||
callback?.invoke(CompletionResult.Success(ResponseApdu(response.data)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue