用 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 可能跳转慢,截的图是未加载完成的,待改进