上一篇文章中講了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的方法去操作的,要么直接調用,要么反射調用。我的博客有很多關于這方面的文章,可以先去看看。
# click
~~~
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();
}
~~~
e1的定義為
~~~
private final UiObject el;
~~~
說明最終調用的是uiautomator中的UiObject類的click方法,這個方法的click方法就是點擊該控件的中心點。然后回到Click類中繼續往下看,會調用
~~~
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);
}
~~~
創建AndroidCommandResult新對象,傳入WDStatus.SUCCESS,和value(我們這里傳入的值為true).首先看一下SUCCESS的值,該值存放在枚舉類WDStatus中。
~~~
SUCCESS (0, "The command executed successfully."),
~~~
就是一行文本。好,下面進入AndroidCommandResult類的構造方法里。
~~~
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!");
}
}
~~~
構造方法里把傳入的參數保存在了json對象中,以鍵值對的形式。好了,條件為控件的情況分析結束,下面開始分析坐標。
**坐標**
如果是坐標的話,程序會獲得命令里的坐標參數,保存在Double數組中。
~~~
final Hashtable<String, Object> params = command.params();
final Double[] coords = { Double.parseDouble(params.get("x").toString()),
Double.parseDouble(params.get("y").toString()) };
~~~
接下來會通過absPosFromCoords方法將Double轉換為List。所以下面來看absPosFromCoords方法的實現:
~~~
/**
* 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;
}
~~~
首先會判斷傳入的坐標是以百分比的形式還是以坐標的形式。如果是百分比說明你傳入的不是絕對坐標,而是相對坐標(可以這么理解吧,這樣可以適應各個屏幕),這種情況你就需要獲取屏幕的尺寸,然后和百分比做計算得到當前屏幕中你所要點擊的坐標點。如果你傳入的就是坐標,那就直接將Double類型的值轉化為Int的值。
經過上面的一番操作以后,會得到確切坐標值保存在數組中返回。
然后程序調用UiDevice的click方法點擊啦:
~~~
final boolean res = UiDevice.getInstance().click(posVals.get(0), posVals.get(1));
~~~
最后返回一個成功的AndroidCommandResult對象。
- 前言
- appium框架之bootstrap
- bootstrap之Click事件
- bootstrap之WaitForIdle&&Clear
- bootstrap之Orientation
- bootstrap之Swipe
- bootstrap之Flick
- bootstrap之Drag
- bootstrap之Pinch
- bootstrap之鼠標操作
- bootstrap之文本框的操作
- bootstrap之GetName&&GetAttribute&&GetDeviceSize&&GetSize&&GetLocation&&GetDataDir
- bootstrap之ScrollTo
- bootstrap之Wake&&PressBack&&TakeScreenshot&&OpenNotification
- bootstrap之PressKeyCode&&LongPressKeyCode
- bootstrap之DumpWindowHierarchy
- bootstrap之UpdateStrings
- bootstrap之MultiPointerGesture