标签:
本系列的上一篇文章《Monkey源码分析之事件源》中我们描述了monkey是怎么从事件源取得命令,然后将命令转换成事件放到事件队列里面的,但是到现在位置我们还没有了解monkey里面的事件是怎么一回事,本篇文章就以这个问题作为切入点,尝试去搞清楚monkey的event架构是怎么样的,然后为什么是这样架构的,以及它又是怎么注入事件来触发点击等动作的。
在看这篇文章之前,希望大家最好先去看下另外几篇博文,这样理解起来就会更容易更清晰了:
public class MonkeyKeyEvent extends MonkeyEvent {
private long mDownTime = -1;
private int mMetaState = -1;
private int mAction = -1;
private int mKeyCode = -1;
private int mScancode = -1;
private int mRepeatCount = -1;
private int mDeviceId = -1;
private long mEventTime = -1;
private KeyEvent keyEvent = null;
public MonkeyKeyEvent(int action, int keycode) {
super(EVENT_TYPE_KEY);
mAction = action;
mKeyCode = keycode;
}
public MonkeyKeyEvent(KeyEvent e) {
super(EVENT_TYPE_KEY);
keyEvent = e;
}
public MonkeyKeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int device, int scancode) {
super(EVENT_TYPE_KEY);
mAction = action;
mKeyCode = code;
mMetaState = metaState;
mScancode = scancode;
mRepeatCount = repeat;
mDeviceId = device;
mDownTime = downTime;
mEventTime = eventTime;
}
MonkeyKeyEvent有多个构造函数,参数都不一样,但是目的都只有一个,通过传进来的参数获得足够的信息保存成成员变量,以便今后创建一个android.view.KeyEvent,皆因该系统事件就是可以根据不同的参数进行初始化的。比如下面的getEvent方法就是根据不同的参数创建对应的KeyEvent的。注意这系统KeyEvent是非常重要的,因为我们今后通过WindowManager注入事件就要把它的对象传进去去驱动相应的按键相关的事件。 * @return the key event
*/
private KeyEvent getEvent() {
if (keyEvent == null) {
if (mDeviceId < 0) {
keyEvent = new KeyEvent(mAction, mKeyCode);
} else {
// for scripts
keyEvent = new KeyEvent(mDownTime, mEventTime, mAction,
mKeyCode, mRepeatCount, mMetaState, mDeviceId, mScancode);
}
}
return keyEvent;
}
支持的成员变量比较多,名字都挺浅显易懂,我这里就简单描述两个我们最常用的:public static final int KEYCODE_MENU = 82;
private int run(String[] args) {
...
if (!getSystemInterfaces()) {
return -3;
}
....
}
那么我们进入该方法看下我们需要的WindowManager是怎么初始化的。 private boolean getSystemInterfaces() {
mAm = ActivityManagerNative.getDefault();
if (mAm == null) {
System.err.println("** Error: Unable to connect to activity manager; is the system "
+ "running?");
return false;
}
mWm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
if (mWm == null) {
System.err.println("** Error: Unable to connect to window manager; is the system "
+ "running?");
return false;
}
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
if (mPm == null) {
System.err.println("** Error: Unable to connect to package manager; is the system "
+ "running?");
return false;
}
try {
mAm.setActivityController(new ActivityController());
mNetworkMonitor.register(mAm);
} catch (RemoteException e) {
System.err.println("** Failed talking with activity manager!");
return false;
}
return true;
}
@Override
public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
if (verbose > 1) {
String note;
if (mAction == KeyEvent.ACTION_UP) {
note = "ACTION_UP";
} else {
note = "ACTION_DOWN";
}
try {
System.out.println(":Sending Key (" + note + "): "
+ mKeyCode + " // "
+ MonkeySourceRandom.getKeyName(mKeyCode));
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(":Sending Key (" + note + "): "
+ mKeyCode + " // Unknown key event");
}
}
// inject key event
try {
if (!iwm.injectKeyEvent(getEvent(), false)) {
return MonkeyEvent.INJECT_FAIL;
}
} catch (RemoteException ex) {
return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION;
}
return MonkeyEvent.INJECT_SUCCESS;
}
注意传入参数 @Override
public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
if (verbose > 1) {
System.out.println("Sleeping for " + mThrottle + " milliseconds");
}
try {
Thread.sleep(mThrottle);
} catch (InterruptedException e1) {
System.out.println("** Monkey interrupted in sleep.");
return MonkeyEvent.INJECT_FAIL;
}
return MonkeyEvent.INJECT_SUCCESS;
}
所以虽然不同的MonkeyEvent实现类都实现了父类的injectEvent方法,但是并不是所有的的MonkeyEvent都需要注入事件的。所有这个接口方法的名字我觉得Google 工程师起得不好,比如叫做handleEvent就不会造成混乱了(个人见解)|
事件处理方式 |
MonkeyEvent实现类 |
关键代码 |
注释 |
| 通过WindowManager注入事件 | MonkeyKeyEvent | injectKeyiwm.injectKeyEvent(getEvent(),false)Event | |
| MonkeyTouchEvent | iwm.injectPointerEvent(me,false) | ||
| MonkeyTrackballEvent | iwm.injectTrackballEvent(me,false) | ||
| 通过往事件设备/dev/input/event0发送命令注入事件 | MonkeyFlipEvent | FileOutputStream("/dev/input/event0") | |
| 通过ActvityManager的startInstrumentation方法启动一个应用 | MonkeyInstrumentationEvent | iam.startInstrumentation(cn,null, 0,args,null) | |
| 睡眠 | MonkeyThrottleEvent | Thread.sleep(mThrottle) | |
| MonkeyWaitEvent | Thread.sleep(mWaitTime) |
| 作者 | 自主博客 | 微信服务号及扫描码 | CSDN |
| 天地会珠海分舵 | http://techgogogo.com | 服务号:TechGoGoGo扫描码:![]() |
http://blog.csdn.net/zhubaitian |
标签:
原文地址:http://www.cnblogs.com/techgogogo/p/4284823.html