Android中提供了一个input命令来进行事件的模拟注入,如input tap 10 100, 可以模拟在坐标(10,100)处进行一个点击操作
input的帮助信息
$ input
Usage: input [<source>] <command> [<arg>...]
The sources are:
dpad
keyboard
mouse
touchpad
gamepad
touchnavigation
joystick
touchscreen
stylus
trackball
The commands and default sources are:
text <string> (Default: touchscreen)
keyevent [--longpress] <key code number or name> ... (Default: keyboard)
tap <x> <y> (Default: touchscreen)
swipe <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen)
draganddrop <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen)
press (Default: trackball)
roll <dx> <dy> (Default: trackball)
input的源码在frameworks/base/cmds/input/src/com/android/commands/input/Input.java
主要是通过向输入管理服务发送injectInputEvent命令来进行事件注入,
private void injectMotionEvent(int inputSource, int action, long when, float x, float y, float pressure) {
final float DEFAULT_SIZE = 1.0f;
final int DEFAULT_META_STATE = 0;
final float DEFAULT_PRECISION_X = 1.0f;
final float DEFAULT_PRECISION_Y = 1.0f;
final int DEFAULT_EDGE_FLAGS = 0;
MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, DEFAULT_SIZE,
DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y,
getInputDeviceId(inputSource), DEFAULT_EDGE_FLAGS);
event.setSource(inputSource);
Log.i(TAG, "injectMotionEvent: " + event);
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}
由于input命令是个脚本,调用的是生成的jar中的方法,
cat /system/bin/input
# Script to start "input" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/input.jar
exec app_process $base/bin com.android.commands.input.Input "$@"
通过app_process启动java虚拟机去执行,我们可以在一个脚本文件中多次的调用input命令来实现一系列的点击,滑动操作,
但是这样就会多次启动虚拟机,每次执行都会延迟1秒左右,这里,我们可以在一次启动后,接收输入命令来实现事件注入
使用场景:玩一些手机游戏如绝地求生时,可以通过连接键盘去进行操作。
private void run(String[] args) {
if (args.length < 1) {
showUsage();
return;
}
...
} else if (command.equals("roll")) {
inputSource = getSource(inputSource, InputDevice.SOURCE_TRACKBALL);
if (length == 3) {
sendMove(inputSource, Float.parseFloat(args[index+1]),
Float.parseFloat(args[index+2]));
return;
}
}
//添加
else if (command.equals("test")) {
int duration = -1;
inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
System.out.println("Please input the command:");
try {
while(true)
{
char c = (char)System.in.read();
if (c == 'a' || c == 'A')
{
sendSwipe(inputSource, 200, 400, 100, 400, duration);
}
if (c == 'd' || c == 'D')
{
sendSwipe(inputSource, 200, 400, 300, 400, duration);
}
}
} catch (Exception e)
{}
// duration = Integer.parseInt(args[index+5]);
}
输入aaaa,就可以在屏幕上看到多次滑动,
这里有个问题,由于java的io方法中,没有类似C里面的getchar方法,所以不能实时的获取到键盘输入,需要敲回车后才可以接收键盘输入。
可以写一个C程序专门用来接收键盘输入,然后把输入通过进程通信的方式传给input程序,这算得上是一个不得已的方案。