monkey

作者: 轻情 | 来源:发表于2017-03-01 10:11 被阅读22次

    1. adb shell monkey -p com.v1.pakage --throttle 360 --ignore-crashes --monitor-native-crashes --ignore-security-exceptions --ignore-timeouts --ignore-native-crashes --pct-syskeys 0 --pct-nav 0 --pct-majornav 20 --pct-touch 60 --pct-appswitch 20 -v -v -v 25000 >d:\liulian_MonkeyLog.txt

    adb shell bugreport >d:\Bugreport_liulian.txt

    2. app包名查看:

    a.手机安装包名查看器'

    b.aapt命令aapt dump badging *.apk

    c、源码下的AndroidManifest.xml文件查看

    d.adb logcat抓取当前Android机运行的app的包名(  I/ActivityManager(数字): Displayed 包名/类

    名: +ms )

    命令行输入 adb logcat >e:\bag.txt

    手机操控app,ctrl+c停止

    去e:\bag.txt这个文件下搜索关键字如Displayed ,一般都能找到

    这两天在读Android Monkey的源代码.代码不多,放出分享.

    我现说一下,Monkey是干什么的:简单的说就是,模拟用户的touch screen和keyboard的输入.其实这个功能就已经很恐怖了.  Google自己说的下面:

    // Only bind this to local host.  This means that you can only

    // talk to the monkey locally, or though adb port forwarding.

    就是觊觎这个强大的力量.Monkey是用JAVA写成的,但是我们确可以这样运行:

    $adb shell monkey ......

    这是为什么呢?是因为在/system/bin目录下有一个monkey的shell脚本.内容如下:

    # Script to start "monkey" on the device, which has a very rudimentary

    # shell.

    #

    base=/system

    export CLASSPATH=$base/framework/monkey.jar

    exec app_process $base/bin com.android.commands.monkey.Monkey $*

    exec 会运行起/system/framework/monkey.jar这只Java程序.后面我们还会用到这个脚本.

    先给出Monkey的架构图:

    又是我的手绘图.哈哈.实际上,并不复杂.

    Monkey.java 里面有main()函数.而main()->Run().Run()里面作了下面的操作:

    1.processOptions()初始化参数(通过传入入参来初始化参数).还有一些的操作函数如:nextOption() nextOptionLong()。。

    2.做接口的检查,也就是申请这些接口资源.

    3.关键的一步:

    if(mServerPort!=1)

    { try{

    mEventSource = new MonkeySourceNetWork(mServerPort);

    ...省略

    开始ServerSocket.监听用户输入的command.

    4.mNetworkMonitor.Start();开始监控网络状态

    5.关键的一步:

    runMonkeyCycles(),代码如下:

    while()

    {

    MonkeyEvent ev = mEventSource.getNextEvent();

    ev.inject(....);

    ...省略

    开始Event loop,把每个CommandQueue中的消息都执行.

    6.mNetworkMonitor.Stop()

    这里我们看到使用了SocketServer,所以理论上来说,可以在PC端发送command给device,但是必须透过USB的连接.这点我在上面已经说的很清楚了.(PC端,Android不可能帮你实现,我们只要在PC端使用Socket向device发送命令就可以了).

    好了,我们接着往下分析:

    MonkeyEvent的实现是典型的OO思想.

    MonkeyEvent.java仅仅是一个abstract class.

    最重要的方法都由子类去实现.(把Event放入当前的Activity去运行)

    public abstract int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose);

    monkey*Event.java都是MonkeyEvent.java的子类.

    来讲一下,MonkeySourceNetwork.java.

    这个类相对较大,里面有许多的内嵌类.(ps. 我不是写Java出身的,看到内嵌类就不符合我的审美习惯)

    1.有一个MonkeyCommand的类,这是一个interface. *Command都是他的子类.

    其中定义了一个很重要的方法:这个方法将string 类型的command转换为MonkeyEvent对象,并放入

    commandQueue.

    MonkeyCommandReturn translateCommand(List command, CommandQueue queue);

    好了,首先MonkeyCommandReturn又是一个类,是命令执行成功还是失败的一个类.

    commandQueue是实际上是一个interface,然后它的实现是在CommandQueueImpl这个类中.

    实现了如下的方法:

    public void enqueueEvent(MonkeyEvent e) {

    queuedEvents.offer(e);

    }

    将Event放入queueEvents队列中.而queueEvents是这样定义的:

    private final Queue queuedEvents = new LinkedList();

    无非就是一个LinkedList而已拉.

    2.下面我在来说说MonkeySourceNetwork类中的方法:

    private void translateCommand(String commandLine)

    和上面的方法同名.实际上这个translateCommand是上面的封装.我们来RTFS:

    List parts = commandLineSplit(commandLine);

    if (parts.size() > 0) {

    MonkeyCommand command = COMMAND_MAP.get(parts.get(0));

    if (command != null) {

    MonkeyCommandReturn ret = command.translateCommand(parts,commandQueue);

    COMMAND_MAP这是个什么东西呢?

    private static final Map COMMAND_MAP = new HashMap();

    看了没,是一个Map.以Command string作为Key, MonkeyCommand作为Value.这样的话,就建立了,

    输入的命令和Command的关系。

    static {

    // Add in all the commands we support

    COMMAND_MAP.put("flip", new FlipCommand());

    COMMAND_MAP.put("touch", new TouchCommand());

    COMMAND_MAP.put("trackball", new TrackballCommand());

    COMMAND_MAP.put("key", new KeyCommand());

    COMMAND_MAP.put("sleep", new SleepCommand());

    COMMAND_MAP.put("wake", new WakeCommand());

    COMMAND_MAP.put("tap", new TapCommand());

    COMMAND_MAP.put("press", new PressCommand());

    COMMAND_MAP.put("type", new TypeCommand());

    COMMAND_MAP.put("listvar", new MonkeySourceNetworkVars.ListVarCommand());

    COMMAND_MAP.put("getvar", new MonkeySourceNetworkVars.GetVarCommand());

    }

    但也不是所有的命令都放入COMMAND_MAP中.quit 和 done 就是例外,原因也很简单,没必要放进Map.

    再来分析下这条语句:MonkeyCommandReturn ret = command.translateCommand(parts,commandQueue);

    首先,command已经是MonkeyCommand的sub class了.so 调用translateCommand将会表现出不同的行为.

    例如,command假设为PressCommand.则translateCommand的表现为:

    queue.enqueueEvent(new MonkeyKeyEvent(....))

    每一个MonkeyEvent又都代表了一些对AP GUI错作.所以,也就是把操作放入了Queue.

    okay.就这么多了.才不多这次就说这么多吧.我再附上我的手绘图,希望有帮助.

    相关文章

      网友评论

        本文标题:monkey

        本文链接:https://www.haomeiwen.com/subject/ejrqgttx.html