You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Appium执行TouchActions操作时触发ClassCastException错误求助

解决Appium中io.appium.java_client.AppiumDriver cannot be cast to org.openqa.selenium.interactions.HasTouchScreen异常

你的问题根源很清晰:你用了Selenium原生的TouchActions类来实现触摸操作,但这个类要求驱动必须实现HasTouchScreen接口,而AppiumDriver并没有实现这个接口,所以直接抛出了类型转换异常。

解决方案:使用Appium官方适配的触摸操作API

Appium Java客户端自带了专门的触摸操作工具类,完全适配AppiumDriver,不需要做任何类型转换。下面分两种场景给你修改代码:


1. 适用于Appium 1.x(或偏好旧API):使用io.appium.java_client.TouchAction

首先替换导入的包,把Selenium的TouchActions换成Appium专属的TouchAction:

// 删除这行Selenium的导入:import org.openqa.selenium.interactions.touch.TouchActions;
import io.appium.java_client.TouchAction;
import io.appium.java_client.touch.LongPressOptions;
import io.appium.java_client.touch.offset.ElementOption;
import io.appium.java_client.touch.offset.PointOption;

然后修改你的testSearchAppium方法中的触摸操作逻辑:

@Test
public void testSearchAppium() throws Throwable {
    driver.get(AppURL);
    // 用WebDriverWait替代Thread.sleep,让测试更稳定
    wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[@class='notnow']"))).click();
    
    // 初始化Appium的TouchAction实例
    TouchAction action = new TouchAction(driver);
    
    // 长按目标元素
    action.longPress(LongPressOptions.longPressOptions()
            .withElement(ElementOption.element(driver.findElement(By.xpath("//a[@class='scroll__nav-link active-nav']")))))
            .release() // 必须调用release结束长按动作
            .perform();
    
    Thread.sleep(3000); // 建议后续替换为WebDriverWait等待操作反馈
    
    // 模拟向右滑动20像素(x轴偏移+20,y轴保持不变)
    // 坐标可以根据实际元素位置动态计算,这里用固定值做示例
    action.press(PointOption.point(100, 500))
            .waitAction()
            .moveTo(PointOption.point(120, 500))
            .release()
            .perform();
}

2. 适用于Appium 2.x+:推荐使用W3C标准的PointerInput和Sequence

TouchAction在新版本Appium中已被标记为Deprecated,官方推荐使用W3C标准API实现触摸操作,兼容性更好:

// 导入需要的包
import org.openqa.selenium.interactions.PointerInput;
import org.openqa.selenium.interactions.Sequence;
import java.time.Duration;
import java.util.Collections;

@Test
public void testSearchAppium() throws Throwable {
    driver.get(AppURL);
    wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[@class='notnow']"))).click();
    
    PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
    WebElement target = driver.findElement(By.xpath("//a[@class='scroll__nav-link active-nav']"));
    // 计算元素中心坐标,避免点击到元素边缘
    int centerX = target.getLocation().getX() + target.getSize().getWidth() / 2;
    int centerY = target.getLocation().getY() + target.getSize().getHeight() / 2;
    
    // 实现长按操作(保持2秒)
    Sequence longPress = new Sequence(finger, 1);
    longPress.addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), centerX, centerY));
    longPress.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
    longPress.addAction(finger.createPointerMove(Duration.ofSeconds(2), PointerInput.Origin.viewport(), centerX, centerY));
    longPress.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
    driver.perform(Collections.singletonList(longPress));
    
    Thread.sleep(3000);
    
    // 实现向右滑动20像素的操作
    Sequence flick = new Sequence(finger, 2);
    flick.addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), centerX, centerY));
    flick.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
    flick.addAction(finger.createPointerMove(Duration.ofMillis(300), PointerInput.Origin.viewport(), centerX + 20, centerY));
    flick.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
    driver.perform(Collections.singletonList(flick));
}

额外优化建议

  • 尽量减少Thread.sleep()的使用,改用WebDriverWait等待元素状态变化,提升测试稳定性
  • 确保Appium Java客户端版本与Appium Server版本兼容,版本不匹配容易引发各类异常
  • 滑动操作的坐标尽量基于元素位置动态计算,避免写死固定值,适配不同尺寸的移动设备

内容的提问来源于stack exchange,提问作者Madan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:35:21