18

I have a physical barcode scanner and I want to get it's input, i.e the barcode, in the app without having a focused EditText.

I tried adding a KeyListener in my Activity. However, none of its implemented methods (onKeyUp, onKeyDown etc) was called.

Then I added the dispatchKeyEvent, which worked, but is never called as many times as the barcode length. Instead, before the barcode is read, some random button in my view gets focus from the barcode scanner.

String barcode = "";

@Override
public boolean dispatchKeyEvent(KeyEvent e) {
    char pressedKey = (char) e.getUnicodeChar();
    barcode += pressedKey;
    if (e.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
        Toast.makeText(getApplicationContext(), "barcode--->>>" + barcode, Toast.LENGTH_LONG)
                .show();
    }

    return super.dispatchKeyEvent(e);
}

I've seen a few questions out there in SO but none really gave a concrete answer.

XeniaSis
  • 2,192
  • 5
  • 24
  • 39
  • I think that to really solve this, you'd need some documentation from the barcode scanner - what exactly is it supposed to be sending to your app? Is it emulating a keyboard (the usual thing to do), or something else? Any other hints from the device's documentation? – GreyBeardedGeek Jul 22 '16 at 18:07
  • Searched the documentation but didn't find anything. I did test it with an `EditText` and my only conclusion is that after sending the barcode number one by one it emits an `ENTER` – XeniaSis Jul 22 '16 at 18:14
  • @XeniaSis hai....how did you solve the problem. I tried the below solution. But when I call an api with barcode as parameter only first character is send hence errorr. – Android_id Dec 31 '21 at 20:03
  • @Android_id sorry, haven't worked with android development in years – XeniaSis Jan 02 '22 at 11:09

6 Answers6

10

For me, for a barcode scanner (USB, reference STA pcs) works the next code:

@Override
public boolean dispatchKeyEvent(KeyEvent e) {

    if(e.getAction()==KeyEvent.ACTION_DOWN){
        Log.i(TAG,"dispatchKeyEvent: "+e.toString());
        char pressedKey = (char) e.getUnicodeChar();
        barcode += pressedKey;
    }
    if (e.getAction()==KeyEvent.ACTION_DOWN && e.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
        Toast.makeText(getApplicationContext(), 
            "barcode--->>>" + barcode, Toast.LENGTH_LONG)
        .show();

        barcode="";
    }

    return super.dispatchKeyEvent(e);
}
Hpsaturn
  • 2,702
  • 31
  • 38
  • Hello. I have a tablet app and a physical barcode scanne, but when the tablet is connected to the pc via usb, the scanner does not work correctly. any suggestions? – jvargas Jul 14 '20 at 15:47
3

First, thank you all. Since my App has to look up the barcode in the DB I had to not add the ENTER_KEY input to the Barcode String, also to prevent any focused button of going off I made the Method return false.

String barcode = "";
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
    if(e.getAction()==KeyEvent.ACTION_DOWN
            && e.getKeyCode() != KeyEvent.KEYCODE_ENTER){ //Not Adding ENTER_KEY to barcode String
        char pressedKey = (char) e.getUnicodeChar();
        barcode += pressedKey;
    }
    if (e.getAction()==KeyEvent.ACTION_DOWN 
            && e.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
        Log.i(TAG,"Barcode Read: "+barcode);
        barcodeLookup(barcode);// or Any method handling the data
        barcode="";
    }
        return false;
}
3

Using kotlin

private val barcode = StringBuffer()

override fun dispatchKeyEvent(event: KeyEvent?): Boolean {

    if (event?.action == KeyEvent.ACTION_DOWN) {
        val pressedKey = event.unicodeChar.toChar()
        barcode.append(pressedKey)
    }
    if (event?.action == KeyEvent.ACTION_DOWN && event?.keyCode == KeyEvent.KEYCODE_ENTER) {
        Toast.makeText(baseContext, barcode.toString(), Toast.LENGTH_SHORT).show()
        barcode.delete(0, barcode.length)
    }

    return super.dispatchKeyEvent(event)
}
1

e.getCharacters() should give you the complete barcode. This works for me on a PL-40L device with embedded 2d barcode reader, running Android 5.1 dispatchKeyEvent(KeyEvent e) is triggered once for each read barcode, not for each character in the barcode Hope this helps

0

DispatchKeyEvent Hardware key events are always delivered to the View currently in focus. They are dispatched starting from the top of the View hierarchy, and then down, until they reach the appropriate destination. If your View (or a child of your View) currently has focus, then you can see the event travel through the dispatchKeyEvent() method. In short, dispatchKeyEvent() will be only called if TextView/EditText is in focus.

Pawan Maheshwari
  • 15,088
  • 1
  • 48
  • 50
0

You can do it even without any focused View. You need to subscribe for broadcast intent like this:

const val QR_ACTION: String = "android.intent.ACTION_DECODE_DATA"
const val QR_EXTRA: String = "barcode_string"

private val receiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            try {
                Timber.d("Get intent ${intent.action}")
                if (QR_ACTION == intent.action) {
                    if (intent.hasExtra(QR_EXTRA)) {
                       val code = intent.getStringExtra(QR_EXTRA)
                       Timber.d("New QR code $code")
                       // now you have qr code here 
                    }
                }                    }
            } catch (t: Throwable) {
                // handle errors
            }
        }
    }

Please check QR_ACTION and QR_EXTRA in your scanner settings first, it can be different for different brands.