I am trying to start Appium programmatically but I keep getting this error:
org.openqa.selenium.SessionNotCreatedException: Unable to create a new remote session. Please check the server log for more details. Original error: An unknown server-side error occurred while processing the command. Original error: Neither ANDROID_HOME nor ANDROID_SDK_ROOT environment variable was exported. Read https://developer.android.com/studio/command-line/variables for more details
However, if I run echo $ANDROID_HOME
it returns the correct path, and in addition to this, I have explicitly specified the environment variables in my AppiumServiceBuilder object. Here is the code that kicks off my Appium server:
import Pages.LoginPage;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.remote.MobileCapabilityType;
import io.appium.java_client.screenrecording.CanRecordScreen;
import io.appium.java_client.service.local.AppiumDriverLocalService;
import io.appium.java_client.service.local.AppiumServiceBuilder;
import io.appium.java_client.service.local.flags.GeneralServerFlag;
import org.apache.commons.codec.binary.Base64;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.annotations.*;
import java.io.*;
import java.net.URL;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Properties;
public class BaseTest {
AppiumDriver driver;
protected Properties props;
InputStream inputStream;
LoginPage loginPage;
static Logger log = LogManager.getLogger(BaseTest.class.getName());
private static AppiumDriverLocalService server;
private static int OS = 2; // 1 = Windows, 2 = Ubuntu
@BeforeSuite
public void beforeSuite(){
server = getAppiumServer();
if(!server.isRunning()){
log.info("Starting Appium Server");
server.start();
}
}
@Parameters({"platformName", "deviceName"})
@BeforeTest
public void beforeTest(String platformName, String deviceName, ITestContext context) throws Exception {
log.info("Here is a log");
props = new Properties();
String propFileName="config.properties";
inputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
props.load(inputStream);
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability(MobileCapabilityType.PLATFORM_NAME, platformName);
caps.setCapability(MobileCapabilityType.DEVICE_NAME, deviceName);
caps.setCapability(MobileCapabilityType.AUTOMATION_NAME, props.getProperty("androidAutomationName"));
caps.setCapability(MobileCapabilityType.UDID, "emulator-5554");
caps.setCapability("newCommandTimeout", 300);
//start emulator automatically
caps.setCapability("avd", "Nexus_5_API_30"); // value is the AvdId found in Android Studio emulated device details
caps.setCapability("avdLaunchTimeout", 180000); // set timeout to allow time for emulator to launch
caps.setCapability("appPackage", props.getProperty("androidAppPackage"));
caps.setCapability("appActivity", props.getProperty("androidAppActivity"));
String appUrl = System.getProperty("user.dir") + File.separator + "src" + File.separator +
"main" + File.separator + "resources" + File.separator + props.getProperty("androidApkName");
caps.setCapability(MobileCapabilityType.APP, appUrl);
URL as = new URL(props.getProperty("appiumUrl"));
driver = new AndroidDriver(as, caps);
context.setAttribute("WebDriver", driver);
loginPage = new LoginPage(driver);
}
@BeforeMethod
public void beforeMethod(){
// Record the screen during the test
((CanRecordScreen) driver).startRecordingScreen();
}
@AfterMethod
public void afterMethod(ITestResult result) throws IOException {
String media = ((CanRecordScreen) driver).stopRecordingScreen(); // Returns base64 encoded screen recording
if(!result.isSuccess()){ // This will only save the screen recording if the test fails
String dir = "videos" + File.separator + result.getTestClass().getRealClass().getName()
+ File.separator + result.getMethod().getMethodName();
File videoDir = new File(dir);
if(!videoDir.exists()){
videoDir.mkdirs();
}
FileOutputStream stream = new FileOutputStream(videoDir + File.separator +
Calendar.getInstance().getTime().toString().replace(":", "-") + ".mp4");
stream.write(Base64.decodeBase64(media));
}
}
@AfterTest
public void afterTest() throws IOException {
driver.quit();
if(inputStream != null){
inputStream.close();
}
}
@AfterSuite
public void afterSuite(){
log.info("Stopping Appium Server");
server.stop();
}
public AppiumDriver getDriver() {
return driver;
}
public AppiumDriverLocalService getAppiumServer(){
log.info("Building Appium Server");
switch(OS){
case 1:
return AppiumDriverLocalService.buildDefaultService();
case 2:
HashMap<String, String> environment = new HashMap<>();
environment.put("PATH", "/home/wade/.yarn/bin:/home/wade/.config/yarn/global/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/home/wade/Android/Sdk:/home/wade/Android/Sdk/tools:/home/wade/Android/Sdk/platform-tools:/home/wade/Android/Sdk/tools/bin:/usr/lib/jvm/jdk-15.0.2" + System.getenv("PATH"));
environment.put("ANDROID_HOME", "/home/wade/Android/Sdk");
environment.put("JAVA_HOME", "/usr/lib/jvm/jdk-15.0.2");
return AppiumDriverLocalService.buildService(new AppiumServiceBuilder().
usingDriverExecutable(new File("/usr/bin/node")).
withAppiumJS(new File("/usr/local/lib/node_modules/appium/build/lib/main.js")).
usingPort(4723).
withArgument(GeneralServerFlag.SESSION_OVERRIDE).
withEnvironment(environment));
default:
return null;
}
}
}
So I am really confused as to why this error is still happening.
P.S. I am using IntelliJ IDEA and my OS is Ubuntu 22.04.1.
This is what the relevant section in my bashrc file looks like:
export ANDROID_HOME=$HOME/Android/Sdk
export PATH=$PATH:$ANDROID_HOME
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export JAVA_HOME=/usr/lib/jvm/jdk-15.0.2
export PATH=$PATH:$JAVA_HOME
export JAVA_HOME
export JRE_HOME
export PATH
What am I missing?