源码下载
monkey源码下载地址:
http://download.csdn.net/download/kingzhongmu/9424373
Monkey 测试的入口
在Monkey.java中有一个main函数
public static void main(String[] args) {
int resultCode = (new Monkey()).run(args);
System.exit(resultCode);
}
真正的逻辑执行是在run函数中
Monkey 的执行流程
private int run(String[] args) {
processOptions();//处理从命令行接收到的参数,并赋给相应的变量
loadPackageLists();//加载设置的白名单或者黑名单
getSystemInterfaces();//获得系统接口
getMainApps();//获取要执行的activity
if (mScriptFileName != null) {
mEventSource = new MonkeySourceScript(mScriptFileName);//如果有脚本文件输入的话,就new一个MonkeySourceScript对象。
mEventSource.setVerbose(mVerbose);
} else {
mEventSource = new MonkeySourceRandom(mSeed, mMainApps, mThrottle, mThrottleTouch, mThrottleKey);//如果没有脚本文件输入的话,就new一个MonkeySourceRandom对象。也是我们常用的简单操作。
mEventSource.setVerbose(mVerbose);
}
((MonkeySourceRandom) mEventSource).setFactors(i, mFactors[i]);//设置事件的操作比例。
mEventSource.validate();//调整事件比例。
((MonkeySourceRandom) mEventSource).generateActivity();//随机事件下,产生一个随机的Activity。
int crashedAtCycle = runMonkeyCycles();//monkey的核心事件注入逻辑
}
Monkey 的类结构
monkey源代码主要有若干个java文件,除了入口Monkey.java文件及工具文件外,另外还有两组类文件,分别是以MonkeyEventSource为接口类的事件流处理类(MonkeySourceRandom、MonkeySourceScript等类,分别处理随机事件流和monkey脚本事件流),以及以MonkeyEvent为接口类的事件操作类(MonkeyActivityEvent、MonkeyKeyEvent、MonkeyMotionEvent、MonkeyFlipEvent、MonkeyThrottleEvent等类)
随机事件的生成
public MonkeyEvent getNextEvent() {
//从MonkeyEvent队列mQ里取出MonkeyEvent事件,如果mQ当前是空的话,就生成一个事件。否则就取出队列的第一个事件。
if (mQ.isEmpty()) {
generateEvents();
}
mEventCount++;
MonkeyEvent e = mQ.getFirst();
mQ.removeFirst();
return e;
}
private void generateEvents() {
float cls = mRandom.nextFloat(); //由seed生成的Random,取一个随机数
int lastKey = 0;
//依据随机数的大小,执行生成不同手势的MotionEvent事件(generatePointerEvent实质上是生成MotionEvent事件)。
if (cls < mFactors[FACTOR_TOUCH]) {
generatePointerEvent(mRandom, GESTURE_TAP);
return;
} else if (cls < mFactors[FACTOR_MOTION]) {
generatePointerEvent(mRandom, GESTURE_DRAG);
return;
} else if (cls < mFactors[FACTOR_PINCHZOOM]) {
generatePointerEvent(mRandom, GESTURE_PINCH_OR_ZOOM);
return;
} else if (cls < mFactors[FACTOR_TRACKBALL]) {
generateTrackballEvent(mRandom);
return;
}
......
MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey);
//将事件添加到队列
mQ.addLast(e);
e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey);
mQ.addLast(e);
}
事件注入
private int runMonkeyCycles() {
······
//获取事件
MonkeyEvent ev = mEventSource.getNextEvent();
//注入事件
int injectCode = ev.injectEvent(mWm, mAm, mVerbose);
······
}
Monkey的代码框架
主控模块:主控模块即Monkey类,是入口函数所在类,主要负责参数解析和赋值、初始化运行环境(导入package列表、检查内部配置、申请系统资源、初始化事件源、启动监控等)、执行runMonkeyCycles()方法针对不同的事件源开始获取并执行不同的事件。
监控模块:监控部分包括异常监控和网络监控两部分。异常监控通过ActivityWatch类来实现,主要监控Activity的Crash和ANR事件。网络监控通过MonkeyNetworkMonitor类来实现,主要用于统计运行期间移动网络和Wi-Fi网络的链接时长。
事件源模块:事件源代表不同的事件来源。以MonkeyEventSource为基类,衍生出三个Source类,分别代表网络来源(如Monkeyrunner)、随机事件来源(常规Monkey命令)、脚本来源(通过-f参数指定的脚本)三种事件来源。事件源要做的事情有:从对应来源获取信息,并生成对应的事件,将其插入事件队列中。
事件模块:事件代表了各种用户操作类型。以MonkeyEvent为基类,衍生出各种Event类,每一个Event类代表一种用户操作类型,如常见的点击、输入、滑动事件等。MonkeyEvent抽象类中提供了intinjectEvent()方法,用于执行对应的事件。