Android 在按下多个键时不调用 onKeyUp

Android is not calling onKeyUp when multiple keys pressed

我正在 Java 中为 Android 编写一个小游戏,但我在处理输入时遇到了问题。对于早期测试,我使用的是硬件键盘输入,但我最终打算使用游戏手柄控件。

我遇到的问题是:当用户按住一个 key 超过 10 秒,同时按下并释放其他一些键时,onKeyUp() 函数因为第一个键在最终释放时不会被调用。

我还没有找到完全最小的重现,但我可以在两个不同的 emulators 和一个物理 Nexus 5(带有一个显示为键盘的游戏手柄)上可靠地触发它。

相关代码,已删除冗余和日志语句:

public class GameSurfaceView extends GLSurfaceView {
    public final static short VBTN_FORWARD      = 0;
    public final static short VBTN_BACKWARD     = 1;
    // snipped several more similar constants
        public AtomicIntegerArray virtual_button_state = new AtomicIntegerArray(7);

    @Override
    public boolean onKeyDown(int keyCode, @NonNull KeyEvent event){
        if (event.isLongPress() || event.getRepeatCount() > 0){
            return true;
        }
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_W:
                virtual_button_state.incrementAndGet(GameRenderer.VBTN_FORWARD);
                return true;
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_S:
                virtual_button_state.incrementAndGet(GameRenderer.VBTN_BACKWARD);
                return true;
            // snipped several more similar cases
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, @NonNull KeyEvent event){
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_UP:
            case KeyEvent.KEYCODE_W:
                virtual_button_state.decrementAndGet(GameRenderer.VBTN_FORWARD);
                return true;
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_S:
                virtual_button_state.decrementAndGet(GameRenderer.VBTN_BACKWARD);
                return true;
            // snipped several more similar cases
        }
    }
}

我做了广泛的测试,跟踪语句显示 onKeyUp() 没有被调用 at all。不管是什么问题,它首先阻止了事件到达我的 GLSurfaceView。

Possibly-relevant其他信息:

问题已解决 - 错误与我最初描述的不完全相同。我编写的用于检测焦点是否丢失的测试代码中存在一个微妙的错误,这导致我对问题的原因得出了错误的结论。

在触摸事件期间,焦点实际上丢失了,有时在触发 keyUp 事件时没有重新获得焦点。多个同时发生的按键事件使这种情况更有可能发生,这就是为什么它被错误地包含在重现中,以及为什么我错误地关注多个按键而不是同时发生的触摸事件。

问题的最终原因是在我的视图构造函数中调用 setFocusableInTouchMode(true) 失败。