Search code examples
javaandroidbluetoothbarcode-scannerhid

Android handle key event before reaching focused view


I connected an external barcode scanner to my tablet via Bluetooth in HID mode and try to handle the input in my app. The barcode scanner basically works like a keyboard.

I have a simple gui and in my main activity i have the following method:

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    System.out.println(keyCode + " - " + (char) event.getUnicodeChar());
    return true;
}

Problem:

when i open a text app, like google notes and scan any code the barcode is inserted followed by a new line. this made me think that i could handle the key events and write all characters into a stringbuilder until i reach the key event for 'Enter'.

But the problem is that when i use the scanner (this barcode) within my app the output of the method above is the following:

59 - �� <- 'Shift'
29 - a
59 - ��
47 - s
62 -
8 - 1
9 - 2
10 - 3

the 'Enter' at the end of the barcode couldn't be caught in the event (should be keyCode 66) but one of the elements in my GUI was highlighted, which means the scanner must have sent 'Enter'

When I add a multiline EditText to my GUI and scan the same barcode while the element is focused the output is the following:

29 - a
47 - s
62 -
8 - 1
9 - 2
10 - 3
66 -

Here the 'Enter' key event was logged while the both 'Shift' keys are not visible (the letters in the EditText element are capitalized though).

as a workaround i could have an invisible multiline element that remains focussed all the time, but i really prefer not to rely on an invisible element. instead i wanna catch all the key strokes sent by my barcode scanner.

any ideas why i cannot see 'Enter'?


Solution

  • I did a little more research on that matter and I found a pretty (for me) satisfying solution to my problem.

    Apparently onKeyDown and onKeyUp are not always called, especially if a KeyEvent was consumed somewhere else by a window element. In my case a ListView had the default focus and consumed the ENTER event before it reached the mentioned methods (therefore it got highlighted as mentioned in my problem description).

    There is another method that can be used, which is called before the KeyEvents are sent to the window. it is dispatchKeyEvent. But cautious, the event is called twice, once for key down and once for key up.

    here a sample code:

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
    
        System.out.println(event.getAction() + " " + event.getKeyCode() + " - " + (char) event.getUnicodeChar());
    
        return true;
    }
    

    this solution works for me, because my app doesn't need to listen to any other key event, otherwise another return should be used.