Android monkey改造分析 (base uiautomation)

(1)看monkey就要看它底层如何触发操作,下面列举了几个send MotionEvent 的方法。

我们可以看到包括monkey和一些自动化框架都是基于什么去操作页面的。

Send Event

1.Monkey

MotionEvent me = getEvent();
InputManager.getInstance().injectInputEvent(me, 1)

2.Instrumentation

Instrumentation inst = new Instrumentation();
inst.sendPointerSync

3.Uiautomation

mUiAutomation.injectInputEvent

 

(2)改造

1.保留monkey的event分发机制

 

public MonkeySourceRandom(Random random, ArrayList<ComponentName> MainApps,
            long throttle, boolean randomizeThrottle, Display display) {
        // default values for random distributions
        // note, these are straight percentages, to match user input (cmd line
        // args)
        // but they will be converted to 0..1 values before the main loop runs.
        mFactors[FACTOR_TOUCH] = 47.0f;
        mFactors[FACTOR_MOTION] = 10.0f;
        mFactors[FACTOR_TRACKBALL] = 30.0f;
        mFactors[FACTOR_NAV] = 0.0f;
        mFactors[FACTOR_MAJORNAV] = 5.0f;
        mFactors[FACTOR_SYSOPS] = 2.0f;
        mFactors[FACTOR_APPSWITCH] = 0.0f;
        mFactors[FACTOR_FLIP] = 1.0f;
        mFactors[FACTOR_ANYTHING] = 3.0f;
        mFactors[FACTOR_PINCHZOOM] = 2.0f;

        mRandom = random;
        mMainApps = MainApps;
        mQ = new MonkeyEventQueue(random, throttle, randomizeThrottle);
        mDisplay = display;
    }

 

    private void generateEvents() {
        float cls = mRandom.nextFloat();
        int lastKey = 0;

        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;
        }

 

2.由于InputManager在安卓中无法直接调用,所以我们可以用Instrumentation或者Uiautomation去做操作。

再一步分析Instrumentation的Send Event只能基于app本身去操作(安卓权限问题,如果操作其他应用需要系统权限)

我们可以直接用uiautomator2.0,通过instrumentation获取Uiautomation

 this.mInstrumentation = instrumentation;
        this.mUiDevice = UiDevice.getInstance(instrumentation);

调用:

public boolean injectInputEvent(InputEvent event, boolean sync) {
        synchronized (mLock) {
            throwIfNotConnectedLocked();
        }
        try {
            if (DEBUG) {
                Log.i(LOG_TAG, "Injecting: " + event + " sync: " + sync);
            }
            // Calling out without a lock held.
            return mUiAutomationConnection.injectInputEvent(event, sync);
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error while injecting input event!", re);
        }
        return false;
    }

 

 3.改进

1.例如点击区域

2.点击方式

3.去掉一些无意义的keyevent

4.增加一些监听,例如页面死循环监听(图片对比),activity切换监听

 

posted @ 2017-01-21 21:30  q55091  阅读(770)  评论(2编辑  收藏  举报