Как подделать клавиши со стрелками для моей активности на Android

Я пытаюсь переопределить кнопки громкости, чтобы они действовали как клавиши со стрелками вверх / вниз (то есть они должны переместить фокус на все мои виды деятельности с возможностью фокусировки).

Для этого я отменяю свою деятельность dispatchKeyEvent() Обратите внимание, что я также пытался onKeyDown() но некоторая часть событий, связанных с клавишами регулировки громкости, все еще проходила через систему, мое устройство имеет звуковую обратную связь при изменении громкости. Я все еще мог слышать звуковой сигнал, но громкость на самом деле не менялась. Переключение на dispatchKeyEvent() убрал звуковой сигнал из системы.

Вот мой ток dispatchKeyEvent() метод:

@Override
public boolean dispatchKeyEvent(KeyEvent ke){
    int keyCode = ke.getKeyCode();
    if(ke.getAction() == KeyEvent.ACTION_DOWN){
        print("press " + keyCode);
        if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) 
        { 
            mTxt.postDelayed(pressDown, 600);
            return true;
        }else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP) 
        { 
            KeyEvent key = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP); 
            dispatchKeyEvent(key); 
            return true;
        } 
    }else if(ke.getAction() == KeyEvent.ACTION_UP){
        print("release " + keyCode);
        if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) 
        { 
            /*KeyEvent keyUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_DOWN); 
            dispatchKeyEvent(keyUp);*/
            return true;
        }else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP) 
        { 
            KeyEvent keyUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_UP); 
            dispatchKeyEvent(keyUp);
            return true;
        } 
    }
    return super.dispatchKeyEvent(ke);
}

способ, которым он настроен сейчас, использует разные методы для увеличения и уменьшения, но ни один из них не работает правильно, чтобы сместить фокус. Для клавиши "Вверх" я просто вызываю функцию dispatchKeyEvent() вручную, передавая ей клавишу d-pad up и то же действие, которое происходило с кнопкой регулировки громкости (поэтому, когда я нажимаю, она должна нажиматься, а когда я отпускаю, она должна отпускать). Мой вывод для кнопки вверх выглядит так:

press 24
press 19
release 24
release 19

для кнопки "вниз" я немного подправил ее, потому что подумал, может быть, тот факт, что нажатие на dpad происходило до того, как громкость отпала, сломал его, поэтому я создал работающий модуль, который будет одновременно нажимать и отпускать кнопку dpad

    pressDown = new Runnable(){
        @Override
        public void run(){
            KeyEvent key = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN); 
            dispatchKeyEvent(key); 
            KeyEvent keyUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_DOWN); 
            dispatchKeyEvent(keyUp);
        }
    };

и я задерживаю это на долю секунды, чтобы у меня была возможность выпустить том. Мой вывод для кнопки вниз выглядит так:

press 25
release 25
press 20
release 20

если я подключу USB-клавиатуру к своему устройству и нажму клавиши со стрелками, фокус перемещается правильно, и я вижу вывод вверх:

press 19
release 19

и для пуха:

press 20
release 20

Единственное отличие (насколько я могу судить) состоит в том, что фокус фактически перемещается правильно, когда я нажимаю стрелки на клавиатуре, и не перемещается вообще, когда я нажимаю кнопки громкости (которые подделывают кнопки со стрелками).

Я что-то пропускаю здесь? Может ли кто-нибудь помочь мне понять, как подделать клавиши со стрелками к моей деятельности, чтобы они на самом деле правильно перемещали фокус?

1 ответ

Решение

В конце концов я понял, что вам нужно использовать класс Instrumentation для отправки ключевых событий, и вы должны сделать это вне основного потока по некоторым причинам. Вот фрагменты, которые будут отправлять вниз и вверх:

new Thread(new Runnable() {         
   @Override
   public void run() {                 
       new Instrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
   }   
}).start();

new Thread(new Runnable() {         
   @Override
   public void run() {                 
       new Instrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
   }   
}).start();

Если вы используете их вместо переопределенного dispatchKeyEvent из вопроса, он будет правильно перемещать фокус.

Другие вопросы по тегам