quittle / gradle-android-emulator

Gradle plugin for starting the Android Emulator when running instrumentation tests

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

JAVA_HOME is not set

dwb357 opened this issue · comments

Looking for a reliable way to start android emulators for CI testing and stumbled across this. Unfortunately, it doesn't seem to be working in my environment. I get the following error sequence (on a formerly working project), even if I explicitly define JAVA_HOME and java is in /usr/bin/java, on all the default paths on a Mac.

> Task :ui-android:installAndroidEmulatorSystemImage

ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation.


> Task :ui-android:installAndroidEmulatorSystemImage FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':ui-android:installAndroidEmulatorSystemImage'.
> Process 'command '/Users/dberry/Library/Android/sdk/tools/bin/sdkmanager'' finished with non-zero exit value 1

If possible, could you link me to your project or ideally the branch that doesn't work so I can play with it to help me debug?

There are a few things I'd like to confirm as part of this investigation

Does running the :ui-android:installAndroidEmulator task also fail? I expect it would, but if it doesn't that would be interesting.


You said

I get the following error sequence (on a formerly working project), even if I explicitly define JAVA_HOME and java is in /usr/bin/java

By that do you mean you set it on your path explicitly when running gradle?

$ JAVA_HOME=/usr/bin/java ./gradlew 'ui-android:installAndroidEmulatorSystemImage'

These tasks are simply Gradle ExecTasks so you should be able to set the environment variables of the exec tasks when you run explicitly by adding some code like the following in your build.gradle file. This should enforce that the JAVA_HOME that you want is made available when running sdkmanager. Can you try this and let me know if that works for you?

project.afterEvaluate {
    tasks['installAndroidEmulatorSystemImage'].environment('JAVA_HOME', '/usr/bin/java')
}

Does running the :ui-android:installAndroidEmulator task also fail? I expect it would, but if it doesn't that would be interesting.

This also fails.

By that do you mean you set it on your path explicitly when running gradle?
$ JAVA_HOME=/usr/bin/java ./gradlew 'ui-android:installAndroidEmulatorSystemImage'

I use tcsh, but yes, the moral equivalent thereof.

Can you try this and let me know if that works for you?

project.afterEvaluate {
tasks['installAndroidEmulatorSystemImage'].environment('JAVA_HOME', '/usr/bin/java')
}

Doesn't seem to change anything.

If possible, could you link me to your project or ideally the branch that doesn't work so I can play with it to help me debug?

Unfortunately, that's really not an option. I'll see if I can create a minimum reproducible failure though.

Here's a pretty minimal reproducible failure, but it's really pretty much just an empty AAR project.

moxie-mobile-sdk.zip

I will definitely try to take a look at this and reproduce your error this weekend.

Hmm, this is interesting. I've downloaded and built your example and it builds just fine. It installs the android emulator and runs to the point of failing due to there being no tests so my environment doesn't have that issue. I develop on Ubuntu and don't have access to play with a mac setup to reproduce your problem.

Could you try building with Gradle's --debug flag to see if we can get any other clues as to why java isn't available when running sdkmanager?

Here ya go.

log.txt

I am genuinely perplexed by the differences. Comparing your output vs my own it seems like gradle is reporting the same types out output aside from being unable to run successfully. Unfortunately I'm out of ideas. Do you have access to a linux machine you could try running on and see if it works there? My only guess is that your java environment setup is causing issues due to being configured differently to mine. Is there anything non-standard with your setup or the way you invoke gradle?

Nope. It's a pretty much vanilla Mac install, particularly as far as the java and android installs are concerned.

Hi @quittle and @dwb357,
I see two problems here:

  1. Plugin reports a problem with incorrect JAVA_HOME set even though the real problem is in executing sdkmanager or avdmanager command
  2. I've come accros the same problem with calling sdkmanager as @dwb357. On macOS the system image arguments need to be in quotes:
./sdkmanager system-images;android-28;default;x86
    Warning: Failed to find package system-images

./sdkmanager "system-images;android-28;default;x86"
    Runs OK!!!

The same applies when calling avdmanager.
Not sure how force the quotes when running Exec Gradle tasks.

@quittle Do you have any idea? And a Mac to test this?

Hey @xsveda, thanks for reaching out.

  1. The JAVA_HOME is indeed coming from sdkmanager. The wrapper script ($SDK_ROOT/tools/bin/sdkmanager) is just a shell script that does validation before running java on the SDK manager jar in $SDK_ROOT/tools/lib. During the validation, it appears to detect that JAVA_HOME is not set. Here is the point that I believe is displaying the output. See the last clause for the error you are seeing.
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
  1. In the context of Gradle, you don't need to quote the argument as it is not be executed from the command line. In a terminal, the shell will treat the argument as 4 different statements: ./sdkmanager system-images;android-28;default;x86 -> ./sdkmanager system-images, android-28, default, and x86. This is because ; in most shells indicates the end of a statement, so it only sees system-images as the argument, not the whole thing. In my plugin, I pass it as the only argument in the list of arguments, so I don't need to escape or otherwise handle the ; or any other character for that matter.

As far as reproducing it myself, unfortunately I don't have a Mac, just Windows and Ubuntu.

Hi @quittle, finally I've found a root cause.
The problem lays here AndroidEmulatorPlugin.java#L190:
task.setEnvironment(emulatorConfiguration.getEnvironmentVariableMap());

setEnvironment(Map) will replace all system ENV variables with only those in the map (ANDROID_SDK_ROOT and ANDROID_AVD_HOME in this case). The required JAVA_HOME is missing.

To fix it use a different API method environment(Map) that just adds new ENV variables to the original ones.
task.environment(emulatorConfiguration.getEnvironmentVariableMap());

Do you want me to create a PR?

Yeah, that would be great. Thank you for getting back to me on this issue.

This will be released under version 0.0.2 pending this build: https://travis-ci.com/quittle/gradle-android-emulator/builds/116168104

0.0.2 has been released. Can you try it out and confirm it works for you if you are using the plugin?