Appium UIAutomatorview 简单封装 (三) 提升获取元素截图效率方案,模拟器提升 7-9 倍

taki · 2016年04月14日 · 最后由 伊釨言 回复于 2017年06月19日 · 2772 次阅读

用 UIAutomatorview 获取控件,我觉得是好慢,我用的模拟器 (BlueStacks),手机没统计过不过也快步了多少,不管什么控件都差不多 9 秒,这效率是无法忍受的,即使你是压缩,其实慢的不是获取 XML 文件,而是慢在截图,空余时间每次一小步


查看 UIAutomatorview 截图实现代码


rawImage = device.getScreenshot();  //自带的截图方式,那么看看里面是什么

static RawImage getFrameBuffer(InetSocketAddress adbSockAddr, Device device) throws TimeoutException, AdbCommandRejectedException, IOException {
        RawImage imageParams = new RawImage();
        byte[] request = formAdbRequest("framebuffer:");
        byte[] nudge = new byte[]{(byte)0};
        SocketChannel adbChan = null;

        Object var11;
        try {
            adbChan = SocketChannel.open(adbSockAddr);
            adbChan.configureBlocking(false);
            setDevice(adbChan, device);
            write(adbChan, request);
            AdbHelper.AdbResponse resp = readAdbResponse(adbChan, false);
            if(!resp.okay) {
                throw new AdbCommandRejectedException(resp.message);
            }

            byte[] reply = new byte[4];
            read(adbChan, reply);
            ByteBuffer buf = ByteBuffer.wrap(reply);
            buf.order(ByteOrder.LITTLE_ENDIAN);
            int version = buf.getInt();
            int headerSize = RawImage.getHeaderSize(version);
            reply = new byte[headerSize * 4];
            read(adbChan, reply);
            buf = ByteBuffer.wrap(reply);
            buf.order(ByteOrder.LITTLE_ENDIAN);
            if(imageParams.readHeader(version, buf)) {
                Log.d("ddms", "image params: bpp=" + imageParams.bpp + ", size=" + imageParams.size + ", width=" + imageParams.width + ", height=" + imageParams.height);
                write(adbChan, nudge);
                reply = new byte[imageParams.size];
                read(adbChan, reply);
                imageParams.data = reply;
                return imageParams;
            }

            Log.e("Screenshot", "Unsupported protocol: " + version);
            var11 = null;
        } finally {
            if(adbChan != null) {
                adbChan.close();
            }

        }

        return (RawImage)var11;
    }

里面是通过 scoket 交互了好几次,获取 data 的时候特别慢


改造,直接用 ADB 截图


String command = "rm /sdcard/screenshot.png";
        command = "adb shell rm /sdcard/screenshot.png";
run(command);

command = "adb shell /system/bin/screencap -p /sdcard/screenshot.png";
        run(command);

command = "adb pull /sdcard/screenshot.png " + System.getProperty("user.dir");
        run(command);
        Picture.rotate(System.getProperty("user.dir") + File.separator + "screenshot.png"); //我用的模拟可能有问题,截图之后不是竖屏,那么自己旋转下,方式网上有

public static UiAutomatorResult takeSnapshot 方法修改,直接在入口起一个新的线程,不管 XML 获取没获取先把图截了


//入口不用管获取没获取到XML文件,直接起线程获取截图
ScreenShotUtil screenShotUtil = new ScreenShotUtil();
        Thread threadScreenShotUtil = new Thread(screenShotUtil);
        threadScreenShotUtil.start();

//文件结尾,自带的那些代码全部删掉,sPath是你保存图片的地方
ImageData imageData = new ImageData(sPath);
        Image screenshot = new Image(Display.getDefault(), imageData);
        return new UiAutomatorResult(xmlDumpFile, model, screenshot);

改完成之后那个酸爽,提升了 7-9 倍


在联想一下我之前写的文章,https://testerhome.com/topics/4545
既然效率这么高了,那么我在操作 APK 或者系统事件的时候,可以反调生成控件的按钮,也就是实现了伪录制的效果


输入文本信息,这里只有在 appium 脚本执行成功后才会刷新


自动刷新控件中


刷新之后的控件,这个有一个问题,就是目前的方式获取控件太快了,导致 app 可能跳转慢,截的图是未加载完成的,待改进

共收到 13 条回复 时间 点赞

不知道 minicap 能不能运用到这个里面去,如果可。以的话性能可以提升很多@doctorQ

#1 楼 @carl 如果性能是卡在截图的话,是可以通过 minicap 解决的,如果是卡在 dump 控件的话,那 minicap 也解决不了

taki #3 · 2016年04月14日 Author

#2 楼 @doctorq 主要卡在截图,目前这种方式可以秒出,minicap 没接触过,我了解一下

—— 来自 TesterHome 官方 安卓客户端

taki #4 · 2016年04月14日 Author

#1 楼 @carl 现在已经 秒级了 暂时够用了

—— 来自 TesterHome 官方 安卓客户端

#2 楼 @doctorq
主要还是截图效率不高导致的
看过你之前的帖子,但是还是没找到怎么将 minicap 用到这个 java 程序中去

#5 楼 @carl minicap 那篇文章下面有个 github 链接,里面有源码

#4 楼 @taki
不好不好,应该再提升一下。还有就是你用的是原生的 dump 吗?会碰到动态界面抓不了的问题,可以使用 ui2.0 的 dump 再抓出来

taki #8 · 2016年04月14日 Author

#6 楼 @doctorq 刚看了下,那个也是 socket 连接的吧,数据流获取可能是个瓶颈

—— 来自 TesterHome 官方 安卓客户端

#8 楼 @taki 速度肯定是比原生快很多

改了 出图是块了 当是 dump 还是太慢 怎么解决

@taki 通过执行 uiautomator dump 去得到控件的 xml 还是非常慢,这方面请问有什么建议没?

taki #12 · 2016年11月04日 Author

#11 楼 @yiziyan XML 复杂吧,慢主要在解析

wixed 打造专属 uiautomatorviewer 中提及了此贴 11月25日 16:46

@taki 除了 uiautomator dump 之外,有什么其他方法快速获取到手机界面的 xml 不

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册