Implemented catching Flickercode decoding errors and displaying them in UI

This commit is contained in:
dankl 2020-01-02 14:05:43 +01:00 committed by dankito
parent b3f815eb7e
commit 9869b44ccd
4 changed files with 65 additions and 27 deletions

View File

@ -26,7 +26,6 @@ import net.dankito.banking.ui.model.TanMediumStatus
import net.dankito.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium import net.dankito.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium
import net.dankito.fints.model.* import net.dankito.fints.model.*
import net.dankito.fints.response.client.FinTsClientResponse import net.dankito.fints.response.client.FinTsClientResponse
import net.dankito.fints.tan.TanImage
open class EnterTanDialog : DialogFragment() { open class EnterTanDialog : DialogFragment() {
@ -136,7 +135,14 @@ open class EnterTanDialog : DialogFragment() {
if (tanChallenge is FlickercodeTanChallenge) { if (tanChallenge is FlickercodeTanChallenge) {
val flickerCodeView = rootView.flickerCodeView val flickerCodeView = rootView.flickerCodeView
flickerCodeView.visibility = View.VISIBLE flickerCodeView.visibility = View.VISIBLE
flickerCodeView.setCode((tanChallenge as FlickercodeTanChallenge).flickercode)
val flickercode = (tanChallenge as FlickercodeTanChallenge).flickercode
if (flickercode.decodingSuccessful) {
flickerCodeView.setCode(flickercode)
}
else {
showDecodingTanChallengeFailedErrorDelayed(flickercode.error)
}
} }
else if (tanChallenge is ImageTanChallenge) { else if (tanChallenge is ImageTanChallenge) {
rootView.tanImageView.visibility = View.VISIBLE rootView.tanImageView.visibility = View.VISIBLE
@ -147,7 +153,7 @@ open class EnterTanDialog : DialogFragment() {
rootView.imgTanImageView.setImageBitmap(bitmap) rootView.imgTanImageView.setImageBitmap(bitmap)
} }
else { else {
showDecodingTanImageFailedErrorDelayed(decodedImage) // this method gets called right on start up before dialog is shown -> Alert would get displayed before dialog and therefore covered by dialog if we don't delay displaying dialog showDecodingTanChallengeFailedErrorDelayed(decodedImage.error)
} }
} }
@ -156,16 +162,20 @@ open class EnterTanDialog : DialogFragment() {
} }
protected open fun showDecodingTanImageFailedErrorDelayed(decodedImage: TanImage) { /**
* This method gets called right on start up before dialog is shown -> Alert would get displayed before dialog and
* therefore covered by dialog -> delay displaying alert.
*/
protected open fun showDecodingTanChallengeFailedErrorDelayed(error: Exception?) {
val handler = Handler() val handler = Handler()
handler.postDelayed({ showDecodingTanImageFailedError(decodedImage) }, 500) handler.postDelayed({ showDecodingTanChallengeFailedError(error) }, 500)
} }
protected open fun showDecodingTanImageFailedError(decodedImage: TanImage) { protected open fun showDecodingTanChallengeFailedError(error: Exception?) {
activity?.let { context -> activity?.let { context ->
AlertDialog.Builder(context) AlertDialog.Builder(context)
.setMessage(context.getString(R.string.dialog_enter_tan_error_could_not_decode_tan_image, decodedImage.error?.localizedMessage)) .setMessage(context.getString(R.string.dialog_enter_tan_error_could_not_decode_tan_image, error?.localizedMessage))
.setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
.show() .show()
} }

View File

@ -3,5 +3,20 @@ package net.dankito.fints.tan
open class Flickercode( open class Flickercode(
val challengeHHD_UC: String, val challengeHHD_UC: String,
val parsedDataSet: String val parsedDataSet: String,
) val error: Exception? = null
) {
val decodingSuccessful: Boolean
get() = error == null
override fun toString(): String {
if (decodingSuccessful == false) {
return "Decoding error: $error"
}
return "Parsed $challengeHHD_UC to $parsedDataSet"
}
}

View File

@ -1,5 +1,6 @@
package net.dankito.fints.tan package net.dankito.fints.tan
import org.slf4j.LoggerFactory
import java.util.regex.Pattern import java.util.regex.Pattern
@ -7,10 +8,13 @@ open class FlickercodeDecoder {
companion object { companion object {
val ContainsOtherSymbolsThanFiguresPattern: Pattern = Pattern.compile("\\D") val ContainsOtherSymbolsThanFiguresPattern: Pattern = Pattern.compile("\\D")
private val log = LoggerFactory.getLogger(FlickercodeDecoder::class.java)
} }
open fun decodeChallenge(challengeHHD_UC: String): Flickercode { open fun decodeChallenge(challengeHHD_UC: String): Flickercode {
try {
val challengeLength = parseIntToHex(challengeHHD_UC.substring(0, 2)) val challengeLength = parseIntToHex(challengeHHD_UC.substring(0, 2))
val startCode = parseStartCode(challengeHHD_UC, 2) val startCode = parseStartCode(challengeHHD_UC, 2)
@ -37,6 +41,11 @@ open class FlickercodeDecoder {
val parsedDataSet = dataWithoutChecksum + luhnChecksum + xorChecksumString val parsedDataSet = dataWithoutChecksum + luhnChecksum + xorChecksumString
return Flickercode(challengeHHD_UC, parsedDataSet) return Flickercode(challengeHHD_UC, parsedDataSet)
} catch (e: Exception) {
log.error("Could not decode challenge $challengeHHD_UC")
return Flickercode(challengeHHD_UC, "", e)
}
} }
protected fun parseStartCode(challengeHHD_UC: String, startIndex: Int): FlickercodeDatenelement { protected fun parseStartCode(challengeHHD_UC: String, startIndex: Int): FlickercodeDatenelement {

View File

@ -12,6 +12,10 @@ open class TanImage(
override fun toString(): String { override fun toString(): String {
if (decodingSuccessful == false) {
return "Decoding error: $error"
}
return "$mimeType ${imageBytes.size} bytes" return "$mimeType ${imageBytes.size} bytes"
} }