手机自动化测试:appium源码分析之bootstrap十七

手机自动化测试:appium源码分析之bootstrap十七

 

   

   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标。如果对课程感兴趣,请大家咨询qq:908821478。

MultiPointerGesture

package io.appium.android.bootstrap.handler;

import android.view.MotionEvent.PointerCoords;

import com.android.uiautomator.common.ReflectionUtils;

import io.appium.android.bootstrap.*;

import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;

import java.lang.reflect.Method;

import static io.appium.android.bootstrap.utils.API.API_18;

public class MultiPointerGesture extends CommandHandler {

  private double computeLongestTime(final JSONArray actions)

      throws JSONException {

    double max = 0.0;

    for (int i = 0; i < actions.length(); i++) {

      final JSONArray gestures = actions.getJSONArray(i);

      final double endTime = gestures.getJSONObject(gestures.length() - 1)

          .getDouble("time");

      if (endTime > max) {

        max = endTime;

      }

    }

    return max;

  }

  private PointerCoords createPointerCoords(final JSONObject obj)

      throws JSONException {

    final JSONObject o = obj.getJSONObject("touch");

    final int x = o.getInt("x");

    final int y = o.getInt("y");

    final PointerCoords p = new PointerCoords();

    p.size = 1;

    p.pressure = 1;

    p.x = x;

    p.y = y;

    return p;

  }

  @Override

  public AndroidCommandResult execute(final AndroidCommand command)

      throws JSONException {

    try {

      final PointerCoords[][] pcs = parsePointerCoords(command);

      if (command.isElementCommand()) {

        final AndroidElement el = command.getElement();

        if (el.performMultiPointerGesture(pcs)) {

          return getSuccessResult("OK");

        } else {

          return getErrorResult("Unable to perform multi pointer gesture");

        }

      } else {

        if (API_18) {

          final ReflectionUtils utils = new ReflectionUtils();

          final Method pmpg = utils.getControllerMethod("performMultiPointerGesture",

              PointerCoords[][].class);

          final Boolean rt = (Boolean) pmpg.invoke(utils.getController(),

              (Object) pcs);

          if (rt) {

            return getSuccessResult("OK");

          } else {

            return getErrorResult("Unable to perform multi pointer gesture");

          }

        } else {

          Logger.error("Device does not support API < 18!");

          return new AndroidCommandResult(WDStatus.UNKNOWN_ERROR,

              "Cannot perform multi pointer gesture on device below API level 18");

        }

      }

    } catch (final Exception e) {

      Logger.debug("Exception: " + e);

      e.printStackTrace();

      return new AndroidCommandResult(WDStatus.UNKNOWN_ERROR, e.getMessage());

    }

  }

  private PointerCoords[] gesturesToPointerCoords(final double maxTime,

      final JSONArray gestures) throws JSONException {

    // gestures, e.g.:

    // [

    // {"touch":{"y":529.5,"x":120},"time":0.2},

    // {"touch":{"y":529.5,"x":130},"time":0.4},

    // {"touch":{"y":454.5,"x":140},"time":0.6},

    // {"touch":{"y":304.5,"x":150},"time":0.8}

    // ]

    // From the docs:

    // "Steps are injected about 5 milliseconds apart, so 100 steps may take

    // around 0.5 seconds to complete."

    final int steps = (int) (maxTime * 200) + 2;

    final PointerCoords[] pc = new PointerCoords[steps];

    int i = 1;

    JSONObject current = gestures.getJSONObject(0);

    double currentTime = current.getDouble("time");

    double runningTime = 0.0;

    final int gesturesLength = gestures.length();

    for (int j = 0; j < steps; j++) {

      if (runningTime > currentTime && i < gesturesLength) {

        current = gestures.getJSONObject(i++);

        currentTime = current.getDouble("time");

      }

      pc[j] = createPointerCoords(current);

      runningTime += 0.005;

    }

    return pc;

  }

  private PointerCoords[][] parsePointerCoords(final AndroidCommand command)

      throws JSONException {

    final JSONArray actions = (org.json.JSONArray) command.params().get(

        "actions");

    final double time = computeLongestTime(actions);

    final PointerCoords[][] pcs = new PointerCoords[actions.length()][];

    for (int i = 0; i < actions.length(); i++) {

      final JSONArray gestures = actions.getJSONArray(i);

      pcs[i] = gesturesToPointerCoords(time, gestures);

    }

    return pcs;

  }

}

多点触控根据你传递过来的参数决定,如果参数是一个控件元素,那么就要调用performMultiPointerGesture方法,如果参数是一系列的点,那么就要调用反射。那么具体来看看2个方法细节。

控件

performMultiPointerGesture

public boolean performMultiPointerGesture(PointerCoords[] ...touches) {

    try {

      if (API_18) {

        // The compile-time SDK expects the wrong arguments, but the runtime

        // version in the emulator is correct. So we cannot do:

        //   `return el.performMultiPointerGesture(touches);`

        // Instead we need to use Reflection to do it all at runtime.

        Method method = this.el.getClass().getMethod("performMultiPointerGesture", PointerCoords[][].class);

        Boolean rt = (Boolean)method.invoke(this.el, (Object)touches);

        return rt;

      } else {

        Logger.error("Device does not support API < 18!");

        return false;

      }

    } catch (final Exception e) {

      Logger.error("Exception: " + e + " (" + e.getMessage() + ")");

      return false;

    }

  }

UiObject中有直接可以调用的performMultiPointerGesture方法,为什么还要用反射呢。上面的方法里的注释是这样解释的:编译的时候sdk会认为参数是错误的,但是运行时却认为是正确的,所以只有在运行时调用才能保证正确性。反射调用的就是运行时的环境,所以它使用了反射调用了performMultiPointerGesture。

点组

在api18以上的版本中才有传点组的方法可调用,所以先判断sdk的版本。如果api在18以上,那么就要调用InteractionController..performMultiPointerGesture的方法来执行

原文地址:https://www.cnblogs.com/poptest/p/4953542.html