Ok I think I've got a working solution for you. Turns out I had a few things wrong. For one dispatchKeyEvent()
is better than onKeyDown()
because it stops the volume button presses from making it through to the system(on my device they caused a beep sound to play, but no volume change). And it also turns out that you need to use the Instrumentation class to send the spoof KeyEvents instead of manually calling dispatchKeyEvent()
. The Instrumentation class won't make its method calls from the main thread either, so you've got to wrap the calls in their own thread.
I also learned why some of the buttons on your device were sending two key events 117 and 71. Those match up to shift+[ For our purposes we can ignore the shift press and use just the [ to take action for us.
Here is an overridden dispatchKeyEvent() method that seems to be working for me.
@Override
public boolean dispatchKeyEvent(KeyEvent ke){
int keyCode = ke.getKeyCode();
if(ke.getAction() == KeyEvent.ACTION_DOWN){
if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
{
/**************************************
* What ever code snippet you put
* here will run whenever you press the
* volume down button on your presenter
* device
**************************************/
return true;
}else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP)
{
/**************************************
* What ever code snippet you put
* here will run whenever you press the
* volume up button on your presenter
* device
**************************************/
return true;
}else if (keyCode == 30){
/**************************************
* What ever code snippet you put
* here will run whenever you press the
* left programmable button on your
* presenter device
**************************************/
return true;
}
else if (keyCode == 59){
/**************************************
* This was an attempt to get it to ignore
* the shift keypress coming from the
* left/right arrow keys on the devices
* ignoring that would in theory make
* those keys function as up/down focus
* movers. Didn't seem to work though.
* you could probably remove this branch
* of the if statement if you want.
* However since those buttons do send
* key events to the device it should
* should still be possible override these
* buttons somehow.
**************************************/
return true;
}
}else if(ke.getAction() == KeyEvent.ACTION_UP){
/**************************************
* This section will catche the "release"
* events from all of the keys we are using
* and tell the system that we've handled
* them. So that the system will not pass
* the events along to anything else.
**************************************/
if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
{
/**************************************
* If you had any reason / desire to
* you could put a code snipet here and it
* would be run when you let go after
* pressing the volume down button on your
* presenter device.
**************************************/
return true;
}else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP)
{
return true;
}else if (keyCode == 59){
return true;
}else if (keyCode == 30) {
return true;
}
}
/**************************************
* The following line is needed so that
* the system will treat any key events
* that we aren't interested in normally.
* i.e. the back button on the tablet, by
* by calling super.dispatchKeyEvent(), we
* ensure that the back button still behaves
* like normal.
**************************************/
return super.dispatchKeyEvent(ke);
}
This will allow you to take control of 3 buttons on your presenter device (Vol Up, Vol Down, and the Left programmable button), by putting your code snippets in the appropriate branch of the if statement you can make any of those 3 buttons do whatever you want.
I've created a test project that implements this you can download the zipped project folder here if you'd like to see the whole thing. In this test project I've set it up so that vol up/down will function as d-pad up/down which will allow you to move focus to different views within your activity.
Here is the code that you could put inside one of the branches of the if statement to spoof a d-pad arrow button:
new Thread(new Runnable() {
@Override
public void run() {
new Instrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
}
}).start();
you can replace the KeyEvent.KEYCODE_DPAD_DOWN
with any other key event that you want for instance KeyEvent.KEYCODE_DPAD_UP
or KeyEvent.KEYCODE_DPAD_CENTER
the latter of which would act as a select button which will send a click event to the button that currently has focus.