A Java Appium 2.0 code to run Android app on Mac device and BrowserStack.

Sameera De Silva
4 min readApr 15, 2024

--

In latest appium 2.0 , let’s look at how to run an android app. Here ,I mainly discuss the coding part , neither installation or configuration.

To demonsrate this I use the apk from https://github.com/saucelabs/my-demo-app-rn/releases/

I created a Maven Java project and my pom.xml is as per below.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>Appium2.0</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<!-- https://mvnrepository.com/artifact/io.appium/java-client -->
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>9.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.10.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.browserstack/browserstack-local-java -->
<dependency>
<groupId>com.browserstack</groupId>
<artifactId>browserstack-local-java</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
</project>

Running on Local Mac device.

First let’s look at how to run this locally.

Assume that in Mac terminal you set path before using nano ~/.zshrc

To see the environment variables
nano ~/.zshrc

To edit
nano -w ~/.zshrc

export ANDROID_HOME=/users/myusername/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH="/opt/homebrew/opt/openjdk/bin:$PATH"
export PATH="/usr/local/opt/openjdk@21/bin:$PATH"
export JAVA_HOME=/opt/homebrew/opt/openjdk
export path=$JAVA_HOME
export PATH="$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/emulator

Then to save press Ctrl+O
Press enter so it will be saved to the same file
Press Ctrl+X to exit the editor.

Reenter nano ~/.zshrc to see the changes are saved

Also can type each variable and see its print the path.
echo $ANDROID_HOME

I’ll start the emulator via ac terminal. Using below commands

This line changes the directory to the location of the emulator executable within the Android SDK.
cd /users/myusername/Library/Android/sdk/emulator

This command lists all the available Android Virtual Devices (AVDs) that you have created in the Android SDK. This is useful to verify which AVDs are available.

./emulator -list-avds

This command launches the emulator with the specified AVD name. Replace {AVD_NAME} with the actual name of the AVD you want to use.
./emulator -avd {AVD_NAME}
./emulator -avd Pixel_4_API_VanillaIceCream

what does ./ mean?

On Unix-based systems (macOS and Linux), ./ is used to indicate a relative path starting from the current working directory. In this case, ./emulator refers to the emulator executable within the current directory.

Tip-

If needed , you type below command in terminal and see where appium is installed.

which appium

if you installed appium via nom, use

npm list -g appium

Respectively output as per below.

/opt/homebrew/bin/appium


/opt/homebrew/lib
└── appium@2.5.1

Before running the code I’ll start the Appium server in localhost.

To start Appium server via command line

appium — address <IP_address> — port <port>

appium — address 127.0.0.1 — port 4723

To see the appium server is up
http://127.0.0.1:4723/status

Then i’ll execute the below Java TestNG code to run locally.

package com.test;

import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;
import io.appium.java_client.remote.AutomationName;
import org.openqa.selenium.WebElement;
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.net.URL;

public class AndroidOnly {

@Test
void androidLaunchTest() throws MalformedURLException, InterruptedException {

UiAutomator2Options options = new UiAutomator2Options();
options.setAutomationName(AutomationName.ANDROID_UIAUTOMATOR2);
options.setPlatformName("Android"); //optional
options.setPlatformVersion("14"); //Optional
options.setDeviceName("emulator-5554");
options.setApp(System.getProperty("user.dir") + "/apps/Android-MyDemoAppRN.1.3.0.build-244.apk");
options.setAppActivity("com.saucelabs.mydemoapp.rn.MainActivity");
AndroidDriver driver = new AndroidDriver(new URL("http://127.0.0.1:4723"), options);
WebElement shoppingCardIcon= driver.findElement(AppiumBy.accessibilityId("cart badge"));
shoppingCardIcon.click();
WebElement goShoppingButton=driver.findElement(AppiumBy.xpath("//*[contains(@text, 'Go Shopping')]"));
goShoppingButton.click();

}
}

Running on Browserstack

Now let’s see how to run on BrowserStack. For that , you need below maven dependency.

<!-- https://mvnrepository.com/artifact/com.browserstack/browserstack-local-java -->
<dependency>
<groupId>com.browserstack</groupId>
<artifactId>browserstack-local-java</artifactId>
<version>1.1.1</version>
</dependency>

Also it goes without saying that you need a BrowserStack account. Log to it and upload your apk file and copy the link it provides.

So instead of giving the local app path as below , we must give that path.

    // options.setApp(System.getProperty("user.dir") + "/apps/Android-MyDemoAppRN.1.3.0.build-244.apk");

Give the copied path of the app that uploaded to BrowserStack

        options.setApp("bs://b8409681b"); // upload your app and copy the path they sent.

The apps you uploaded are listed in and can be viewed as a Json.

https://api-cloud.browserstack.com/app-automate/recent_apps

Also in ACCESS KEY tab of BrowserStack, you could copy the username and accesskey.

Now , you can use the below modfied code.

package com.test;

import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;
import io.appium.java_client.remote.MobilePlatform;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.net.URL;

public class BrowserStackAppiumTestAndroid {

@Test
public void launchAndroidAppInBrowserStack() throws MalformedURLException {
// Replace with your BrowserStack credentials (if provided)
String userName = "myusername";
String accessKey = "mykey";
// Replace with your actual values or retrieve them dynamically
String deviceName = "Google Pixel 4 XL";
String osVersion = "10.0";
//http://your_username:your_access_key@hub-cloud.browserstack.com/wd/hub
String url = "http://" + userName + ":" + accessKey + "@hub-cloud.browserstack.com/wd/hub";

UiAutomator2Options options = new UiAutomator2Options();
options.setPlatformName(MobilePlatform.ANDROID);
options.setDeviceName(deviceName);
options.setPlatformVersion(osVersion);
options.setAutomationName("UiAutomator2");
// we can't do like ths by givng path locally throws Could not start a new session. Possible causes are invalid address of the remote server or browser start-up failure.
// options.setApp(System.getProperty("user.dir") + "/apps/Android-MyDemoAppRN.1.3.0.build-244.apk");

// instead of setting local app path,upload your app to brwoserstack and copy the path they give.
options.setApp("bs://b8409681bed30d8010");

// You can set these directly in the options object if applicable
options.setCapability("browserstack.user", userName);
options.setCapability("browserstack.key", accessKey);
// Add other BrowserStack specific capabilities here
// Add other capabilities as needed based on BrowserStack configuration (e.g., username/access key)
AndroidDriver driver = new AndroidDriver(new URL(url), options);
WebElement shoppingCardIcon= driver.findElement(AppiumBy.accessibilityId("cart badge"));
shoppingCardIcon.click();
WebElement goShoppingButton=driver.findElement(AppiumBy.xpath("//*[contains(@text, 'Go Shopping')]"));
goShoppingButton.click();
driver.quit();
}

}

This will execute the code remotely in BroswerStack.

If you get below error due to opened BrowserStack sessions,

Either another browserstack local client is running on your machine or some server is listening on port 45690

Try below walkaround in Mac terminal.

ps -A | grep BrowserStackLocal
Kill processid

Kill 666

A list of BrowserStack devices details can be found here.

--

--

No responses yet