• UiAutomator源码学习(1)-- UiDevice


    UiDevice提供对设备状态信息的访问。 也可以使用此类来模拟设备上的用户操作,例如按键盘或按Home和Menu按钮。UiDevice类的完整源码 UiDevice.java

    废话不多说,我们首先根据用法来来看看Android Uiautomator 访问设备的原理。

     device = UiDevice.getInstance(getInstrumentation());
     device.pressHome();
    
        // Bring up the default launcher by searching for a UI component
        // that matches the content description for the launcher button.
     UiObject allAppsButton = device
                .findObject(new UiSelector().description("Apps"));
    
        // Perform a click on the button to load the launcher.
     allAppsButton.clickAndWaitForNewWindow();

     根据这个用法实例,我们先看一下它的构造函数:

     /** Private constructor. Clients should use {@link UiDevice#getInstance(Instrumentation)}. */
        private UiDevice(Instrumentation instrumentation) {
            mInstrumentation = instrumentation;
            UiAutomation uiAutomation = instrumentation.getUiAutomation();
            mUiAutomationBridge = new InstrumentationUiAutomatorBridge(
                    instrumentation.getContext(), uiAutomation);
            // Enable multi-window support for API level 21 and up
            if (UiDevice.API_LEVEL_ACTUAL >= Build.VERSION_CODES.LOLLIPOP) {
                // Subscribe to window information
                AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
                info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
                uiAutomation.setServiceInfo(info);
            }
        }
        /**
         * Retrieves a singleton instance of UiDevice
         *
         * @return UiDevice instance
         */
        public static UiDevice getInstance(Instrumentation instrumentation) {
            if (sInstance == null) {
                sInstance = new UiDevice(instrumentation);
            }
            return sInstance;
        }

    这是一个单例模式的类,负责创建自己的对象,以确保UiDevcie对象的唯一性。在构造方法中除了初始化唯一的uiDevice对象,还初始化了UiAutomoatorBridge对象。UiAutomatorBridge这个类非常的重要,获取设备界面信息、注入事件以及截图都需要经过UiAutomatorBridge。稍后会做详细的介绍。

    接下来我们来看,是如何获取设备信息以及模拟用户操作的。

     /**
         * Returns the display size in dp (device-independent pixel)
         *
         * The returned display size is adjusted per screen rotation. Also this will return the actual
         * size of the screen, rather than adjusted per system decorations (like status bar).
         *
         * @return a Point containing the display size in dp
         */
        public Point getDisplaySizeDp() {
            Tracer.trace();
            Display display = getAutomatorBridge().getDefaultDisplay();
            Point p = new Point();
            display.getRealSize(p);
            DisplayMetrics metrics = new DisplayMetrics();
            display.getRealMetrics(metrics);
            float dpx = p.x / metrics.density;
            float dpy = p.y / metrics.density;
            p.x = Math.round(dpx);
            p.y = Math.round(dpy);
            return p;
        }
    getDisplaySizeDp()方法返回的是一个以dp为单位的坐标点。同样可以获取设备的宽度或者高度:
      /**
         * Gets the width of the display, in pixels. The width and height details
         * are reported based on the current orientation of the display.
         * @return width in pixels or zero on failure
         */
        public int getDisplayWidth() {
            Display display = getDefaultDisplay();
            Point p = new Point();
            display.getSize(p);
            return p.x;
        }

    以上都是设备属性,接下来看模拟用户的操作。操作的第一步就是获取屏幕的焦点。获取到UiObject后就可以对屏幕上的这些控件进行模拟用户操作。

    /**
         * Returns a UiObject which represents a view that matches the specified selector criteria.
         *
         * @param selector
         * @return UiObject object
         */
        public UiObject findObject(UiSelector selector) {
            return new UiObject(this, selector);
        }

    获取到屏幕上布局对象以后,操作无外乎就是点击、长按、滑动 以及键盘等操作。

       /**
         * Simulates a short press on the HOME button.
         * @return true if successful, else return false
         * @since API Level 16
         */
        public boolean pressHome() {
            Tracer.trace();
            waitForIdle();
            return getAutomatorBridge().getInteractionController().sendKeyAndWaitForEvent(
                    KeyEvent.KEYCODE_HOME, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
                    KEY_PRESS_EVENT_TIMEOUT);
        }
    
     /**
         * Perform a click at arbitrary coordinates specified by the user
         *
         * @param x coordinate
         * @param y coordinate
         * @return true if the click succeeded else false
         * @since API Level 16
         */
        public boolean click(int x, int y) {
            Tracer.trace(x, y);
            if (x >= getDisplayWidth() || y >= getDisplayHeight()) {
                return (false);
            }
            return getAutomatorBridge().getInteractionController().clickNoSync(x, y);
        }
        /**
         * Performs a swipe from one coordinate to another using the number of steps
         * to determine smoothness and speed. Each step execution is throttled to 5ms
         * per step. So for a 100 steps, the swipe will take about 1/2 second to complete.
         *
         * @param startX
         * @param startY
         * @param endX
         * @param endY
         * @param steps is the number of move steps sent to the system
         * @return false if the operation fails or the coordinates are invalid
         * @since API Level 16
         */
        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);
        }

    不难看出,所有的操作都离不开 uiAutomatorBridge。在该类的方法getInteractionController()获取InteractionController 对象。InteractionController类将用户的键盘事件注入到android系统中,与系统进行交互。稍后会做详细的介绍。

    除了这些操作,UiDevice还提供了其他的方法,如打开通知栏、点亮屏幕、执行adb命令、检查电源管理器,屏幕是否打开、等待屏幕更新、获取当前窗口的布局层次结构、截图等。

  • 相关阅读:
    ORACLE中dba,user,v$等开头的常用表和视图
    rman restore spfile from backup
    oracle11g设置归档模式和非归档模式
    Oracle数据文件改名
    Linux下rz/sz安装及使用方法
    oracle数据库rman备份计划及恢复
    高级数据查询SQL语法
    关系数据库SQL之基本数据查询:子查询、分组查询、模糊查询
    关系数据库常用SQL语句语法大全
    微服务化的基石——持续集成【转】
  • 原文地址:https://www.cnblogs.com/yuan1225/p/13254235.html
Copyright © 2020-2023  润新知