Emulator setup
Basically we have next choices:
- Manage devices automatically by
avd
- Manage docker containers with emulators by
docker
Using docker image is the easiest way, however it's important to understand how docker creates device for you.
Creating an emulator
Before starting to read this topic, make sure you've read an an official documentation
Firstly, you need to create an ini
configuration:
PlayStore.enabled=false
abi.type=x86_64
avd.ini.encoding=UTF-8
hw.cpu.arch=x86_64
hw.cpu.ncore=2
hw.ramSize=2048
hw.lcd.density=120
hw.lcd.width=320
hw.lcd.height=480
hw.audioInput=no
hw.audioOutput=no
hw.accelerometer=no
hw.gyroscope=no
hw.dPad=no
hw.mainKeys=yes
hw.keyboard=no
hw.sensors.proximity=no
hw.sensors.magnetic_field=no
hw.sensors.orientation=no
hw.sensors.temperature=no
hw.sensors.light=no
hw.sensors.pressure=no
hw.sensors.humidity=no
hw.sensors.magnetic_field_uncalibrated=no
hw.sensors.gyroscope_uncalibrated=no
image.sysdir.1=system-images/android-29/google_apis/x86_64/
tag.display=Google APIs
tag.id=google_apis
skin.dynamic=yes
skin.name=320x480
disk.dataPartition.size=8G
Pay your attention that we disabled:
- Accelerometer
- Audio input/output
- Play Store
- Sensors:Accelerometer, Humidity, Pressure, Light
- Gyroscope
We don't really need them for our tests run. It also may improve our tests performance, because there are no background operations related to that tasks.
After that, you can run your emulator by avd manager
, which is a part of android sdk manager. After your device
creation, you need change default generated ini file to custom one. You may see an example below:
function define_android_sdk_environment_if_needed() {
android_env=$(printenv ANDROID_HOME)
if [ -z "$android_env" ]; then
if [[ -d "$HOME/Library/Android/sdk" ]]; then
export ANDROID_HOME="$HOME/Library/Android/sdk"
else
printf "Can't locate your android sdk. Please set ANDROID_HOME manually"
exit
fi
fi
}
function define_path_environment_if_needed() {
if ! command -v adb &>/dev/null; then
export PATH=~/Library/Android/sdk/tools:$PATH
export PATH=~/Library/Android/sdk/platform-tools:$PATH
fi
}
function create_and_patch_emulator() {
EMULATOR_API_VERSION=29
EMULATOR_NAME="ui_tests_emulator_api_${EMULATOR_API_VERSION}"
# Install sdk
$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "system-images;android-${EMULATOR_API_VERSION};google_apis;x86_64"
# Create new emulator
echo "no" | $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager create avd --force \
--name "${EMULATOR_NAME}" \
--package "system-images;android-${EMULATOR_API_VERSION};google_apis;x86_64" \
--abi google_apis/x86_64
# Change emulator's config after emulator's creation
cp -p YOUR_INI_FILE.ini $HOME/.android/avd/${EMULATOR_NAME}.avd/config.ini
# Run new emulator
pushd ${ANDROID_HOME}/emulator/
nohup ${ANDROID_HOME}/emulator/emulator @${EMULATOR_NAME} >/dev/null 2>&1 &
}
define_android_sdk_environment_if_needed
define_path_environment_if_needed
create_and_patch_emulator
Pay your attention that you also need to wait until your emulator is fully booted.
How to run an emulator in a Docker?
Running an emulator in a docker a way easier than manually, because it encapsulates all this logic. If you don't have an experience with docker, you can check this guide to check the basics.
There are some popular already built docker images for you:
Talking about Avito emulator, it also patches your emulator with adb commands to prevent tests flakiness and to speed them up
Run Avito emulator
#run emulator 1 in a headless mode
docker run -d -p 5555:5555 -p 5554:5554 -p 8554:8554 --privileged avitotech/android-emulator-29:915c1f20be
adb connect localhost:5555
#run emulator 2 in a headless mode
docker run -d -p 5557:5555 -p 5556:5554 -p 8555:8554 --privileged avitotech/android-emulator-29:915c1f20be
adb connect localhost:5557
#run emulator 3 in a headless mode
docker run -d -p 5559:5555 -p 5558:5554 -p 8556:8554 --privileged avitotech/android-emulator-29:915c1f20be
adb connect localhost:5559
#...etc
Stop all emulators
docker kill $(docker ps -q)
docker rm $(docker ps -a -q)
Conclusion
-
Use docker emulators You also will have an opportunity to run them with
Kubernetes
, to make it scalable in the future -
Start fresh emulators each test batch and kill them after all of your tests finished Emulators tend to leak and may not work properly after some time
-
Use the same emulator as on CI locally All devices are different. It can save you a lot of time with debugging and understanding why your test works locally and fails on CI. It won't be possible to run Docker emulator on macOS or Windows, because of haxm#51. Use AVD to launch them on such machines (script above may help you)
Warning
To run an emulator on CI with a docker, make sure that nested virtualisation supported and KVM installed. You can check more details here