Uiautomator界面中存在的控件,但是无法被点击的问题解决

在Android P出来后,开展自动化测试的路上一些地方有些磕磕绊绊。先说说之前发现的一种必现的无法点击到桌面控件的问题,明明界面中存在,但是无法被点击,Uiautomator运行时并没有抛出这一步的异常,但是下一步就抛异常了。

详细的实例如下:case删除全部联系人的操作步骤(点击删除--选择确定--验证是否正确删除)

而因为无法点击到删除这个控件,导致没有弹出确认窗口,导致下一步的点击“确定”按钮这一步抛UiObjectNotFound异常。


    @Test
    public void testCase() throws UiObjectNotFoundException {
        UiObject deleteBtn=new UiObject(new UiSelector().text("删除"));//未正确点击,但未抛出异常
        deleteBtn.click();
        UiObject okBtn=new UiObject(new UiSelector().text("确定"));//抛异常
        okBtn.click();
    }

那么,接下来,分析下,为什么出错了。使用UiautomatorViewer同步快照后,发现删除按钮被截取掉一部分了。

可见,控件确实存在,但是其中有一部分被干掉了,整个屏幕被切割掉了一小部分。

从Uiautomator源码中,我们可以知道,Uiautomator其实获取控件后,会获取该控件的中心点坐标,随后点击坐标,从而实现点击控件。上源码:

UiObject类的click()方法:

/**
     * Performs a click at the center of the visible bounds of the UI element represented
     * by this UiObject.
     *
     * @return true id successful else false
     * @throws UiObjectNotFoundException
     * @since API Level 16
     */
    public boolean click() throws UiObjectNotFoundException {
        Tracer.trace();
        AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
        if(node == null) {
            throw new UiObjectNotFoundException(mUiSelector.toString());
        }
        Rect rect = getVisibleBounds(node);
        return getInteractionController().clickAndSync(rect.centerX(), rect.centerY(),
                mConfig.getActionAcknowledgmentTimeout());//rect.centerX(), rect.centerY()。中心点
    }

跳转到etInteractionController().clickAndSync()方法中:

/**
     * Click at coordinates and blocks until either accessibility event TYPE_WINDOW_CONTENT_CHANGED
     * or TYPE_VIEW_SELECTED are received.
     *
     * @param x
     * @param y
     * @param timeout waiting for event
     * @return true if events are received, else false if timeout.
     */
    public boolean clickAndSync(final int x, final int y, long timeout) {

        String logString = String.format("clickAndSync(%d, %d)", x, y);
        Log.d(LOG_TAG, logString);

        return runAndWaitForEvents(clickRunnable(x, y), new WaitForAnyEventPredicate(
                AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED |
                AccessibilityEvent.TYPE_VIEW_SELECTED), timeout) != null;
    }

不确定是开发全面屏机器都这样还是部分ROM的开发者不小心留的坑,但,无力吐槽,更无力修复这种软件状态,只能寻找解决方案。

多方尝试后,发现adb shell input tap <x> <y> 可以实现屏幕点击,而滑动(长按)则可以通过adb shell input swipe <x1> <y1> <x2> <y2> [duration(ms)]来实现。而且,上面的切割部分的坐标,也是可以点击到的。辣么,解决方案便出来了。只要修改下点击的方式更换为Runtime.getRuntime().exec("input tap "+rect.centerX()+" "+ rect.centerY()),可以是在源码上做修改,也可以是在自己二次封装的代码上替换掉就可以了。贴上adb shell input 帮助文档:


C:\Users>adb shell input
Usage: input [<source>] <command> [<arg>...]

The sources are:
      dpad
      keyboard
      mouse
      touchpad
      gamepad
      touchnavigation
      joystick
      touchscreen
      stylus
      trackball

The commands and default sources are:
      text <string> (Default: touchscreen)
      keyevent [--longpress] <key code number or name> ... (Default: keyboard)
      tap <x> <y> (Default: touchscreen)
      swipe <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen)
      draganddrop <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen)
      press (Default: trackball)
      roll <dx> <dy> (Default: trackball)

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值