好的,我想我已经为您找到了可行的解决方案。原来我做错了一些事情。对于一个dispatchKeyEvent() 比onKeyDown() 更好,因为它阻止按下音量按钮进入系统(在我的设备上,它们会发出哔哔声,但音量没有变化)。而且事实证明,您需要使用Instrumentation 类来发送欺骗键事件,而不是手动调用dispatchKeyEvent()。 Instrumentation 类也不会从主线程进行方法调用,因此您必须将调用包装在它们自己的线程中。
我还了解了为什么您设备上的某些按钮会发送两个关键事件 117 和 71。这些与 shift+[ 匹配,出于我们的目的,我们可以忽略按下 shift 并仅使用 [ 为我们采取行动。
这是一个似乎对我有用的被覆盖的 dispatchKeyEvent() 方法。
@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);
}
这将允许您控制演示者设备上的 3 个按钮(Vol Up、Vol Down 和左侧可编程按钮),方法是将您的代码 sn-ps 放在 if 语句的适当分支中,您可以进行任何操作这 3 个按钮中的任何一个都可以随心所欲。
我已经创建了一个测试项目来实现这一点,如果您想查看整个内容,可以download the zipped project folder here。在这个测试项目中,我进行了设置,以便 vol up/down 将用作 d-pad up/down,这将允许您将焦点移动到活动中的不同视图。
这是您可以放在 if 语句的一个分支中以欺骗 d-pad 箭头按钮的代码:
new Thread(new Runnable() {
@Override
public void run() {
new Instrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
}
}).start();
您可以将 KeyEvent.KEYCODE_DPAD_DOWN替换为您想要的任何其他关键事件,例如 KeyEvent.KEYCODE_DPAD_UP或 KeyEvent.KEYCODE_DPAD_CENTER @ KeyEvent.KEYCODE_DPAD_CENTER后者将作为选择按钮,将单击事件发送到当前具有焦点的按钮.