1

I'm trying to get a Sip'n'Puff device to work with an Android tablet. I have the S&P set to joystick mode. I've remapped the relevant joystick buttons to the down arrow key and the enter key by overriding dispatchKeyEvent in my activity, as such:

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BUTTON_1) {
        if(event.getAction() == KeyEvent.ACTION_DOWN) {
            return dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN));
        } else if(event.getAction() == KeyEvent.ACTION_UP) {
            return dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_DOWN));
        }
    } else if(event.getKeyCode() == KeyEvent.KEYCODE_BUTTON_2) {
        if(event.getAction() == KeyEvent.ACTION_DOWN) {
            return dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
        } else if(event.getAction() == KeyEvent.ACTION_UP) {
            return dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER));
        }
    }
    return super.dispatchKeyEvent(event);
}

Now here's the issue. I've got my layout set up so that the user can visit every View in a loop by pressing the down arrow key. This works just fine using a physical keyboard. I've even remapped the tab key on the keyboard to down arrow and that works just fine.

With the S&P device, however, the key mapped to down arrow exhibits odd behavior. If I navigate through a ListView, the selection stops at the last item and focus won't move to the next View in the interface. I've confirmed that the KEYCODE_BUTTON_1 event is being caught and converted to DPAD_DOWN appropriately, it just doesn't do what it's supposed to do.

Given that remapping the tab key on the keyboard works correctly, could it be that the down arrow key simply does something different when a joystick is plugged in? Any ideas on what's happening here, and how I can fix it?

Edit: I've now tried the keyboard mode of the S&P device, which uses the enter and spacebar keys. I remapped space to down arrow, and ran into the exact same problem as above. So it doesn't seem to be a keyboard vs. joystick issue.

Edit edit: After some tinkering with postDelayed, it looks like dispatching a down arrow event doesn't actually cause navigation to occur. Or to be more precise, it only causes navigation to occur within the ListView. I guess remapping the tab key worked because it was being treated as tab while not in the ListView, and as down arrow while in the ListView. At least it's a lead?

Yet another edit: I think what's happening here is that navigation via a physical input device is handled outside of the Activity. I can navigate through the ListView because it's a View within the Activity, so it receives the DPAD_DOWN event from dispatchKeyEvent and reacts by moving the selection. However, it's not Views that normally handle navigation: it's some layer in the OS between the input device and the application. So the question now becomes how to get a hold of that navigation layer and override the key mappings there.

Graph Theory
  • 699
  • 1
  • 7
  • 18
  • I guess you can't leave a ListView using ONLY down action. You have to press TAB key to leave it. – Stan Apr 01 '15 at 19:49
  • If I use the down arrow on the keyboard it leaves the ListView just fine. – Graph Theory Apr 01 '15 at 19:50
  • When you use a soft keyboard maybe it acts a bit differently like adds a tab at the end of list. Try also to tap left-right to leave ListView. – Stan Apr 01 '15 at 19:52
  • Sorry, I should have specified that I'm using a physical keyboard plugged into the device. – Graph Theory Apr 01 '15 at 19:52
  • Try to log which key codes generates a keyboard maybe that gonna shed some light... I guess keyboard works without any remapping like you are doing for the joystick – Stan Apr 01 '15 at 19:53
  • Keyboard arrow down generates KEYCODE_DPAD_DOWN. Keyboard tab generates KEYCODE_TAB. I had to check to know which codes to remap the joystick keys to. – Graph Theory Apr 01 '15 at 19:54
  • Could it be that the ListView intercepts and interprete all the key presses on its own? – Stan Apr 01 '15 at 19:58
  • There are other methods like `public boolean onKeyUp(int keycode, KeyEvent e)` maybe you should give that method a try instead of dispatch one? – Stan Apr 01 '15 at 20:00
  • Unfortunately onKeyUp and onKeyDown handle input after all of the Views in the layout, so that doesn't help either. I might be able to create custom classes for every type of View that can be visited and override their onKeyUp and onKeyDown methods, but that would NOT be fun, haha. I really, really hope there's a better way. – Graph Theory Apr 01 '15 at 20:16
  • "Could it be that the ListView intercepts and interprete all the key presses on its own?" As far as I understand, dispatchKeyEvent will capture key input first, before the Views in the layout. – Graph Theory Apr 01 '15 at 20:19
  • What about to try to postDelayed a KEYCODE_DPAD_DOWN event and move using joystick to the end of ListView before it triggers? Just to see what happens. Will it leave the ListView that way? – Stan Apr 01 '15 at 20:25
  • Okay, if I use postDelayed, it doesn't leave the ListView when *either* the keyboard or the S&P device are plugged in. Which seems to mean that launching an arrow key event with dispatchKeyEvent isn't actually causing navigation to occur. – Graph Theory Apr 01 '15 at 21:00
  • Why are you so sure? I tried to generate keyevent and it works. The point is - you need to generate key_down followed by key_up. – Stan Apr 01 '15 at 21:15
  • Also I tried to remap vol_up and vol_down and I can't leave the ListView using remapped DPAD_DOWN KeyEvent. Instead vol_down starts to act like real vol_down (not reampped) at the last item in ListView. – Stan Apr 01 '15 at 21:18
  • "Why are you so sure?" I tried remapping the arrow key to another arbitrary key (the "K" key) and it's exhibiting the same behavior as the S&P device. See my latest edits. – Graph Theory Apr 01 '15 at 21:22
  • 1
    A question was addressed to "Which seems to mean that launching an arrow key event with dispatchKeyEvent isn't actually causing navigation to occur" actually. It does causing a navigation to occur, except for a DPAD_DOWN at the end of ListView. – Stan Apr 01 '15 at 21:24
  • 1
    http://stackoverflow.com/questions/11601892/how-to-spoof-arrow-keys-to-my-activity-on-android – Stan Apr 01 '15 at 21:34

0 Answers0