I'm currently working on an app that uses a barcode scanner for scanning some bar codes. So, I'm capturing the data by overloading the dispatchKeyEvent method. Everything works fine, as long as I'm not trying to post-process the prompted bar code.
For example, this code snippet works as expected.
private var promptedEAN:String = ""
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
if(event?.action == KeyEvent.ACTION_DOWN) {
val pressedKey: Char = event.getUnicodeChar().toChar()
promptedEAN += pressedKey
val eTMengeKomm = findViewById<EditText>(R.id.eTMengeKomm)
eTMengeKomm.setText(promptedEAN, TextView.BufferType.EDITABLE)
val etCharge = findViewById<EditText>(R.id.eTCharge)
etCharge.setText(promptedEAN, TextView.BufferType.EDITABLE)
val etMHD = findViewById<EditText>(R.id.eTMHD)
etMHD.setText(promptedEAN, TextView.BufferType.EDITABLE)
}
return super.dispatchKeyEvent(event)
}
BUT, as soon as I want to post-process the prompted barcode inside the dispatchKeyEvent method, the whole app freezes. In this case, I have to go to to Settings -> App -> Force Stop to kill my app, because none of the buttons work either.
My post-processing code works without any problems - I tried it out in with a test string in the onCreate method of my activity.
My question is why I'm getting this behavior with the dispatchKeyEvent method?
This is my code. I'm filling the HashMap with the key-value pairs in the OnCreate method, which is starting before firing the dispatchKeyEvent.
private var promptedEAN:String = ""
private var testPromptedEAN:String = "" //"C10207613037926927200015200600370098$1092547017L4"
private val hashMap : HashMap<String, Int> = HashMap()
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
if(event?.action == KeyEvent.ACTION_DOWN) {
val pressedKey: Char = event.getUnicodeChar().toChar()
promptedEAN += pressedKey
testPromptedEAN = promptedEAN
val eTMengeKomm = findViewById<EditText>(R.id.eTMengeKomm)
eTMengeKomm.setText(promptedEAN, TextView.BufferType.EDITABLE)
val etCharge = findViewById<EditText>(R.id.eTCharge)
etCharge.setText(promptedEAN, TextView.BufferType.EDITABLE)
val etMHD = findViewById<EditText>(R.id.eTMHD)
etMHD.setText(promptedEAN, TextView.BufferType.EDITABLE)
if (testPromptedEAN.contains("C1",true) or testPromptedEAN.contains("C0",true)) { // EAN-128 Code
var pos:Int = 2 // init pos
var tail:String = testPromptedEAN.substring(pos) // init tail
var lookInString:String =""
while (pos<testPromptedEAN.length-1) {
var searchString:String = testPromptedEAN.substring(pos, pos+2) // look into 2-digit codes first
if (hashMap.containsKey(searchString)){
var lengthData4code:Int = hashMap.getValue(searchString) // get length of data for code from hash table
if (tail.length<lengthData4code){
lengthData4code = tail.length
lookInString = tail.substring(searchString.length, lengthData4code)
} else {
lookInString = tail.substring(searchString.length, searchString.length+lengthData4code) // data (part)string
}
if (lookInString.indexOf("$")>=0) { // string size is actually shorter than expected
lookInString = tail.substring(searchString.length,searchString.length+lookInString.indexOf("$"))
pos += (searchString.length + lookInString.length + 1)
} else {
pos += (searchString.length+ lengthData4code)
}
if (pos>=testPromptedEAN.length-1) {tail = ""}
else {tail = testPromptedEAN.substring(pos)}
if (searchString.contains("37", false)) {
//val eTMengeKomm = findViewById<EditText>(R.id.eTMengeKomm)
eTMengeKomm.setText(lookInString, TextView.BufferType.EDITABLE)
}
if (searchString.contains("10", false)) {
//val etCharge = findViewById<EditText>(R.id.eTCharge)
etCharge.setText(lookInString, TextView.BufferType.EDITABLE)
}
if (searchString.contains("15", false)) {
//val etMHD = findViewById<EditText>(R.id.eTMHD)
etMHD.setText(lookInString, TextView.BufferType.EDITABLE)
}
}
}
}
}
return super.dispatchKeyEvent(event)
}
Any help is highly appreciated.
How I solved this problem:
First of all, I got rid of the overloaded dispachKeyEvent
method. This was making a lot of mess in my app, in my case, the back and the middle button were not reacting at all. A barcode USB scanner should be mostly recognized from Android as a external keyboard, so this method was not needed for capturing barcodes into specific EditText
field(s). After that, I've set the focus on the first EditText
field and prompted the barcode there.
Secondly, I've learned that a while
loop doesn't work in an active UI thread - this was the reason, why my app was freezing all the time. That's why I've implemented an AsyncTask
as inner class in my Activity and placed all the backround processing logic into the overloaded doInBackround
method from the AsyncTask
. In the onPostExecute
method, I've set all the needed values for my EditText
fields.
UPDATE: I've lifted the whole background logic into a ViewModel
and finally got rid of the AsyncTask
.