Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android simulate key press

How can I programmatically simulate a key press on a Droid? I would like to mimic a manual key press (appearing on the droid that someone is pressing a key but it is being done programmatically).

There are solutions out there involving IWindowManager, but that isn't an option anymore in the new SDK.

like image 882
calcrisk33 Avatar asked Jan 02 '12 00:01

calcrisk33


3 Answers

You can use instrumentation, ie following code called from onCreate of your activity will cause menu to be opened and closed multiple times:

    new Thread(new Runnable() {         
        @Override
        public void run() {
            try {
            Instrumentation inst = new Instrumentation();
            for ( int i = 0; i < 10; ++i ) {
                inst.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
                Thread.sleep(2000);
                inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
                Thread.sleep(2000);
            }
            }
            catch(InterruptedException e){
            }
        }   
    }).start();

...but I am not sure if this is what you are after

like image 131
marcinj Avatar answered Nov 14 '22 23:11

marcinj


If you have a view that want to consume the event you can use BaseInputConnection class and its sendKeyEvent method.

To use it you will need to specify a target view (e.g an EditText) that will receive the KeyEvent. For example:

EditText editText;
BaseInputConnection inputConnection = new BaseInputConnection(editText, true);
inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_POUND));

The result of this is like user would actually pressed # key (while having the edit text focused).

like image 40
tpaczesny Avatar answered Nov 15 '22 01:11

tpaczesny


Using instrumentation in my opinion doesn't work as intended, when editText is focused it sometimes causes soft keyboard to pop.

In my project i have a numeric keyboard fragment which should act like a normal keyboard, that's my way of achieving desired solution:

I tested this solution on 3 devices with android 7+:

Keyboard fragment onClick():

@Override
public void onClick(View v) {

    switch(v.getId()) {

        case R.id.button0:
            simulateKeyPress(KeyEvent.KEYCODE_0);
            break;
        case R.id.button1:
            simulateKeyPress(KeyEvent.KEYCODE_1);
            break;
        case R.id.button2:
            simulateKeyPress(KeyEvent.KEYCODE_2);
            break;
        case R.id.button3:
            simulateKeyPress(KeyEvent.KEYCODE_3);
            break;
        case R.id.button4:
            simulateKeyPress(KeyEvent.KEYCODE_4);
            break;
        case R.id.button5:
            simulateKeyPress(KeyEvent.KEYCODE_5);
            break;
        case R.id.button6:
            simulateKeyPress(KeyEvent.KEYCODE_6);
            break;
        case R.id.button7:
            simulateKeyPress(KeyEvent.KEYCODE_7);
            break;
        case R.id.button8:
            simulateKeyPress(KeyEvent.KEYCODE_8);
            break;
        case R.id.button9:
            simulateKeyPress(KeyEvent.KEYCODE_9);
            break;
    }

}

public void simulateKeyPress(int key){
    Activity a = (Activity) getContext();
    a.getWindow().getDecorView().getRootView();
    BaseInputConnection inputConnection = new BaseInputConnection(a.getWindow().getDecorView().getRootView(),
            true);
    KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, key);
    KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, key);
    inputConnection.sendKeyEvent(downEvent);
    inputConnection.sendKeyEvent(upEvent);
}

This way i send the event to the root view of an activity and there it goes to the desired focused editText.

It's a bit rough solution but works fine.

like image 37
TomaszKoltun Avatar answered Nov 15 '22 01:11

TomaszKoltun