上一篇文章中讲了bootstrap的工作流程,这篇文章开始来研究一下bootstrap可以接受哪些指令(从源码的角度来看,由于appium的项目现在还处在持续更新中,所以有的指令已经实现,某些或许未来会实现,从源码来看的好处是你知道以后或许未来appium能做到哪些功能)。
在bootstrap项目中的io.appium.android.bootstrap.handler包中的类都是对应的相应的指令的类,里面都有execute方法来执行命令。先上上一篇文章中讲的map。
private static HashMap<String, CommandHandler> map = new HashMap<String, CommandHandler>(); static { map.put("waitForIdle", new WaitForIdle()); map.put("clear", new Clear()); map.put("orientation", new Orientation()); map.put("swipe", new Swipe()); map.put("flick", new Flick()); map.put("drag", new Drag()); map.put("pinch", new Pinch()); map.put("click", new Click()); map.put("touchLongClick", new TouchLongClick()); map.put("touchDown", new TouchDown()); map.put("touchUp", new TouchUp()); map.put("touchMove", new TouchMove()); map.put("getText", new GetText()); map.put("setText", new SetText()); map.put("getName", new GetName()); map.put("getAttribute", new GetAttribute()); map.put("getDeviceSize", new GetDeviceSize()); map.put("scrollTo", new ScrollTo()); map.put("find", new Find()); map.put("getLocation", new GetLocation()); map.put("getSize", new GetSize()); map.put("wake", new Wake()); map.put("pressBack", new PressBack()); map.put("dumpWindowHierarchy", new DumpWindowHierarchy()); map.put("pressKeyCode", new PressKeyCode()); map.put("longPressKeyCode", new LongPressKeyCode()); map.put("takeScreenshot", new TakeScreenshot()); map.put("updateStrings", new UpdateStrings()); map.put("getDataDir", new GetDataDir()); map.put("performMultiPointerGesture", new MultiPointerGesture()); map.put("openNotification", new OpenNotification()); }
我们就按照上面的顺序来讲。首先声明一点,事先了解一下uiautomator的api很有必要,因为这些指令中大多数都是调用uiautomator的方法去操作的,要么直接调用,要么反射调用。我的博客有很多关于这方面的文章,可以先去看看。
package io.appium.android.bootstrap.handler; import com.android.uiautomator.core.UiDevice; import com.android.uiautomator.core.UiObjectNotFoundException; import io.appium.android.bootstrap.*; import org.json.JSONException; import java.util.ArrayList; import java.util.Hashtable; /** * This handler is used to click elements in the Android UI. * * Based on the element Id, click that element. * */ public class Click extends CommandHandler { /* * @param command The {@link AndroidCommand} * * @return {@link AndroidCommandResult} * * @throws JSONException * * @see io.appium.android.bootstrap.CommandHandler#execute(io.appium.android. * bootstrap.AndroidCommand) */ @Override public AndroidCommandResult execute(final AndroidCommand command) throws JSONException { if (command.isElementCommand()) { try { final AndroidElement el = command.getElement(); el.click(); return getSuccessResult(true); } catch (final UiObjectNotFoundException e) { return new AndroidCommandResult(WDStatus.NO_SUCH_ELEMENT, e.getMessage()); } catch (final Exception e) { // handle NullPointerException return getErrorResult("Unknown error"); } } else { final Hashtable<String, Object> params = command.params(); final Double[] coords = { Double.parseDouble(params.get("x").toString()), Double.parseDouble(params.get("y").toString()) }; final ArrayList<Integer> posVals = absPosFromCoords(coords); final boolean res = UiDevice.getInstance().click(posVals.get(0), posVals.get(1)); return getSuccessResult(res); } } }
控件
如果是控件的话,首先会获得命令中的控件对象,然后调用click方法,我们进入click方法看看
AndroidElement.java
public boolean click() throws UiObjectNotFoundException { return el.click(); }
private final UiObject el;
return getSuccessResult(true);
从字面意思来看,走到这一步肯定就是告诉调用者,我只想成功了,跟你说一声。然后我们来看看这个方法里面的具体实现。
/** * Returns success along with the payload. * * @param value * @return {@link AndroidCommandResult} */ protected AndroidCommandResult getSuccessResult(final Object value) { return new AndroidCommandResult(WDStatus.SUCCESS, value); }
SUCCESS (0, "The command executed successfully."),
JSONObject json; public AndroidCommandResult(final WDStatus status, final Object val) { json = new JSONObject(); try { json.put("status", status.code()); json.put("value", val); } catch (final JSONException e) { Logger.error("Couldn't create android command result!"); } }
坐标
如果是坐标的话,程序会获得命令里的坐标参数,保存在Double数组中。
final Hashtable<String, Object> params = command.params(); final Double[] coords = { Double.parseDouble(params.get("x").toString()), Double.parseDouble(params.get("y").toString()) };
/** * Given a position, it will return either the position based on percentage * (by passing in a double between 0 and 1) or absolute position based on the * coordinates entered. * * @param coordVals * @return ArrayList<Integer> */ protected static ArrayList<Integer> absPosFromCoords(final Double[] coordVals) { final ArrayList<Integer> retPos = new ArrayList<Integer>(); final UiDevice d = UiDevice.getInstance(); final Double screenX = (double) d.getDisplayWidth(); final Double screenY = (double) d.getDisplayHeight(); if (coordVals[0] < 1 && coordVals[1] < 1) { retPos.add((int) (screenX * coordVals[0])); retPos.add((int) (screenY * coordVals[1])); } else { retPos.add(coordVals[0].intValue()); retPos.add(coordVals[1].intValue()); } return retPos; }
经过上面的一番操作以后,会得到确切坐标值保存在数组中返回。
然后程序调用UiDevice的click方法点击啦:
final boolean res = UiDevice.getInstance().click(posVals.get(0), posVals.get(1));
bootstrap之Click事件,布布扣,bubuko.com
原文:http://blog.csdn.net/itfootball/article/details/37921869