CalcSnippets
Mobile Development 4 min read

`ANDROID_HOME` and `ANDROID_SDK_ROOT`: Keep One SDK Path

Two Android SDK variables that point at different folders create confusing license and build failures. Make the selected SDK explicit and verify the executable path.

The mismatch is usually more important than the variable name

Android tools have accumulated both ANDROID_HOME and ANDROID_SDK_ROOT. Older guides often set one, newer tools may inspect both, and a machine can end up with values left over from Android Studio, a shell profile, or a CI image. If the variables point to different SDK directories, one command can accept licenses while another still reports them missing.

Print both values in the same shell that runs Flutter or Gradle:

printf 'HOME=%s\nROOT=%s\n' "$ANDROID_HOME" "$ANDROID_SDK_ROOT"
which adb
which sdkmanager

Then inspect the resolved executables. A correct-looking environment variable is not proof that PATH uses that installation.

Choose one directory and align the shell

On macOS, a common location is $HOME/Library/Android/sdk; Linux installations vary. Set both variables to the selected directory if your toolchain expects both, then prepend its platform-tools and cmdline-tools/latest/bin directories to PATH. Avoid adding a second SDK because a command cannot be found until you know which installation you intend to maintain.

Open a new terminal after editing the startup file, or source the file explicitly. Verify again with printf, command -v adb, and sdkmanager --list. Finally run flutter doctor -v and compare the SDK path it reports with the one you selected.

If Android Studio uses another SDK directory, update its SDK Location setting or deliberately point the command-line workflow at that location. The goal is not to prefer one variable universally; it is to make every participating tool resolve the same SDK and prove it from output.

Trace the value from your login shell to the build process

One subtle source of confusion is that a terminal window, an IDE, and a CI job do not necessarily inherit the same environment. A shell opened from a desktop launcher may read a different startup file than an interactive terminal. Android Studio may also retain its own SDK selection even after you change a shell variable. Capture the environment at the point of failure instead of assuming that the settings you inspected are the ones Gradle received.

On macOS, inspect the shell in which you run Flutter, and compare it with the SDK location shown in Android Studio. In a Gradle build, the local sdk.dir value in local.properties can be another path selector. That file is machine-specific and is commonly excluded from version control, so do not copy a path from another developer's laptop into a shared repository unless your project has a deliberate convention for it. In CI, install the command-line tools into a known directory and set the path in the job environment before invoking Gradle. Printing the values near the beginning of the job makes later logs interpretable.

Check PATH in order, not just for presence. If an older platform-tools directory appears first, command -v adb may resolve to a binary from a different SDK even though ANDROID_HOME is correct. type -a adb can reveal multiple candidates in shells that support it. Remove stale entries from shell startup files rather than appending yet another SDK directory each time a build breaks. A machine with one canonical SDK is easier to update and easier to explain to a teammate.

Make SDK installation reproducible

The SDK directory alone does not define a complete build environment. Record the required platform, build-tools, command-line tools, and accepted licenses in the setup instructions or CI provisioning. Install only versions the project actually needs, and review SDK upgrades like other toolchain changes. A build that succeeds because a developer has an unrecorded platform package installed is not reproducible.

After aligning the paths, run the failing command from a fresh shell and note the selected SDK, adb path, Java version, and Flutter diagnostic output. If the command line succeeds but Android Studio fails, compare its configured SDK path and Gradle JDK. If Android Studio succeeds but CI fails, compare the runner's installed packages and environment rather than changing application code. This turns a vague “Android cannot find the SDK” report into a short list of observable differences.

Avoid exporting SDK paths globally for unrelated projects if you switch between isolated toolchains. A project bootstrap script can set local values for a controlled command, while a team setup guide can document the default installation. The important rule is consistency at the process boundary: the SDK manager that installs packages, the ADB client that talks to devices, and the Gradle build that consumes them should all be traceable to the same intended installation.

Keep reading

Related guides