appium源码分析(八)-touch

摘要

这次主要分析的对象时touch功能,如touchMove、touchUp、touchDown、touchLongClick。查看这些源代码的时候你会发现,他们都是继承于TouchEvent的这个类,并且execute的方法也是在TouchEvent里面实现的,所以我们有必要去看看touchEvent这个基类里面实现了那些内容

正文

说白了,touch类的操作也是分为两种,一种就是坐标的操作,一种是针对于元素的操作,了解了这个我们就好更清楚的明白touchEvent的代码实现了。

public AndroidCommandResult execute(final AndroidCommand command)
      throws JSONException {
    initalize();
    try {
      params = command.params();

      // isElementCommand doesn't check to see if we actually have an element
      // so getElement is used instead.
      try {
        if (command.getElement() != null) {
          isElement = true;
        }
      } catch (final Exception e) {
        isElement = false;
      }

      if (isElement) {
        // extract x and y from the element.
        el = command.getElement();

        // check if element exists without wait
        if(! el.exists()) {
          throw new UiObjectNotFoundException("TouchEvent element does not exist.");
        }

        final Rect bounds = el.getVisibleBounds();
        clickX = bounds.centerX();
        clickY = bounds.centerY();
      } else { // no element so extract x and y from params
        final Object paramX = params.get("x");
        final Object paramY = params.get("y");

        // these will be defaulted to 0.5 when passed to getDeviceAbsPos
        double targetX = 0;
        double targetY = 0;

        if (paramX != null) {
          targetX = Double.parseDouble(paramX.toString());
        }

        if (paramY != null) {
          targetY = Double.parseDouble(paramY.toString());
        }

        Point coords = new Point(targetX, targetY);
        coords = PositionHelper.getDeviceAbsPos(coords);

        clickX = coords.x.intValue();
        clickY = coords.y.intValue();
      }

      if (executeTouchEvent()) {
        return getSuccessResult(true);
      }

    } catch (final UiObjectNotFoundException e) {
      return new AndroidCommandResult(WDStatus.NO_SUCH_ELEMENT, e.getMessage());
    } catch (final InvalidCoordinatesException e) {
      return new AndroidCommandResult(WDStatus.INVALID_ELEMENT_COORDINATES, 
          e.getMessage());
    } catch (final Exception e) {
      return getErrorResult(e.getMessage());
    }
    return getErrorResult("Failed to execute touch event");
  }

  protected abstract boolean executeTouchEvent()
      throws UiObjectNotFoundException;

以上的一些步骤实际上之前的都有类似的分析过首先判断command是否是针对于元素操作的命令。

-非元素操作:获取param中的x,y坐标值转换成double类型的坐标,再将坐标值转换成point的对象后最后通过getDeviceAbsPos方法转换成相对的设备的坐标。执行抽象方法executeTouchEvent()
-元素操作:获取到元素的可见矩形区域后,直接获取元素的中点坐标即可。执行抽象方法executeTouchEvent()

我们这里就看看TouchLongClick吧,因为

protected boolean executeTouchEvent() throws UiObjectNotFoundException {
    final Object paramDuration = params.get("duration");
    int duration = 2000; // two seconds
    if (paramDuration != null) {
      duration = Integer.parseInt(paramDuration.toString());
    }

    printEventDebugLine("TouchLongClick", duration);
    if (correctLongClick(clickX, clickY, duration)) {
      return true;
    }
    // if correctLongClick failed and we have an element
    // then uiautomator's longClick is used as a fallback.
    if (isElement) {
      Logger.debug("Falling back to broken longClick");

      return el.longClick();
    }
    return false;
  }

这里首先先获取到参数里面的持续时间,再来调用correctLongClick方法

InteractionController interactionController = UiAutomatorBridge.getInstance().getInteractionController();

if (interactionController.touchDown(x, y)) {
  SystemClock.sleep(duration);
  if (interactionController.touchUp(x, y)) {
    return true;
  }
}

这里实际上通过反射调用了interactionController中的touchDown以及touchUp。实际上到这里我们是不是就结束了呢。实际上并没有,我们再继续看下executeTouchEvent的代码

// if correctLongClick failed and we have an element
// then uiautomator's longClick is used as a fallback.
if (isElement) {
  Logger.debug("Falling back to broken longClick");

  return el.longClick();
}

实际上下面还有这句,看看注释,说的是,如果correctLongClick 失败了,并且我们是有一个元素的时候,我们可以使用uiautomator的longclick方法。
那我们再看看uiautomator里面的longclick跟我们correctLongClick 的区别是什么

**
* Touches down for a long press at the specified coordinates.
*
* @param x
* @param y
* @return true if successful.
*/
public boolean longTapNoSync(int x, int y) {
   if (DEBUG) {
       Log.d(LOG_TAG, "longTapNoSync (" + x + ", " + y + ")");
   }

   if (touchDown(x, y)) {
       SystemClock.sleep(mUiAutomatorBridge.getSystemLongPressTime());
       if(touchUp(x, y)) {
           return true;
       }
   }
   return false;
}

以上就是uiautomator关于longclick的代码了。乍一看咦 这个不是跟我们correctLongClick 的方法一模一样吗?为什么appium又要重复造轮子,重新写一遍呢。这明显不是他们的作风啊。
我们再回到前面TouchEvent里面看看,想想一开始的时候做了什么判断吗?
哦对了。我们首先判断这个操作的对象是个元素还是坐标对吧,但是我们再看看UiAutomator里面的longclick,这个方法是只属于UiObject的。这一想就明白了。appium对touch做了扩展,让其能够即支持坐标又支持元素。这下子是不是就清晰很多了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值