Back to project page Cafe.
The source code is released under:
Apache License
If you think the Android project Cafe listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) 2011 Baidu.com Inc//from www . j a v a 2 s . c om * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.baidu.cafe.remote; import java.util.ArrayList; import android.app.Instrumentation; import android.os.SystemClock; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ViewConfiguration; /** * An ui operation lib for testing demand across processes. * * @author luxiaoyu01@baidu.com * @date 2011-8-6 * @version * @todo */ public class UILib { /** * If Arms is signed by platform signature, UILib should use * USE_INSTRUMENTATION. USE_INSTRUMENTATION has better performance than * USE_MONKEY. */ private final static int USE_INSTRUMENTATION = 0; private final static int USE_MONKEY = 1; private final static int EVENT_SENDER = USE_MONKEY; private final static int STEP_COUNT = 100; private final static int SCROLL_TIME_OUT = 120000; private final static int DOWN = 0; private final static int UP = 1; private ViewPropertyProvider mViewPropertyProvider = null; private Instrumentation mInstrumentation = null; public UILib(ViewPropertyProvider viewPropertyProvider) { mViewPropertyProvider = viewPropertyProvider; mInstrumentation = new Instrumentation(); } @Override protected void finalize() throws Throwable { super.finalize(); } /** * simulate key pad using key code * * @param keyCode * the code to be simulated * @param longPress * true if need to press long, else false */ private void keypad(int keyCode, boolean longPress) { switch (EVENT_SENDER) { case USE_INSTRUMENTATION: if (longPress) { mInstrumentation.sendKeySync(KeyEvent.changeFlags(new KeyEvent( KeyEvent.ACTION_DOWN, keyCode), KeyEvent.FLAG_LONG_PRESS)); } else { mInstrumentation.sendKeyDownUpSync(keyCode); } break; case USE_MONKEY: new MonkeyNetwork().key(MonkeyNetwork.DOWN, keyCode); if (longPress) { SystemClock.sleep((int) (ViewConfiguration.getLongPressTimeout() * 1.5f)); } new MonkeyNetwork().key(MonkeyNetwork.UP, keyCode); // new MonkeyNetwork().done(); break; } } /** * check whether the view exist or even has more * * @param searchKey * key property to be dumped * @param searchValue * key value to be dumped * @param searchMode * dumping mode including SEARCHMODE_INCLUDE_MATCHING, * SEARCHMODE_COMPLETE_MATCHING * @param targetNumber * the amount of views you wanna to dump * @return true if the number of the view not less than {targetNumber}, else * false */ public boolean checkView(String searchKey, String searchValue, int searchMode, int targetNumber) { String[] getKeys = { "mID" }; ArrayList<String[]> getValues = mViewPropertyProvider.getViewsProperties(searchKey, searchValue, searchMode, targetNumber, getKeys, true, true); return targetNumber <= getValues.size(); } /** * enter a text by instrumentation * * @param text * the text you wanna to enter */ public void enterText(String text) { switch (EVENT_SENDER) { case USE_INSTRUMENTATION: mInstrumentation.sendStringSync(text); break; case USE_MONKEY: new MonkeyNetwork().type(text); break; } } /** * press a key * * @param keyCode * the key code u wanna to press */ public void pressKey(int keyCode) { keypad(keyCode, false); } /** * press a key long time * * @param keyCode * the key code u wanna to press */ public void longPressKey(int keyCode) { keypad(keyCode, true); } /** * click one dot of a screen * * @param x * the x value of a coordinate * @param y * the y value of a coordinate */ public void clickScreen(int x, int y) { touch(x, x, y, y, 0, 0); } /** * click one dot of a screen long time * * @param x * the x value of a coordinate * @param y * the y value of a coordinate * @param longClickTime * the time length u wanna click */ public void clickLongScreen(int x, int y, int longClickTime) { if (longClickTime < 0) { Log.print("param error: longClickTime < 0"); return; } touch(x, x, y, y, 0, longClickTime); } /** * @param searchKey * key property to be dumped * @param searchValue * key value to be dumped * @param searchMode * dumping mode including SEARCHMODE_INCLUDE_MATCHING, * SEARCHMODE_COMPLETE_MATCHING * @param index * the amount of views you wanna to dump * @param timeout * the time length for clicking * @param xOffset * offset from center X * @param yOffset * offset from center Y * @param longClickTime * touch time length * @param scrollViewId * the given scroll view's id * @param scrollViewIndex * the given scroll view's index level * @return */ public boolean clickView(String searchKey, String searchValue, int searchMode, int index, int timeout, int xOffset, int yOffset, int longClickTime, String scrollViewId, int scrollViewIndex) { if (index < 0 || timeout < 0 || null == searchKey || searchKey.isEmpty() || null == searchValue || longClickTime < 0 || scrollViewIndex < 0) { Log.print("clickView's param error"); return false; } if (scrollViewId != null) { timeout = SCROLL_TIME_OUT; } ArrayList<String[]> getValues; final long endTime = System.currentTimeMillis() + timeout; while (true) { final boolean timedOut = System.currentTimeMillis() > endTime; if (timedOut) { Log.print("click View timeout"); return false; } getValues = mViewPropertyProvider.getViewsProperties(searchKey, searchValue, searchMode, index + 1, new String[] { "coordinate" }, true, true); Log.print("getValues.size():" + getValues.size()); if (getValues.size() > index) { final String[] coordinates = getValues.get(index)[0].split("\\,"); if (scrollViewId != null && !isClickInList(coordinates, scrollViewId, scrollViewIndex)) { Log.print("Scroll half height of scroll view, because target view is not completely visible."); scrollList(DOWN, (float) 0.5, scrollViewId, scrollViewIndex); getValues = mViewPropertyProvider.getViewsProperties(searchKey, searchValue, searchMode, index + 1, new String[] { "coordinate" }, true, true); } break; } if (scrollViewId != null && !scrollList(DOWN, 1, scrollViewId, scrollViewIndex)) { if (index >= getValues.size()) { Log.print("Found Failed:" + searchKey + " = " + searchValue); return false; } break; } getValues.clear(); } final String[] coordinates = getValues.get(index)[0].split("\\,"); int[] centerXY = getCenterXY(coordinates); int centerX = centerXY[0] + xOffset; int centerY = centerXY[1] + yOffset; Log.print("centerX + xOffset = " + centerX); Log.print("centerY + yOffset = " + centerY); touch(centerX, centerX, centerY, centerY, 0, longClickTime); return true; } /** * check whether the given scroll view's center coordinate is in the given * coordinates * * @param coordinates * all of coordinates to be calculated * @param scrollViewId * the given scroll view's id * @param scrollViewIndex * the given scroll view's index level * @return true if the the given scroll view's center coordinate is in the * given coordinates */ private boolean isClickInList(String[] coordinates, String scrollViewId, int scrollViewIndex) { int[] clickXY = getCenterXY(coordinates); String[] xywh = getScrollProperty(scrollViewId, scrollViewIndex, "coordinate", false) .split("\\,"); int scrollViewX = Integer.valueOf(xywh[0]); int scrollViewY = Integer.valueOf(xywh[1]); int scrollViewWidth = Integer.valueOf(xywh[2]); int scrollViewHeight = Integer.valueOf(xywh[3]); if (scrollViewX < clickXY[0] && clickXY[0] < scrollViewX + scrollViewWidth && scrollViewY < clickXY[1] && clickXY[1] < scrollViewY + scrollViewHeight) { return true; } return false; } /** * get center coordinate of the given coordinates * * @param coordinates * all of coordinates to be calculated * @return the center coordinate */ private int[] getCenterXY(String[] coordinates) { int[] centerXY = new int[2]; int x = Integer.valueOf(coordinates[0]); int y = Integer.valueOf(coordinates[1]); int width = Integer.valueOf(coordinates[2]); int height = Integer.valueOf(coordinates[3]); int centerX = x + width / 2; int centerY = y + height / 2; centerXY[0] = centerX; centerXY[1] = centerY; return centerXY; } /** * drag from X to Y * * @param fromX * the x value of the original dot * @param toX * the x value of the destination dot * @param fromY * the y value of the original value * @param toY * the y value of the destination dot * @param stepCount * the step to touch from X to Y * @return */ public void drag(float fromX, float toX, float fromY, float toY, int stepCount) { Log.print("scroll from (" + (int) fromX + "," + (int) fromY + ") to (" + (int) toX + "," + (int) toY + ")"); touch(fromX, toX, fromY, toY, stepCount, 0); } /** * touch screen including two ways: instrumentation or native event * * @param fromX * the x value of the original dot * @param toX * the x value of the destination dot * @param fromY * the y value of the original value * @param toY * the y value of the destination dot * @param stepCount * the step to touch from X to Y * @param longClickTime * touch time length */ private void touch(float fromX, float toX, float fromY, float toY, int stepCount, int longClickTime) { switch (EVENT_SENDER) { case USE_INSTRUMENTATION: touchUseInstrumentation(fromX, toX, fromY, toY, stepCount, longClickTime); break; case USE_MONKEY: touchUseMonkey(fromX, toX, fromY, toY, stepCount, longClickTime); break; } } /** * touch screen from X to Y continually, maybe many steps according to your * params * * @param fromX * the x value of the original dot * @param toX * the x value of the destination dot * @param fromY * the y value of the original value * @param toY * the y value of the destination dot * @param stepCount * the step to touch from X to Y * @param longClickTime * touch time length */ private void touchUseInstrumentation(float fromX, float toX, float fromY, float toY, int stepCount, int longClickTime) { if (stepCount > 0 && longClickTime > 0) { Log.print("touchUseInstrumentation's param error: stepCount > 0 && longClickTime > 0"); } long downTime = SystemClock.uptimeMillis(); long eventTime = SystemClock.uptimeMillis(); float x = fromX; float y = fromY; float xStep = 0; float yStep = 0; if (stepCount > 0) { xStep = (toX - fromX) / stepCount; yStep = (toY - fromY) / stepCount; } mInstrumentation.sendPointerSync(MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0)); for (int i = 0; i < stepCount; ++i) { y += yStep; x += xStep; eventTime = SystemClock.uptimeMillis(); mInstrumentation.sendPointerSync(MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0)); } if (longClickTime > 0) { mInstrumentation.sendPointerSync(MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0)); SystemClock.sleep(longClickTime); } eventTime = SystemClock.uptimeMillis(); mInstrumentation.sendPointerSync(MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0)); } /** * touch screen using native event * * @param fromX * the x value of the original dot * @param toX * the x value of the destination dot * @param fromY * the y value of the original value * @param toY * the y value of the destination dot * @param stepCount * the step to touch from X to Y * @param longClickTime * touch time length */ private void touchUseMonkey(float fromX, float toX, float fromY, float toY, int stepCount, int longClickTime) { if (stepCount > 0 && longClickTime > 0) { Log.print("touchUseInstrumentation's param error: stepCount > 0 && longClickTime > 0"); } int x = (int) fromX; int y = (int) fromY; float xStep = 0; float yStep = 0; if (stepCount > 0) { xStep = (toX - fromX) / stepCount; yStep = (toY - fromY) / stepCount; } new MonkeyNetwork().touch(MonkeyNetwork.DOWN, x, y); for (int i = 0; i < stepCount; ++i) { y += yStep; x += xStep; new MonkeyNetwork().touch(MonkeyNetwork.MOVE, x, y); } if (longClickTime > 0) { new MonkeyNetwork().touch(MonkeyNetwork.MOVE, x, y); SystemClock.sleep(longClickTime); } new MonkeyNetwork().touch(MonkeyNetwork.UP, x, y); // new MonkeyNetwork().done(); } /** * @param direction * scroll direction * @param scrollDistance * scroll distance that how many height of scrollView * @param scrollViewId * id of scrollView * @param scrollViewIndex * index of the same id * @return true if more scrolling can be done */ public boolean scrollList(int direction, float scrollDistance, String scrollViewId, int scrollViewIndex) { String[] xywh = getScrollProperty(scrollViewId, scrollViewIndex, "coordinate", false) .split("\\,"); int x = Integer.valueOf(xywh[0]); int y = Integer.valueOf(xywh[1]); int width = Integer.valueOf(xywh[2]); int height = Integer.valueOf(xywh[3]); int centerX = x + width / 2; int scrollAmount = getScrollAmount(scrollViewId, scrollViewIndex, false); if (direction == DOWN) { drag(centerX, centerX, (y + height - 1) * scrollDistance, y + 1, STEP_COUNT); } else if (direction == UP) { drag(centerX, centerX, y + 1, (y + height - 1) * scrollDistance, STEP_COUNT); } return getScrollAmount(scrollViewId, scrollViewIndex, true) == scrollAmount ? false : true; } /** * get the amount of the scroll * * @param scrollViewId * the given scroll view's id * @param scrollViewIndex * the given scroll view's index level * @param getNew * true if the view is already dumped, else false * @return the amount of the scroll */ private int getScrollAmount(String scrollViewId, int scrollViewIndex, boolean getNew) { int scrollAmount = 0; String mFirstPosition = getScrollProperty(scrollViewId, scrollViewIndex, "mFirstPosition", getNew); String mScrollY = getScrollProperty(scrollViewId, scrollViewIndex, "mScrollY", getNew); if (null == mFirstPosition) { // scrollview scrollAmount = Integer.valueOf(mScrollY); } else { // listview gridview scrollAmount = Integer.valueOf(mFirstPosition); } return scrollAmount; } /** * get scroll view's properties including its x and y value, and its height * and with * * @param scrollViewId * the given scroll view's id * @param scrollViewIndex * the given scroll view's index level * @param getKey * what the keys u wanna to get its properties * @param getNew * true if the view is already dumped, else false * @return the given scroll view's properties */ private String getScrollProperty(String scrollViewId, int scrollViewIndex, String getKey, boolean getNew) { return mViewPropertyProvider.getViewsProperties("mID", scrollViewId, ViewPropertyProvider.SEARCHMODE_COMPLETE_MATCHING, scrollViewIndex + 1, new String[] { getKey }, getNew, true).get(scrollViewIndex)[0]; } }