Android Command line tools sdkmanager always shows: Warning: Could not create settings
I use the new command line tools for Android because the old sdk-tools repository of Android isn't available anymore. So I changed my gitlab-ci to load the commandlintools
. But when I try to run it I get the following error:
Warning: Could not create settings
java.lang.IllegalArgumentException
at com.android.sdklib.tool.sdkmanager.SdkManagerCliSettings.<init>(SdkManagerCliSettings.java:428)
at com.android.sdklib.tool.sdkmanager.SdkManagerCliSettings.createSettings(SdkManagerCliSettings.java:152)
at com.android.sdklib.tool.sdkmanager.SdkManagerCliSettings.createSettings(SdkManagerCliSettings.java:134)
at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:57)
at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:48)
I already tried executing those commandy by hand, but I get the same error. Also if I run sdkmanager --version
, the same error occurs.
My gitlab-ci looks like:
image: openjdk:9-jdk
variables:
ANDROID_COMPILE_SDK: "29"
ANDROID_BUILD_TOOLS: "29.0.3"
ANDROID_SDK_TOOLS: "6200805"
before_script:
- apt-get --quiet update --yes
- apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
- wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS}_latest.zip
- unzip -d android-sdk-linux android-sdk.zip
- echo y | android-sdk-linux/tools/bin/sdkmanager "platform-tools" "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null
#- echo y | android-sdk-linux/tools/bin/sdkmanager "platform-tools" >/dev/null
- echo y | android-sdk-linux/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null
- export ANDROID_HOME=$PWD/android-sdk-linux
- export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
- chmod +x ./gradlew
# temporarily disable checking for EPIPE error and use yes to accept all licenses
- set +o pipefail
- yes | android-sdk-linux/tools/bin/sdkmanager --licenses
- set -o pipefail
stages:
- build
- test
lintDebug:
stage: build
script:
- ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint
assembleDebug:
stage: build
script:
- ./gradlew assembleDebug
artifacts:
paths:
- app/build/outputs/
debugTests:
stage: test
script:
- ./gradlew -Pci --console=plain :app:testDebug
Instead of passing the argument --sdk_root
for each single command execution, let's deep dive into the real cause.
Starting from Android SDK Command-line Tools 1.0.0 (6200805), in contrast to Android SDK 26.1.1 (4333796), the tools
directory hierarchy has been changed.
Previously it was placed right inside ANDROID_HOME
(which is deprecated, we will use the term ANDROID_SDK_ROOT
for the rest of the paragraph), now it's still named as tools
(the only thing you'll get after unpacking the downloaded commandlinetools zip file), but differently, you have to place it inside a directory called cmdline-tools
on your own. The name cmdline-tools
comes from its package name, where you can get from listing packages command sdkmanager --list
, whose outputs include cmdline-tools;1.0 | 1.0 | Android SDK Command-line Tools
.
Wrapping tools
directory inside cmdline-tools
directory would make it work, and help you get rid of the annoying --sdk_root
argument. But what about the other parts?
Well, that's all you have to change. Let me explain more.
- The king -
sdkmanager
lives insidecmdline-tools/tools/bin
, you'd better set inPATH
environment variable -
cmdline-tools
should not be set asANDROID_SDK_ROOT
. Because later, when updating Android SDK, or installing more packages, the other packages will be placed underANDROID_SDK_ROOT
, but not undercmdline-tools
. - The final, complete
ANDROID_SDK_ROOT
directory structure should look like below, consist of quite a few sub-directories:build-tools
,cmdline-tools
,emulator
,licenses
,patcher
,platform-tools
,platforms
,system-images
. You can easily point out thatbuild-tools
andcmdline-tools
are siblings, all sit inside the parentANDROID_SDK_ROOT
.
Let me recap in a simple way:
- Set your preferred
ANDROID_SDK_ROOT
(just like before) - Download and unpack the commandlinetools zip file into a directory called
cmdline-tools
, which is insideANDROID_SDK_ROOT
- Append the directory
$ANDROID_SDK_ROOT/cmdline-tools/tools/bin
to environment variablePATH
, so that the system knows where to findsdkmanager
!!UPDATE!!
The behavior has changed again since the build 6858069
(Android SDK Command-line Tools 3.0):
- After unzipping the package, the top-most directory you'll get is
cmdline-tools
. - Rename the unpacked directory from
cmdline-tools
totools
, and place it under$ANDROID_SDK_ROOT/cmdline-tools
, so now it should look like:$ANDROID_SDK_ROOT/cmdline-tools/tools
. And inside it, you should have:NOTICE.txt bin lib source.properties
. Actually according to the official Command-Line Tools doc, the tree structure should beandroid_sdk/cmdline-tools/version/bin/
, but I've checked, usingversion
ortools
makes no difference here. - For your environment variable
PATH
, I would recommend you to set like this:PATH=$PATH:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$ANDROID_SDK_ROOT/cmdline-tools/tools/bin
, because after update later, you'll get the latestsdkmanager
placed under$ANDROID_SDK_ROOT/cmdline-tools/latest/bin
, put it in front will make it higher priority.
This appears to be a bug with the way sdkmanager locates the SDK installation folder.
A work-around is to set the flag --sdk_root
. You can move ANDROID_HOME declaration higher, then use it with the subsequent commands.
- export ANDROID_HOME=$PWD/android-sdk-linux
- yes | android-sdk-linux/tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} --licenses
- android-sdk-linux/tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} "platform-tools" "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null
Also, moved blanket license acceptance command to the first command to clean up the echo y
parts.
Oddly enough if you run sdkmanager --sdk_root=${ANDROID_HOME} "tools"
it will upgrade tools from 3.6.0 to 26.1.1 and sdkmanager no longer has this issue. This update takes time and bandwidth and isn't exactly necessary with the work-around.