您好,登录后才能下订单哦!
本系列的上一篇文章《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 扫描码:     |      
 免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。 相关阅读 |