在高版本的android手机(例如android 7.0 , 8.0等等),必须使用高版本的appium, 以及对应的selenium版本,那么很多的appium或者selenium方法会变得无法直接调用,这里是一个汇总收集。
本文以io.appium.java-client 3.14.0版本为例,为2018年最新版本
最新引入了
PointOption
ElementOption
WaitOptions
KeyEvent
TouchAction
The-event firing (时间与元素监听)
AppiumFunction (新的等待元素的方法)
//老版本的操作线,从元素附近的某个点移动到元素中心,新版本不允许出现: press(element,x,y)的语法 // TouchAction action0 = (new TouchAction(driver)).press(el, center.getX(), center.getY() - yOffset).moveTo(el).release(); // TouchAction action1 = (new TouchAction(driver)).press(el, center.getX(), center.getY() + yOffset).moveTo(el).release(); TouchAction action0 = (new TouchAction(driver)).press(PointOption.point(center.getX(), center.getY() - yOffset)).moveTo(ElementOption.element(el)).release(); TouchAction action1 = (new TouchAction(driver)).press(PointOption.point(center.getX(), center.getY() + yOffset)).moveTo(ElementOption.element(el)).release();
action.press(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(500))).perform();
KeyEvent key=new KeyEvent(); key.withKey(AndroidKey.KEYCODE_ZOOM_IN); //driver.pressKeyCode(KEYCODE_ZOOM_IN);//老版操作: 放大键
JAVA-Client 在新版里面提供了如下(等待元素)方法:
//waiting for elements private final AppiumFunction<WebDriver, List<WebElement>> searchingFunction = input -> { List<WebElement> result = input.findElements(By.tagName("a")); if (result.size() > 0) { return result; } return null; }; //waiting for some context using regular expression pattern private final AppiumFunction<Pattern, WebDriver> contextFunction = input -> { Set<String> contexts = driver.getContextHandles(); String current = driver.getContext(); contexts.forEach(context -> { Matcher m = input.matcher(context); if (m.find()) { driver.context(context); } }); if (!current.equals(driver.getContext())) { return driver; } return null; };
等待元素可以直接使用:
//using one function as pre-condition
@Test public void tezt() { .... Wait<Pattern> wait = new FluentWait<>(Pattern.compile("WEBVIEW")) .withTimeout(30, TimeUnit.SECONDS); List<WebElement> elements = wait.until(searchingFunction.compose(contextFunction)); .... }
//using one function as post-condition
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
@Test public void tezt() {
....
Wait<Pattern> wait = new FluentWait<>(Pattern.compile("WEBVIEW"))
.withTimeout(30, TimeUnit.SECONDS);
List<WebElement> elements = wait.until(contextFunction.andThen(searchingFunction));
....
}
TouchAction
private final ActionSupplier<TouchAction> horizontalSwipe = () -> { driver.findElementById("io.appium.android.apis:id/gallery"); AndroidElement gallery = driver.findElementById("io.appium.android.apis:id/gallery"); List<MobileElement> images = gallery .findElementsByClassName("android.widget.ImageView"); Point location = gallery.getLocation(); Point center = gallery.getCenter(); return new TouchAction(driver).press(images.get(2), -10, center.y - location.y) .waitAction(2000).moveTo(gallery, 10, center.y - location.y).release(); }; private final ActionSupplier<TouchAction> verticalSwiping = () -> new TouchAction(driver).press(driver.findElementByAccessibilityId("Gallery")) .waitAction(2000).moveTo(driver.findElementByAccessibilityId("Auto Complete")).release();
//水平与垂直的swipe @Test public void tezt() { ... horizontalSwipe.get().perform(); ... verticalSwiping.get().perform(); ... }
//普通的tap
import io.appium.java_client.TouchAction;
...
//tap
new TouchAction(driver)
.tap(driver
.findElementById("io.appium.android.apis:id/start")).perform();
... //swipe TouchAction swipe = new TouchAction(driver).press(images.get(2), -10, center.y - location.y) .waitAction(2000).moveTo(gallery, 10, center.y - location.y).release(); swipe.perform();
...
//tap by few fingers
MultiTouchAction multiTouch = new MultiTouchAction(driver);
for (int i = 0; i < fingers; i++) {
TouchAction tap = new TouchAction(driver);
multiTouch.add(tap.press(element).waitAction(duration).release());
}
multiTouch.perform();
public class GestureUtils { public static ActionSupplier<TouchAction> swipe(final AppiumDriver<?> driver, final params) { return () -> { new TouchAction(driver).press(params) .waitAction(params).moveTo(params).release(); }; } }
//可以直接使用如下方法进行swipe public class SomeTest { @Test public void tezt() { ... GestureUtils.swipe(driver, params).get().perform(); ... } }
Java-client 更新了The-event firing (新增了element/event的监听)
This feature allows end user to organize the event logging on the client side. Also this feature may be useful in a binding with standard or custom reporting frameworks.
import io.appium.java_client.events.api.general.AlertEventListener; public class AlertListener implements AlertEventListener { ... } ... import io.appium.java_client.events.api.general.ElementEventListener; public class ElementListener implements ElementEventListener { ... } //and so on ... import io.appium.java_client.events.EventFiringWebDriverFactory; import io.appium.java_client.events.api.Listener; ... AndroidDriver driver = new AndroidDriver(parameters); driver = EventFiringWebDriverFactory.getEventFiringWebDriver(driver, new AlertListener(), new ElementListener()); //or AndroidDriver driver2 = new AndroidDriver(parameters); List<Listener> listeners = new ArrayList<>(); listeners.add(new AlertListener()); listeners.add(new ElementListener()); driver = EventFiringWebDriverFactory.getEventFiringWebDriver(driver2, listeners);
如何使用事件监听呢?
//and so on ... import io.appium.java_client.events.EventFiringWebDriverFactory; ... AndroidDriver driver = new AndroidDriver(parameters); driver = EventFiringWebDriverFactory.getEventFiringWebDriver(driver);
如果你自己想封装的话,可以如下操作:
import org.openqa.selenium.support.events.WebDriverEventListener; import io.appium.java_client.events.api.general.AppiumWebDriverEventListener; public class UsersWebDriverEventListener implements WebDriverEventListener, AppiumWebDriverEventListener { ... }
//或者如下操作 import io.appium.java_client.events.api.general.AppiumWebDriverEventListener; public class UsersWebDriverEventListener implements AppiumWebDriverEventListener { ... }