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.
Solution 1:
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
Solution 2:
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).
Solution 3:
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.