android应用发送按键事件
模拟按键事件分发
主要用到了以下三种方法:
Instrumentation
标准写法如下,缺点是不能跨进程
private void sentKey(final int keyCode) {
Log.d(TAG,"---sentKey---, keyCode : " + keyCode);
new Thread() {
public void run() {
try {
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(keyCode);
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
}.start();
}
模拟发送串口命令
参照串口调试执行input keyevent keycode
可跨进程,缺点按键响应时间过长,主观感觉有1-2s
private void sentKey(int keyCode) {
try {
String command = "input keyevent " + keyCode;
Log.i(TAG, "command = " + command);
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(command);
} catch (IOException e) {
Log.e(TAG, "Process exec failed!!!");
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
InputManager类的injectInputEvent(非系统应用)
不能跨进程
//public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0;
private void sentKey(int keyCode) {
Log.d(TAG,"---sentKey---, keyCode : " + keyCode);
Log.d(TAG,"\n");
new Thread() {
public void run() {
try {
long now = SystemClock.uptimeMillis();
KeyEvent down = new KeyEvent(now, now,KeyEvent.ACTION_DOWN, keyCode, 0);
KeyEvent up = new KeyEvent(now, now,KeyEvent.ACTION_UP, keyCode, 0);
InputManager inputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
invokeInjectInputEventMethod(inputManager,down,0);
invokeInjectInputEventMethod(inputManager,up,0);
// InputManager.getInstance().injectInputEvent(down, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
// InputManager.getInstance().injectInputEvent(up, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
} catch (Exception e) {
Log.e(TAG, "Simulate KeyEvent failed !!");
e.printStackTrace();
}
}
}.start();
}
private void invokeInjectInputEventMethod(InputManager inputManager, InputEvent event, int mode) {
Class<?> clazz = null;
Method injectInputEventMethod = null;
Method recycleMethod = null;
try {
clazz = Class.forName("android.hardware.input.InputManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
injectInputEventMethod = clazz.getMethod("injectInputEvent", InputEvent.class, int.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
injectInputEventMethod.invoke(inputManager, event, mode);
// 准备回收event的方法
recycleMethod = event.getClass().getMethod("recycle");
//执行event的recycle方法
recycleMethod.invoke(event);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
InputManager类的injectInputEvent(系统应用)
最终使用的方案,在系统中编译了的,可跨进程,响应时间适中。
private void sentKey(int keyCode) {
// int actkey = getRcCode(keyCode);
Log.i(TAG, "sentKey "+keyCode);
Thread sendKeyEvent = new Thread() {
@Override
public void run() {
try {
long now = SystemClock.uptimeMillis();
KeyEvent down = new KeyEvent(now, now,KeyEvent.ACTION_DOWN, keyCode, 0);
KeyEvent up = new KeyEvent(now, now,KeyEvent.ACTION_UP, keyCode, 0);
InputManager.getInstance().injectInputEvent(down, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
InputManager.getInstance().injectInputEvent(up, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
} catch (Exception e) {
Log.e(TAG, "Simulate KeyEvent failed !!");
e.printStackTrace();
}
}
};
sendKeyEvent.start();
}