Swipe/Scroll best practice with Java-Client 5

The swipe method was deprecated on java-client5.X (AppiumDriver#swipe(int, int, int, int, int) ).

Can someone share the best practice to overcome this change?

We have tried to use the TouchAction class however, it doesn’t seems to work properly.


TouchAction ta = new TouchAction(driver);
ta.press(x1, y1).waitAction(wait).moveTo(x2, y2).release().perform();

@menypeled it is depending on your platform :slight_smile:

    protected void swipe_iOS(int startx, int starty, int endx, int endy, int duration) {
        swipe(startx, starty, -startx + endx, -starty + endy, duration);
    }

    protected void swipe(int startx, int starty, int endx, int endy, int duration) { // Android ONLY!
        System.out.println("    swipe(" + startx + ", " + starty + ", " + endx + ", " + endy + ")");
        new TouchAction((MobileDriver) driver).press(startx, starty).waitAction(Duration.ofMillis(duration)).moveTo(endx, endy).release().perform();
    }
4 Likes

@menypeled but there are best way to scroll:

// iOS scroll by object
    public boolean swipeToDirection_iOS_XCTest(MobileElement el, String direction) {
        try {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            HashMap<String, String> swipeObject = new HashMap<String, String>();
            if (direction.equals("d")) {
                swipeObject.put("direction", "down");
            } else if (direction.equals("u")) {
                swipeObject.put("direction", "up");
            } else if (direction.equals("l")) {
                swipeObject.put("direction", "left");
            } else if (direction.equals("r")) {
                swipeObject.put("direction", "right");
            }
            swipeObject.put("element", el.getId());
            js.executeScript("mobile:swipe", swipeObject);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public boolean scrollToDirection_iOS_XCTest(MobileElement el, String direction) {
        // The main difference from swipe call with the same argument is that scroll will try to move
        // the current viewport exactly to the next/previous page (the term "page" means the content,
        // which fits into a single device screen)
        try {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            HashMap<String, String> scrollObject = new HashMap<String, String>();
            if (direction.equals("d")) {
                scrollObject.put("direction", "down");
            } else if (direction.equals("u")) {
                scrollObject.put("direction", "up");
            } else if (direction.equals("l")) {
                scrollObject.put("direction", "left");
            } else if (direction.equals("r")) {
                scrollObject.put("direction", "right");
            }
            scrollObject.put("element", el.getId());
            scrollObject.put("toVisible", "true"); // optional but needed sometimes
            js.executeScript("mobile:scroll", scrollObject);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

// Android scroll to some text in scroll View

    public boolean tapByText(String text) {
        List<AndroidElement> elementList = driver.findElements(MobileBy.AndroidUIAutomator(
                "new UiScrollable(new UiSelector().resourceIdMatches(\".*id/ADD_YOUR_SCOLLER_VIEW_ID\")).setMaxSearchSwipes(5).scrollIntoView("
                + "new UiSelector().text(\"" + text + "\"))"));
        if (elementList.isEmpty())
            return false;
        return tapElement(elementList.get(0)); // tapElement is just custom tap method. use any you know instead.
    }

2 Likes

@ Aleksei I tried the following codes on ios10 with appium 1.6.5 on MacOS 10.11.6.

Dimension size = driver.manage().window().getSize();
int startx = size.getWidth() / 2;
int starty = (int) (size.getHeight() * 0.8);
int endy = (int) (size.getHeight() * 0.2);
driver.swipe(startx, starty, startx, endy, 1000);

TouchAction action = new TouchAction(driver);
action.press(startx,starty).waitAction(1000).moveTo(startx,endy).release().perform();

I am getting the below error.

/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/bin/java -ea -Didea.test.cyclic.buffer.size=1048576 “-javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=61073:/Applications/IntelliJ IDEA CE.app/Contents/bin” -Dfile.encoding=UTF-8 -classpath “/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar:/Applications/IntelliJ IDEA CE.app/Contents/plugins/testng/lib/testng-plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/lib/tools.jar:/Users/gunuputis4r/Documents/Intellijiworkspace/KidsIviewPhonesAutomation/target/test-classes:/Users/gunuputis4r/Documents/Intellijiworkspace/KidsIviewPhonesAutomation/target/classes:/Users/gunuputis4r/.m2/repository/io/appium/java-client/3.3.0/java-client-3.3.0.jar:/Users/gunuputis4r/.m2/repository/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-java/2.48.2/selenium-java-2.48.2.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-chrome-driver/2.48.2/selenium-chrome-driver-2.48.2.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-remote-driver/2.48.2/selenium-remote-driver-2.48.2.jar:/Users/gunuputis4r/.m2/repository/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-api/2.48.2/selenium-api-2.48.2.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-edge-driver/2.48.2/selenium-edge-driver-2.48.2.jar:/Users/gunuputis4r/.m2/repository/commons-io/commons-io/2.4/commons-io-2.4.jar:/Users/gunuputis4r/.m2/repository/org/apache/commons/commons-exec/1.3/commons-exec-1.3.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-htmlunit-driver/2.48.2/selenium-htmlunit-driver-2.48.2.jar:/Users/gunuputis4r/.m2/repository/net/sourceforge/htmlunit/htmlunit/2.18/htmlunit-2.18.jar:/Users/gunuputis4r/.m2/repository/xalan/xalan/2.7.2/xalan-2.7.2.jar:/Users/gunuputis4r/.m2/repository/xalan/serializer/2.7.2/serializer-2.7.2.jar:/Users/gunuputis4r/.m2/repository/org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.jar:/Users/gunuputis4r/.m2/repository/org/apache/httpcomponents/httpmime/4.5/httpmime-4.5.jar:/Users/gunuputis4r/.m2/repository/net/sourceforge/htmlunit/htmlunit-core-js/2.17/htmlunit-core-js-2.17.jar:/Users/gunuputis4r/.m2/repository/xerces/xercesImpl/2.11.0/xercesImpl-2.11.0.jar:/Users/gunuputis4r/.m2/repository/xml-apis/xml-apis/1.4.01/xml-apis-1.4.01.jar:/Users/gunuputis4r/.m2/repository/net/sourceforge/nekohtml/nekohtml/1.9.22/nekohtml-1.9.22.jar:/Users/gunuputis4r/.m2/repository/net/sourceforge/cssparser/cssparser/0.9.16/cssparser-0.9.16.jar:/Users/gunuputis4r/.m2/repository/org/w3c/css/sac/1.3/sac-1.3.jar:/Users/gunuputis4r/.m2/repository/org/eclipse/jetty/websocket/websocket-client/9.2.12.v20150709/websocket-client-9.2.12.v20150709.jar:/Users/gunuputis4r/.m2/repository/org/eclipse/jetty/jetty-util/9.2.12.v20150709/jetty-util-9.2.12.v20150709.jar:/Users/gunuputis4r/.m2/repository/org/eclipse/jetty/jetty-io/9.2.12.v20150709/jetty-io-9.2.12.v20150709.jar:/Users/gunuputis4r/.m2/repository/org/eclipse/jetty/websocket/websocket-common/9.2.12.v20150709/websocket-common-9.2.12.v20150709.jar:/Users/gunuputis4r/.m2/repository/org/eclipse/jetty/websocket/websocket-api/9.2.12.v20150709/websocket-api-9.2.12.v20150709.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-firefox-driver/2.48.2/selenium-firefox-driver-2.48.2.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-ie-driver/2.48.2/selenium-ie-driver-2.48.2.jar:/Users/gunuputis4r/.m2/repository/net/java/dev/jna/jna/4.1.0/jna-4.1.0.jar:/Users/gunuputis4r/.m2/repository/net/java/dev/jna/jna-platform/4.1.0/jna-platform-4.1.0.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-safari-driver/2.48.2/selenium-safari-driver-2.48.2.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-support/2.48.2/selenium-support-2.48.2.jar:/Users/gunuputis4r/.m2/repository/org/webbitserver/webbit/0.4.14/webbit-0.4.14.jar:/Users/gunuputis4r/.m2/repository/io/netty/netty/3.5.2.Final/netty-3.5.2.Final.jar:/Users/gunuputis4r/.m2/repository/org/seleniumhq/selenium/selenium-leg-rc/2.48.2/selenium-leg-rc-2.48.2.jar:/Users/gunuputis4r/.m2/repository/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:/Users/gunuputis4r/.m2/repository/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar:/Users/gunuputis4r/.m2/repository/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:/Users/gunuputis4r/.m2/repository/commons-codec/commons-codec/1.6/commons-codec-1.6.jar:/Users/gunuputis4r/.m2/repository/com/google/guava/guava/17.0/guava-17.0.jar:/Users/gunuputis4r/.m2/repository/cglib/cglib/3.1/cglib-3.1.jar:/Users/gunuputis4r/.m2/repository/org/ow2/asm/asm/4.2/asm-4.2.jar:/Users/gunuputis4r/.m2/repository/commons-validator/commons-validator/1.4.1/commons-validator-1.4.1.jar:/Users/gunuputis4r/.m2/repository/commons-beanutils/commons-beanutils/1.8.3/commons-beanutils-1.8.3.jar:/Users/gunuputis4r/.m2/repository/commons-digester/commons-digester/1.8.1/commons-digester-1.8.1.jar:/Users/gunuputis4r/.m2/repository/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar:/Users/gunuputis4r/.m2/repository/org/testng/testng/6.9.10/testng-6.9.10.jar:/Users/gunuputis4r/.m2/repository/com/beust/jcommander/1.48/jcommander-1.48.jar:/Users/gunuputis4r/.m2/repository/org/beanshell/bsh/2.0b4/bsh-2.0b4.jar:/Applications/IntelliJ IDEA CE.app/Contents/plugins/testng/lib/jcommander.jar” org.testng.RemoteTestNGStarter -usedefaultlisteners false -socket61072 @w@/private/var/folders/6f/cm41jlqd0vbfmj_f6nwv7tf4sskhh6/T/idea_working_dirs_testng.tmp -temp /private/var/folders/6f/cm41jlqd0vbfmj_f6nwv7tf4sskhh6/T/idea_testng.tmp
objc[22396]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
[TestNG] Running:
/Users/gunuputis4r/Library/Caches/IdeaIC2017.1/temp-testng-customsuite.xml

org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: Unhandled endpoint: /session/F2666989-60EC-4F12-AAD9-AF8BC69D7296/wda/dragfromtoforduration – http://localhost:8100/ with parameters {
wildcards = (
“session/F2666989-60EC-4F12-AAD9-AF8BC69D7296/wda/dragfromtoforduration”
);
} (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 13 milliseconds
Build info: version: ‘2.48.2’, revision: ‘41bccdd10cf2c0560f637404c2d96164b67d9d67’, time: ‘2015-10-09 13:08:06’
System info: host: ‘WS054576’, ip: ‘10.25.18.171’, os.name: ‘Mac OS X’, os.arch: ‘x86_64’, os.version: ‘10.11.6’, java.version: ‘1.8.0_60’
Driver info: io.appium.java_client.ios.IOSDriver
Capabilities [{app=/Users/gunuputis4r/Documents/Intellijiworkspace/KidsIviewPhonesAutomation/src/test/resources/com/kidsIview/mobileApps/kidsiviewiphone.ipa, networkConnectionEnabled=false, bundleId=au.net.abc.kids-iview, databaseEnabled=false, deviceName=Abc_iPhone6plus, platform=MAC, platformVersion=10.0, webStorageEnabled=false, locationContextEnabled=false, browserName=, takesScreenshot=true, javascriptEnabled=true, udid=4c7399acc39cb0e3b8609e6d069c5f619700b70d, platformName=iOS}]
Session ID: c8dadbdf-70ac-4134-b45e-88fed4b6c89c

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:206)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:158)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:647)
at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:42)
at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
at io.appium.java_client.ios.IOSDriver.execute(IOSDriver.java:1)
at io.appium.java_client.AppiumDriver.performTouchAction(AppiumDriver.java:314)
at io.appium.java_client.TouchAction.perform(TouchAction.java:301)
at io.appium.java_client.AppiumDriver.swipe(AppiumDriver.java:369)
at com.kidsIview.util.Util.swipeUp(Util.java:125)
at com.kidsIview.tests.HomePageTest.checkHomePageSwiping(HomePageTest.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:86)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:643)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:820)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1128)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
at org.testng.TestRunner.privateRun(TestRunner.java:782)
at org.testng.TestRunner.run(TestRunner.java:632)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
at org.testng.SuiteRunner.run(SuiteRunner.java:268)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1169)
at org.testng.TestNG.run(TestNG.java:1064)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:127)

