I’ve spent the last couple of days fighting the Android command line to set up a simple project that can run automated tests inside an emulator reliably and repeatably.
To make the tests reliable and independent from anything else on my machine, I wanted to store the Android SDK and AVD files in a local directory.
To do this I had to define a lot of inter-related environment variables, and wrap the tools in scripts that ensure they run with the right flags and settings.
The end result of this work is here: gitlab.com/andybalaam/android-skeleton
You need all the utility scripts included in that repo for it to work, but some highlights include:
The environment variables that I source in every script, scripts/paths:
PROJECT_ROOT=$(dirname $(dirname $(realpath ${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}))) export ANDROID_SDK_ROOT="${PROJECT_ROOT}/android_sdk" export ANDROID_SDK_HOME="${ANDROID_SDK_ROOT}" export ANDROID_EMULATOR_HOME="${ANDROID_SDK_ROOT}/emulator-home" export ANDROID_AVD_HOME="${ANDROID_EMULATOR_HOME}/avd"
Creation of a local.properties file that tells Gradle and Android Studio where the SDK is, by running something like this:
echo "# File created automatically - changes will be overwritten!" > local.properties echo "sdk.dir=${ANDROID_SDK_ROOT}" >> local.properties
The wrapper scripts for Android tools e.g. scripts/sdkmanager:
#!/bin/bash set -e set -u source scripts/paths "${ANDROID_SDK_ROOT}/tools/bin/sdkmanager" \ "--sdk_root=${ANDROID_SDK_ROOT}" \ "$@"
The wrapper for avdmanager is particularly interesting since it seems we need to override where it thinks the tools directory is for it to work properly – scripts/avdmanager:
#!/bin/bash set -e set -u source scripts/paths # Set toolsdir to include "bin/" since avdmanager seems to go 2 dirs up # from that to find the SDK root? AVDMANAGER_OPTS="-Dcom.android.sdkmanager.toolsdir=${ANDROID_SDK_ROOT}/tools/bin/" \ "${ANDROID_SDK_ROOT}/tools/bin/avdmanager" "$@"
An installation script that must be run once before using the project scripts/install-android-tools:
#!/bin/bash set -e set -u set -x source scripts/paths mkdir -p "${ANDROID_SDK_ROOT}" mkdir -p "${ANDROID_AVD_HOME}" mkdir -p "${ANDROID_EMULATOR_HOME}" # Download sdkmanager, avdmanager etc. cd "${ANDROID_SDK_ROOT}" test -f commandlinetools-*.zip || \ wget -q 'https://dl.google.com/android/repository/commandlinetools-linux-6200805_latest.zip' unzip -q -u commandlinetools-*.zip cd .. # Ask sdkmanager to update itself ./scripts/sdkmanager --update # Install the emulator and tools yes | ./scripts/sdkmanager --install 'emulator' 'platform-tools' # Platforms ./scripts/sdkmanager --install 'platforms;android-21' ./scripts/sdkmanager --install 'platforms;android-29' # Install system images for our oldest and newest supported API versions yes | ./scripts/sdkmanager --install 'system-images;android-21;default;x86_64' yes | ./scripts/sdkmanager --install 'system-images;android-29;default;x86_64' # Create AVDs to run the system images echo no | ./scripts/avdmanager -v \ create avd \ -f \ -n "avd-21" \ -k "system-images;android-21;default;x86_64" \ -p ${ANDROID_SDK_ROOT}/avds/avd-21 echo no | ./scripts/avdmanager -v \ create avd \ -f \ -n "avd-29" \ -k "system-images;android-29;default;x86_64" \ -p ${ANDROID_SDK_ROOT}/avds/avd-29
Please do contribute to the project if you know easier ways to do this stuff.