1.在4.4.2版本中滑动屏幕时scrollForward()不起作用而swipeLeft()可以滑动?

(如果想知道结果,直接看总结)

先来看下各自的源码(4.1.1版)

swipeLeft

 public boolean swipeLeft(int steps) throws UiObjectNotFoundException {Rect rect = getBounds();if(rect.width() <= SWIPE_MARGIN_LIMIT * 2)return false; // too small to swipereturn getInteractionController().swipe(rect.right - SWIPE_MARGIN_LIMIT,rect.centerY(), rect.left + SWIPE_MARGIN_LIMIT, rect.centerY(), steps);}

可以看出里面调用了InteractionController.swipe()

    public boolean swipe(int downX, int downY, int upX, int upY, int steps) {boolean ret = false;int swipeSteps = steps;double xStep = 0;double yStep = 0;// avoid a divide by zeroif(swipeSteps == 0)swipeSteps = 1;xStep = ((double)(upX - downX)) / swipeSteps;yStep = ((double)(upY - downY)) / swipeSteps;// first touch starts exactly at the point requestedret = touchDown(downX, downY);for(int i = 1; i < swipeSteps; i++) {ret &= touchMove(downX + (int)(xStep * i), downY + (int)(yStep * i));if(ret == false)break;// set some known constant delay between steps as without it this// become completely dependent on the speed of the system and results// may vary on different devices. This guarantees at minimum we have// a preset delay.SystemClock.sleep(5);}ret &= touchUp(upX, upY);return(ret);}

在swipe方法里在起始点touchDown,然后中间点都是touchMove,在结束点touchUp

scrollForward

public boolean scrollForward(int steps) {Log.d(LOG_TAG, "scrollForward() on selector = " + getSelector());AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);if(node == null) {// Object Not Foundreturn false;}Rect rect = new Rect();;node.getBoundsInScreen(rect);int downX = 0;int downY = 0;int upX = 0;int upY = 0;// scrolling is by default assumed vertically unless the object is explicitly// set otherwise by setAsHorizontalContainer()if(mIsVerticalList) {int swipeAreaAdjust = (int)(rect.height() * getSwipeDeadZonePercentage());// scroll vertically: swipe down -> updownX = rect.centerX();downY = rect.bottom - swipeAreaAdjust;upX = rect.centerX();upY = rect.top + swipeAreaAdjust;} else {int swipeAreaAdjust = (int)(rect.width() * getSwipeDeadZonePercentage());// scroll horizontally: swipe right -> left// TODO: Assuming device is not in right to left languagedownX = rect.right - swipeAreaAdjust;downY = rect.centerY();upX = rect.left + swipeAreaAdjust;upY = rect.centerY();}return getInteractionController().scrollSwipe(downX, downY, upX, upY, steps);}

源码可以看出最后调用了InteractionController.scrollSwipe,进入到该方法:

public boolean scrollSwipe(final int downX, final int downY, final int upX, final int upY,final int steps) {Log.d(LOG_TAG, "scrollSwipe (" +  downX + ", " + downY + ", " + upX + ", "+ upY + ", " + steps +")");try {mUiAutomatorBridge.executeCommandAndWaitForAccessibilityEvent(new Runnable() {@Overridepublic void run() {swipe(downX, downY, upX, upY, steps);}},new Predicate<AccessibilityEvent>() {@Overridepublic boolean apply(AccessibilityEvent event) {return (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED);}}, DEFAULT_SCROLL_EVENT_TIMEOUT_MILLIS);} catch (Exception e) {Log.e(LOG_TAG, "Error in scrollSwipe: " + e.getMessage());return false;}return true;}

可以看到在run方法里他也是调用了swipe方法。那为何swipeLeft可以滑动,而scrollForward却不可以?

去4.4.2版本里去看看这两个方法是否有改动。但是4.4.2源码与4.1.1的源码是一样的的,没有改动,从swipe方法的坐标入手试试。因为swipeleft方法中滑动点的坐标是从距右边框5个像素,滑倒距左边框5个像素,而scrollForward是从距右边框54像素滑到距左边框54像素(宽度*盲区百分比)的。在距离上swipeleft传给swipe的坐标轨迹要比scrollForward的距离远。然后看看界面的视图

从uiautomatorviewer中可以看出可滑动的区域为整个屏幕bounds:[0,0][540,960].而滑动时真正滚动的区域为[6,92][534,748],有6个像素的区别。下面我们通过直接调用InteractionController里的swipe方法,来验证这个想法的正确性。由于InteractionController里的方法都是定义的包内可用,不能直接通过UiObject里的getInteractionContoller得到该对象,然后调用swipe()。那么怎么办呢?好在UiDevice里有个方法swipe:

public boolean swipe(int startX, int startY, int endX, int endY, int steps) {Tracer.trace(startX, startY, endX, endY, steps);return getAutomatorBridge().getInteractionController().swipe(startX, startY, endX, endY, steps);}

刚好也是调用InteractionController中的swipe方法,那么我们来开始代码的编写:

public void test_EnterApp() throws UiObjectNotFoundException{uiDevice = getUiDevice();uiDevice.pressHome();UiScrollable appList = UiUtil.findUiScrollableByScrollable(true);if (appList.exists()) {appList.setAsHorizontalList();//uiDevice.swipe(535, 480, 5, 480, 20);uiDevice.swipe(540-54, 480, 54, 480, 20);}}

通过上面的实验,结论是2个方法都成功的滚动了,说明不是坐标差异造成的滚动差异。这就又开始让我疑惑了,看了一下4.4.2里InteractionController中scrollSwipe改动太大了:

public boolean scrollSwipe(final int downX, final int downY, final int upX, final int upY,final int steps) {Log.d(LOG_TAG, "scrollSwipe (" +  downX + ", " + downY + ", " + upX + ", "+ upY + ", " + steps +")");Runnable command = new Runnable() {@Overridepublic void run() {swipe(downX, downY, upX, upY, steps);}};// Collect all accessibility events generated during the swipe command and get the// last eventArrayList<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();runAndWaitForEvents(command,new EventCollectingPredicate(AccessibilityEvent.TYPE_VIEW_SCROLLED, events),Configurator.getInstance().getScrollAcknowledgmentTimeout());AccessibilityEvent event = getLastMatchingEvent(events,AccessibilityEvent.TYPE_VIEW_SCROLLED);if (event == null) {// end of scroll since no new scroll events receivedrecycleAccessibilityEvents(events);return false;}// AdapterViews have indices we can use to check for the beginning.boolean foundEnd = false;if (event.getFromIndex() != -1 && event.getToIndex() != -1 && event.getItemCount() != -1) {foundEnd = event.getFromIndex() == 0 ||(event.getItemCount() - 1) == event.getToIndex();Log.d(LOG_TAG, "scrollSwipe reached scroll end: " + foundEnd);} else if (event.getScrollX() != -1 && event.getScrollY() != -1) {// Determine if we are scrolling vertically or horizontally.if (downX == upX) {// VerticalfoundEnd = event.getScrollY() == 0 ||event.getScrollY() == event.getMaxScrollY();Log.d(LOG_TAG, "Vertical scrollSwipe reached scroll end: " + foundEnd);} else if (downY == upY) {// HorizontalfoundEnd = event.getScrollX() == 0 ||event.getScrollX() == event.getMaxScrollX();Log.d(LOG_TAG, "Horizontal scrollSwipe reached scroll end: " + foundEnd);}}recycleAccessibilityEvents(events);return !foundEnd;}

教训:看源码一定要看到方法一层层调用,直到谷歌在API没有的类。那个里面往往有着不被人发现的秘密。

但是该方法也没有太大的逻辑上的改动。我尝试着在其他可滚动的控件里使用scrollForward方法。比如在更换壁纸里,该方法是可用的。而且在其他手机的appLiist界面使用scrollForward也无错。

这个与上面那张applist的区别在于,scrollable为true的布局和真正滚动的是一个布局。而上面scrollable布局为整个屏幕,而真正滚动的是中间那部分应用列表。这个我是不是可以归咎与开发的问题,所以问题的根究应该在与scrollable布局的设置,我改一下定位可滚动的控件试试。首先我获得之前获得的控件的坐标:

public void test_EnterApp() throws UiObjectNotFoundException {uiDevice = getUiDevice();//uiDevice.pressHome();UiScrollable appList = UiUtil.findUiScrollableByScrollable(true);Log.i(TAG, appList.getBounds().toString());if (appList.exists()) {appList.setAsHorizontalList();while (true) {appList.scrollForward();}}}

Log输出:

01-02 02:21:47.869: I/Stress(27282): Rect(-1698, -832 - 2240, 1793)
01-02 02:32:28.474: I/QueryController(27608): Matched selector: UiSelector[SCROLLABLE=true] <<==>>
[android.view.accessibility.AccessibilityNodeInfo@8718; boundsInParent: Rect(540, 0 - 4479, 2626);
boundsInScreen: Rect(-1698, -832 - 2240, 1793); packageName: com.android.sprdlauncher2; className: android.view.View;
text: null; contentDescription: null; viewIdResName: com.android.sprdlauncher2:id/workspace; checkable: false;
checked: false; focusable: false; focused: false; selected: false; clickable: false; longClickable: true; enabled: true;
password: false; scrollable: true;
[ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_LONG_CLICK, ACTION_ACCESSIBILITY_FOCUS, ACTION_SCROLL_FORWARD, ACTION_SCROLL_BACKWARD]]
01-02 02:32:28.474: D/InteractionController(27608): scrollSwipe (1847, 480, -1305, 480, 20)
01-02 02:32:28.474: I/InputDispatcher(594): Dropping event because there is no touchable window at (1847, 480).
01-02 02:32:28.474: W/InputManager(594): Input event injection from pid 27608 failed.
01-02 02:32:28.484: W/InputManager(594): Input event injection from pid 27608 failed.
01-02 02:32:28.484: W/InputManager(594): Input event injection from pid 27608 failed.
01-02 02:32:28.684: W/InteractionController(27608): runAndwaitForEvent timedout waiting for events

从日志来看,点击的区域不在屏幕可见位置,终于找到它不滚动的原因啦。瞎琢磨一通啊,终于找到原因。现在分析原因开始。

总结:

1.swipeLeft的方法调用过程是swipeLeft--->swipe,scrollForward调用过程scrollForward--->scrollSwipe--->swipe。scrollForward就卡在了第二步scrollSwipe。因为scrollSwipe里的方法点击的点需要可触摸。而swipe则不需要这样的限制。

2.在遇到这种可滚动控件是整个屏幕的,尽量使用swipeLeft。

3.分析源码时针对当前版本,因为不同版本改动很大。

4.要低调!

uiautomator测试中scrollForward方法使用失灵相关推荐

  1. android开发自制计算器测试图,基于uiautomator测试框架的计算器自动化测试方法和测试系统的制作方法...

    基于uiautomator测试框架的计算器自动化测试方法和测试系统的制作方法 [技术领域] [0001]本发明涉及自动化测试技术领域,特别是一种基于uiautomator测试框架的计算器自动化测试方法 ...

  2. kotlin调用类中的方法_一种轻松的方法来测试Kotlin中令人沮丧的静态方法调用

    kotlin调用类中的方法 by Oleksii Fedorov 通过Oleksii Fedorov 一种轻松的方法来测试Kotlin中令人沮丧的静态方法调用 (A stress-free way t ...

  3. XCode中的单元测试:编写测试类和方法(内容意译自苹果官方文档)

    当你在工程中通过测试导航栏添加了一个测试target之后, xcode会在测试导航栏中显示该target所属的测试类和方法. 这一章演示了怎么创建测试类,以及如何编写测试方法. 测试targets, ...

  4. monkey测试中防止关闭WIFI的方法

    monkey测试中防止关闭WIFI的方法 在monkey测试过程中,经常出现随机下拉顶部的状态栏,导致WIFI被关闭,测试过程中无网络,业务流程无法进行验证,针对这种情况,有如下两种解决方法: 1.时 ...

  5. 关于测试中常用到的一些方法、策略总结

    一些常用模块的测试用例 1.登录 2.添加 3.查询 4.删除 1.登录 ①用户名和密码都符合要求(格式上的要求) ②用户名和密码都不符合要求(格式上的要求) ③用户名符合要求,密码不符合要求(格式上 ...

  6. opencv 配置及测试中遇到的问题及解决方法(Microsoft C++ 异常: cv::Exception,位于内存位置 问题)

    opencv 配置及测试中遇到的问题及解决方法 这是我第一次使用 opencv,配置是opencv3.4.1和Visual Studio 2019.本文主要写的是我在 配置 和 编写运行第一个测试程序 ...

  7. 软件测试中的程序接缝指什么,接缝滑移-定滑移量常用测试标准与方法

    接缝滑移-定滑移量常用测试标准与方法 已被阅读9264次 2018-12-21 织物接缝滑移,也就是之前国内所称的纰裂程度.是指织物经接缝后,缝纫处的纱线抵抗外在拉力的能力,是衡量织物接缝性能的一个重 ...

  8. 软件测试模糊搜索用例,模糊测试中测试用例生成方法.pdf

    模糊测试中测试用例生成方法 2015 年 第 24 卷 第 4 期 计 算 机 系 统 应 用 模糊测试中测试用例生成方法① 李 彤, 黄 轩, 黄 睿 (装甲兵工程学院 信息工程系, 北京 1000 ...

  9. 用博文中的方法-r -d \t试了下conlleval测试crf++的输出

     看到这篇 http://argcv.com/articles/2104.c 觉得不错 后来到官网上看了下http://www.cnts.ua.ac.be/conll2000/chunking/o ...

最新文章

  1. VS2017报错---无可用源
  2. ZeroMQ接口函数之 :zmq_msg_init - 初始化一个空的ZMQ消息结构
  3. 现代软件工程 第十七章 【人、绩效和职业道德】 练习与讨论
  4. C#学习笔记---数据类型
  5. IIS7.0通过FastCGI方式运行PHP遇到的一些问题及解决方法
  6. 全国计算机考试可以异地考吗,公务员省考可以异地考吗
  7. 怎么用鼠标选中java中table的某一行_为什么同事的工作效率那么高?学会这些鼠标双击技巧,你也可以的...
  8. String 类型ID 获取
  9. 大数据滥用 借贷平台肆意妄为的背后
  10. PHP下ajax跨域的解决方案之window.name
  11. fiddler抓包手机app数据(手机连接WiFi)
  12. matlab 线性规划 单纯形法
  13. c语言左移函数_corl_,crol(crol函数怎么左移)
  14. wps excel 表格给一列数据添加相同的内容的方法
  15. Java实现 N的阶乘
  16. 物体移动时按下Shift键加快速度
  17. php简单图片与文字合成
  18. 8086的两种工作模式_8086有哪两种工作模式?其主要区别是什么?
  19. shiro使用md5salt哈希散列加密
  20. 权限管理模型 ---- ACL、RBAC和ABAC(详解)

热门文章

  1. [多点触控测试]不用app,手机怎么测试屏幕触控点数
  2. 如何通过供应链管理来居家做菜?
  3. 互动微剧《明星大侦探》打造沉浸式探案体验
  4. html5适应手机比例,HTML5 如何让手机网站自适应设备屏幕宽度
  5. html如何冻结字段,利用jQuery实现HTML 表格行列冻结
  6. 第一章 人力资源管理概述(6学时)
  7. python zipfile压缩文件夹
  8. DAMO-YOLO | 超越所有YOLO,5行代码即可体验
  9. 微信小程序如何设置背景图片
  10. 英文pdf的划词翻译阅读方法