can some one suggest me what I am doing wrong on this.

on javaclient 5,appium is throwing swipe method is not supported.

Hi,

Though the code seems naive it doesn’t work for me.

This is the function I am using however, it fails (see below log).
What am I missing?

public void swipeUpIpone6Action(IOSDriver driver){
int StartX=200;
int StartY = 150;
int EndX=200;
int EndY = 500;
TouchAction a1 = new TouchAction (driver);
a1.tap(StartX, StartY).moveTo(EndX, EndY).waitAction(2000).release().perform();

============================================

[debug] [MJSONWP] Responding to client with driver.postAcceptAlert() result: {}
[HTTP] <-- POST /wd/hub/session/84880183-270e-4b3a-b95c-f7c1e616ef91/accept_alert 200 4526 ms - 74
[debug] [XCUITest] Connection to WDA timed out
[debug] [iProxy] recv failed: Operation not permitted
[HTTP] --> POST /wd/hub/session/84880183-270e-4b3a-b95c-f7c1e616ef91/touch/perform {“actions”:[{“action”:“tap”,“options”:{“x”:200,“y”:150}},{“action”:“moveTo”,“options”:{“x”:200,“y”:500}},{“action”:“wait”,“options”:{“ms”:2000}},{“action”:“release”,“options”:{}}]}
[debug] [MJSONWP] Calling AppiumDriver.performTouch() with args: [[{“action”:“tap”,“options”:{“x”:200,“y”:150}},{“action”:“moveTo”,“options”:{“x”:200,“y”:500}},{“action”:“wait”,“options”:{“ms”:2000}},{“action”:“release”,“options”:{}}],“84880183-270e-4b3a-b95c-f7c1e616ef91”]
[debug] [XCUITest] Executing command ‘performTouch’
[debug] [XCUITest] Received the following touch action: tap(options={“x”:200,“y”:150})-moveTo(options={“x”:200,“y”:500})-wait(options={“ms”:2000})-release(options={})
[HTTP] <-- POST /wd/hub/session/84880183-270e-4b3a-b95c-f7c1e616ef91/touch/perform 501 6 ms - 636

@menypeled you missed that swipe is different for android and iOS. Look at mine code for differences.

What would be the best code to scroll down to another button?

    //Enter the code for "Edit Profile"
    driver.findElement(By.id(editprofile)).click();

    //Scroll down
    
    
    //Click Change Password button
    driver.findElement(By.id(changePassword)).click();

@Vell_Jackson you did not mention platform but e.g. for Android i use mostly UiScrollable

@Aleksei Yes sorry about that Im running on Android platform, and I need an example of the code UiScrollable for that spot if you don’t mind.

@Vell_Jackson and did you try that i mentioned above? public boolean tapByText(String text) ?

Yes I see your example.

indent preformatted text by 4 [email protected]
    public void ChangePass(int startX, int startY, int endX, int endY, int duration) throws InterruptedException {

    WebDriverWait wait = new WebDriverWait(driver, 25);
    wait.until(ExpectedConditions.elementToBeClickable(By.id(myprofile)));

    //Click the profile icon
    driver.findElement(By.id(myprofile)).click();

    //Click the sign in button
    driver.findElement(By.id(sign)).click();

    //Enter Username
    driver.findElement(By.id(enterUsernameButton)).sendKeys("[email protected]ator.com");

    //Enter Password
    driver.findElement(By.id(enterPasswordButton)).sendKeys("Soni2017");

    //Tap the DONE button
    driver.findElement(By.id(signUpDoneButton)).click();

    wait = new WebDriverWait(driver, 15);
    wait.until(ExpectedConditions.elementToBeClickable(By.id(myprofile)));

    driver.findElement(By.id(myprofile)).click();

    driver.findElement(By.id(name)).click();

    if (!driver.findElements(By.id(editprofile)).isEmpty()) {
        Thread.sleep(1000);
        driver.findElement(By.id(editprofile)).click();

    } else {
        Thread.sleep(2000);
        driver.findElement(By.xpath(ediProfile)).click();

    }
    //Enter the code for "Edit Profile"
    //Insert a code that scrolls down to the bottom of the screen
    // Scroll down
    // X[63,904]
    // Y[365,9771

    new TouchAction((MobileDriver) driver).press(startX, startY).waitAction(Duration.ofMillis(5000)).moveTo(endX, endY).release().perform();

    //Change Password button
    driver.findElement(By.id(changePassword)).click();

After adding in your example it gave me an error saying:

java.lang.Exception: Method ChangePass should have no parameters

Hi Aleksei,

I was trying out your code. Initially it will open Settings App in IOS and execute below code. But it is not scrolling to “Battery” option.

public boolean scrollToDirection_iOS_XCTest() {
		MobileElement el = (MobileElement)aDriver.findElement(By.xpath("//*[@value='Battery']"));
		String direction = "d";
        // The main difference from swipe call with the same argument is that scroll will try to move
        // the current viewport exactly to the next/previous page (the term "page" means the content,
        // which fits into a single device screen)
        try {
            JavascriptExecutor js = (JavascriptExecutor) aDriver;
            HashMap<String, String> scrollObject = new HashMap<String, String>();
            if (direction.equals("d")) {
                scrollObject.put("direction", "down");
            } else if (direction.equals("u")) {
                scrollObject.put("direction", "up");
            } else if (direction.equals("l")) {
                scrollObject.put("direction", "left");
            } else if (direction.equals("r")) {
                scrollObject.put("direction", "right");
            }
            scrollObject.put("element", el.getId());
            scrollObject.put("toVisible", "true"); // optional but needed sometimes
            js.executeScript("mobile:scroll", scrollObject);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

@mathewkuruvila did you check that it was able find your battery element before starting scroll?

Yes. It was able to find that out.

Same issue here, anyone has found any success in it.

If somebody looking for solution for Swipe, Scroll for native apps on Android and iOS this is how I achieved

Android

  1. Based on co-ordinates technique

new TouchAction(driver).press(115, 650).waitAction(ofSeconds(1)).moveTo(115, 350).release().perform();

  1. Not sure if it’s possible to do with particular element ?

iOS

JavascriptExecutor js = (JavascriptExecutor) driver;
HashMap<String, String> swipeObject = new HashMap<String, String>();

  1. Method 1

        swipeObject.put("element", mobileElementToTakeActionUpon.getId());
        swipeObject.put("direction", "up");
        js.executeScript("mobile: swipe", swipeObject);
    

limitation - does more swipe than expected

  1. Method 2

         swipeObject.put("element", itemsViewTopRow.getId());
         swipeObject.put("direction", "down");
         swipeObject.put("toVisible", "true");
         js.executeScript("mobile: scroll", swipeObject);
    
  2. Co-ordinates based

         swipeObject.put("direction", "down"); //up for swipe
         swipeObject.put("startX", "90");
         swipeObject.put("startY", "400");
         swipeObject.put("endX", "90"); //"90");
         swipeObject.put("endY", "350"); //"200");
         swipeObject.put("duration", "2000");
         //js.executeScript("mobile: swipe", swipeObject); 
         js.executeScript("mobile: scroll", swipeObject);
    

limitation - does more swipe than expected

------- Bugs Found during this exercise -------

  1. https://github.com/appium/java-client/issues/784

  2. https://github.com/appium/java-client/issues/783

  3. https://github.com/appium/java-client/issues/785

  4. https://github.com/appium/appium/issues/9771

  5. https://github.com/appium/appium/issues/7914

I hope it helps and in case some info is missing / incorrect please add to thread.

Regards,
Vikram

2 Likes

Using your method for Android, I get the below error in appium logs when I try for a horizontal swipe right to left. Using 5.0.4 and appium 1.7.2. Any ideas?

	t.press(1000, 1500).waitAction(Duration.ofMillis(1000)).moveTo(0, 1500).release().perform();

[HTTP] --> POST /wd/hub/session/cd1cd37c-110a-43c6-a808-b6ff3eac33ac/touch/perform {“actions”:[{“action”:“press”,“options”:{“x”:1000,“y”:1500}},{“action”:“moveTo”,“options”:{“x”:0,“y”:1500}},{“action”:“release”,“options”:{}}]}
[debug] [MJSONWP] Calling AppiumDriver.performTouch() with args: [[{“action”:“press”,“options”:{“x”:1000,“y”:1500}},{“action”:“moveTo”,“options”:{“x”:0,“y”:1500}},{“action”:“release”,“options”:{}}],“cd1cd37c-110a-43c6-a808-b6ff3eac33ac”]
[debug] [AndroidBootstrap] Sending command to android: {“cmd”:“action”,“action”:“element:touchDown”,“params”:{“x”:1000,“y”:1500}}
[debug] [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {“cmd”:“action”,“action”:“element:touchDown”,“params”:{“x”:1000,“y”:1500}}
[debug] [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command of type ACTION
[debug] [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command action: touchDown
[debug] [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Display bounds: [0,0][1080,1920]
[debug] [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Performing TouchDown using element? false x: 1000, y: 1500
[debug] [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Returning result: {“status”:13,“value”:“Failed to execute touch event”}
[debug] [AndroidBootstrap] Received command result from bootstrap
[HTTP] <-- POST /wd/hub/session/cd1cd37c-110a-43c6-a808-b6ff3eac33ac/touch/perform 500 34 ms - 154

Best
Vince

your appium java client version is very old, can you use latest one from https://github.com/appium/java-client/releases

I believe (5.0.4) is the latest that was actually released, 6.* are in beta.