如何使用 webdriver.io 控制 Android 设备
Posted
技术标签:
【中文标题】如何使用 webdriver.io 控制 Android 设备【英文标题】:How to control Android device with webdriver.io 【发布时间】:2022-01-15 01:47:38 【问题描述】:我正在使用appium-uiautomator2-driver 使用以下代码在 android 设备上启动服务器
const startServer = require('appium-uiautomator2-driver')
startServer()
const AndroidUiautomator2Driver = require("appium-uiautomator2-driver");
const startDriver = async () =>
const driver = new AndroidUiautomator2Driver();
const capabilities =
automationName: "UiAutomator2",
platformName: "Android",
deviceName: "emulator-5554",
;
await driver.createSession(capabilities);
;
startDriver().catch((e) => console.error(e));
然后我尝试使用 webdriver.io 连接到设备上运行的服务器,如下所示:
const wdio = require("webdriverio");
const driverPromise = wdio.attach(
isAndroid: true,
port: 8213,
isMobile: true,
automationName: 'UiAutomator2',
sessionId: "56667cc9-625e-4e13-8c4d-354d1928d859",
);
driverPromise.then(async function (driver)
await driver.touchAction([
action: "press", x: 200, y: 200 ,
action: "moveTo", x: 200, y: 300 ,
"release",
]);
);
但我得到的是 UnknownCommandException:
2021-12-09T18:01:20.083Z ERROR webdriver: Request failed with status 404 due to unknown command: The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource
(node:61813) UnhandledPromiseRejectionWarning: io.appium.uiautomator2.common.exceptions.UnknownCommandException: The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource
at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:75)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:611)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:552)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:466)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
at java.lang.Thread.run(Thread.java:919)
谁能告诉我问题出在哪里? UIAutomator 驱动程序是否与 webdriver.io 不兼容?应该是,因为readme.md 表示“驱动程序在 W3C WebDriver 协议的范围内运行,具有几个自定义扩展以涵盖操作系统特定的场景。”
【问题讨论】:
【参考方案1】:我建议不要直接使用 uiautomator2,因为它被设计为 Appium 的内部部分。
Webdriver.io 支持 Appium 协议。如果相应的automationName
能力将被传递,则可以使用 uiautomator2。
https://github.com/webdriverio/appium-boilerplate/blob/main/config/wdio.android.app.conf.ts
请看android原生项目模板: https://github.com/webdriverio/appium-boilerplate/.
【讨论】:
没有设法让 webdriver.io 与 appium 服务器一起工作。甚至不使用样板文件中的配置。 “直接使用uiautomator2”是什么意思? 您正在尝试使用 uiautomator2-driver lib 创建一个单独的 uiautomator2 驱动程序会话,然后附加。我建议使用 wdio.remote 创建一个具有“UIAutomator2”功能的新 appium 会话,如下例所示:appium.io/docs/en/about-appium/getting-started/index.html。以上是关于如何使用 webdriver.io 控制 Android 设备的主要内容,如果未能解决你的问题,请参考以下文章
Selenium & webdriver.io 如何使用 executeScript?
Webdriver.io - 如何在配置中使用 beforeEach 钩子
如何使用没有标识符的 WebDriver.io 在页面上查找元素
如何使用 webdriver.io 模拟 ctrl-click 或 shift-click?