This article is the 17th day article of Android Advent Calendar 2020.
Android Emulator Container Scripts introduced last year, but it is said that a newly built emulator container is experimentally provided this year, so this article uses this script to use the Docker container. We will introduce the procedure for launching the Android emulator with, connecting adb, executing tests, and operating the emulator launched from a web browser.
Continuous Testing with Android Emulator Containers Android Developers Blog / Continuous testing with new Android emulator tools
As of December 17, 2020, KVM is required as described in the README, and it does not work with Docker on Mac or Windows. When running on a cloud service, you need an environment where you can use EC2 bare metal instances, enable nested virtualization, and use KVM.
-Amazon EC2 / Bare Metal Instance -Enable Nested Virtualization for Compute Engine / VM Instances (https://cloud.google.com/compute/docs/instances/enable-nested-virtualization-vm-instances)
In addition, a generator (emu-docker command) is provided when creating the image by yourself, a Python interpreter is required for execution, and Node when performing remote streaming on the Web. You will need .js and npm.
As mentioned above, a pre-built emulator container is now provided and hosted in a public repository, so you can specify it to run without building.
As of December 2020, the following is provided as an image that allows interaction with the emulator.
docker run \
-e ADBKEY="$(cat ~/.android/adbkey)" \
--device /dev/kvm \
--publish 8554:8554/tcp \
--publish 5555:5555/tcp \
us-docker.pkg.dev/android-emulator-268719/images/30-google-x64:30.1.2
Specify adbkey (private key) for the environment variable of ADBKEY
.
When adbkey performs USB debugging etc. on Android 4.2.2 or later, a dialog asking whether to accept the RSA key that allows debugging via this computer is displayed, but this key is used to protect the device. .. Normally, it is automatically generated under .android
, but it is obtained from the specified location and passed to the environment variable.
Allow docker to use KVM with --device/dev/kvm
and allow port 8554 and port 5555 to be accessible from the main machine on the same port with --publish
. The 8554 is a gRPC port used for access from Android Studio and JavaScript, and the 5555 is an ADB port.
When the container starts up and logcat is output, it's done.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2591234e0901 f202bb98c138 "/android/sdk/launch…" About a minute ago Up About a minute (healthy) 0.0.0.0:5555->5555/tcp, 0.0.0.0:8554->8554/tcp, 0.0.0.0:32768->5554/tcp zen_khorana
https://developer.android.com/studio/command-line/adb
You can make an adb connection to the emulator on Docker by adb connect
to localhost: 5555
on the main machine.
adb connect localhost:5555
adb devices
List of devices attached
localhost:5555 device
You can install apk with adb install
and run tests with connectedAndroidTest
.
./gradlew connectedAndroidTest
https://developer.android.com/studio/test/command-line
If you want to disconnect
adb disconnect
You can disconnect with.
A sample script of such a series of flows has been released, so it is a good idea to prepare a script and execute it with CI by referring to this.
There is a generator that creates an image like the one used above, and if you want to use an image or emulator that is not on the list, you can create it separately.
In order to use the various scripts provided, clone and bring the script to the main machine.
git clone [email protected]:google/android-emulator-container-scripts.git
cd android-emulator-container-scripts
Running configure.sh
makes the emu-docker
command available on python virtualenv (venv).
source ./configure.sh
emu-docker -h
usage: emu-docker [-h] [-v] {list,licenses,create,interactive,cloud-build} ...
List and create emulator docker containers (0+untagged.253.gbcb1f3f).
positional arguments:
{list,licenses,create,interactive,cloud-build}
list list all the available the publicly available
emulators and system images.
licenses Lists all licenses and gives you a chance to accept or
reject them.
create Given an emulator and system image zip file, generates
a Docker image comprising complete environment in
which the Android Emulator runs. After the Docker
image is started up, interaction with the emulator is
made possible via port forwarding and ADB, or gRPC and
WebRTC.
interactive Interactively select which system image and emulator
binary to use when creating a docker container
cloud-build Create a cloud builder distribution. This will create
a distribution for publishing container images to a
GCE repository.This is likely only useful if you are
within Google.
optional arguments:
-h, --help show this help message and exit
-v, --verbose Set verbose logging (default: False)
You can see a list of available emulators and system images with emu-docker list
.
SYSIMG K android x86 19 https://dl.google.com/android/repository/sys-img/android/x86-19_r06.zip
SYSIMG K google_apis x86 19 https://dl.google.com/android/repository/sys-img/google_apis/x86-19_r40.zip
SYSIMG L android x86 21 https://dl.google.com/android/repository/sys-img/android/x86-21_r05.zip
SYSIMG L google_apis x86 21 https://dl.google.com/android/repository/sys-img/google_apis/x86-21_r32.zip
SYSIMG L android x86 22 https://dl.google.com/android/repository/sys-img/android/x86-22_r06.zip
SYSIMG L google_apis x86 22 https://dl.google.com/android/repository/sys-img/google_apis/x86-22_r26.zip
SYSIMG M android x86 23 https://dl.google.com/android/repository/sys-img/android/x86-23_r10.zip
SYSIMG M google_apis x86 23 https://dl.google.com/android/repository/sys-img/google_apis/x86-23_r33.zip
SYSIMG N android x86 24 https://dl.google.com/android/repository/sys-img/android/x86-24_r08.zip
SYSIMG N google_apis x86 24 https://dl.google.com/android/repository/sys-img/google_apis/x86-24_r27.zip
SYSIMG N google_apis_playstore x86 24 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86-24_r19.zip
SYSIMG N android x86 25 https://dl.google.com/android/repository/sys-img/android/x86-25_r01.zip
SYSIMG N google_apis x86 25 https://dl.google.com/android/repository/sys-img/google_apis/x86-25_r18.zip
SYSIMG N google_apis_playstore x86 25 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86-25_r09.zip
SYSIMG O android x86_64 26 https://dl.google.com/android/repository/sys-img/android/x86_64-26_r01.zip
SYSIMG O android x86 26 https://dl.google.com/android/repository/sys-img/android/x86-26_r01.zip
SYSIMG O google_apis x86_64 26 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-26_r16.zip
SYSIMG O google_apis x86 26 https://dl.google.com/android/repository/sys-img/google_apis/x86-26_r16.zip
SYSIMG O google_apis_playstore x86 26 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86-26_r07.zip
SYSIMG O android x86_64 27 https://dl.google.com/android/repository/sys-img/android/x86_64-27_r01.zip
SYSIMG O android x86 27 https://dl.google.com/android/repository/sys-img/android/x86-27_r01.zip
SYSIMG O google_apis x86 27 https://dl.google.com/android/repository/sys-img/google_apis/x86-27_r11.zip
SYSIMG O google_apis_playstore x86 27 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86-27_r03.zip
SYSIMG P android x86_64 28 https://dl.google.com/android/repository/sys-img/android/x86_64-28_r04.zip
SYSIMG P android x86 28 https://dl.google.com/android/repository/sys-img/android/x86-28_r04.zip
SYSIMG P google_apis x86_64 28 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-28_r11.zip
SYSIMG P google_apis_playstore x86_64 28 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86_64-28_r08.zip
SYSIMG P google_apis_playstore x86 28 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86-28_r08.zip
SYSIMG P google_apis_playstore x86 28 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86-28_r09.zip
SYSIMG P google_ndk x86 28 https://dl.google.com/android/repository/sys-img/google_ndk/x86-28_r10.zip
SYSIMG Q google_apis x86_64 29 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-29_r11.zip
SYSIMG Q google_apis x86 29 https://dl.google.com/android/repository/sys-img/google_apis/x86-29_r11.zip
SYSIMG R google_apis x86_64 30 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-30_r09.zip
SYSIMG R google_apis x86 30 https://dl.google.com/android/repository/sys-img/google_apis/x86-30_r09.zip
EMU stable 30.2.6 macosx https://dl.google.com/android/repository/emulator-darwin-6962233.zip
EMU stable 30.2.6 linux https://dl.google.com/android/repository/emulator-linux-6962233.zip
EMU stable 30.2.6 windows https://dl.google.com/android/repository/emulator-windows-6962233.zip
EMU stable 28.0.25 windows https://dl.google.com/android/repository/emulator-windows-5395263.zip
EMU canary 30.3.4 macosx https://dl.google.com/android/repository/emulator-darwin-7020230.zip
EMU canary 30.3.4 linux https://dl.google.com/android/repository/emulator-linux-7020230.zip
EMU canary 30.3.4 windows https://dl.google.com/android/repository/emulator-windows-7020230.zip
SYSIMG
is the system image and EMU
is the emulator. Download what you need for each
curl -O 'https://dl.google.com/android/repository/emulator-linux-7020230.zip'
curl -O 'https://dl.google.com/android/repository/sys-img/google_apis/x86_64-30_r09.zip'
By executing emu-docker create <emulator.zip> <sysimg.zip>
, necessary files such as DockerFile will be placed under src
.
emu-docker create emulator-linux-7020230.zip sys-img-google_apis-30-R-x86_64.zip
src/DockerFile
# Copyright 2019 - The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM debian:stretch-slim AS emulator
# Install all the required emulator dependencies.
# You can get these by running ./android/scripts/unix/run_tests.sh --verbose --verbose --debs | grep apt | sort -u
# pulse audio is needed due to some webrtc dependencies.
RUN apt-get update && apt-get install -y --no-install-recommends \
# Emulator & video bridge dependencies
libc6 libdbus-1-3 libfontconfig1 libgcc1 \
libpulse0 libtinfo5 libx11-6 libxcb1 libxdamage1 \
libnss3 libxcomposite1 libxcursor1 libxi6 \
libxext6 libxfixes3 zlib1g libgl1 pulseaudio socat \
# Enable turncfg through usage of curl
curl ca-certificates && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Now we configure the user account under which we will be running the emulator
RUN mkdir -p /android/sdk/platforms && \
mkdir -p /android/sdk/platform-tools && \
mkdir -p /android/sdk/system-images/android && \
mkdir -p /android-home
# Make sure to place files that do not change often in the higher layers
# as this will improve caching.
COPY launch-emulator.sh /android/sdk/
COPY platform-tools/adb /android/sdk/platform-tools/adb
COPY default.pa /etc/pulse/default.pa
RUN gpasswd -a root audio && \
chmod +x /android/sdk/launch-emulator.sh /android/sdk/platform-tools/adb
COPY emu/ /android/sdk/
COPY avd/ /android-home
COPY sys/ /android/sdk/system-images/android/
# Create an initial snapshot so we will boot fast next time around,
# This is currently an experimental feature, and is not easily configurable//
# RUN --security=insecure cd /android/sdk && ./launch-emulator.sh -quit-after-boot 120
# This is the console port, you usually want to keep this closed.
EXPOSE 5554
# This is the ADB port, useful.
EXPOSE 5555
# This is the gRPC port, also useful, we don't want ADB to incorrectly identify this.
EXPOSE 8554
ENV ANDROID_SDK_ROOT /android/sdk
ENV ANDROID_AVD_HOME /android-home
WORKDIR /android/sdk
# You will need to make use of the grpc snapshot/webrtc functionality to actually interact with
# the emulator.
CMD ["/android/sdk/launch-emulator.sh"]
# Note we should use gRPC status endpoint to check for health once the canary release is out.
HEALTHCHECK --interval=30s \
--timeout=30s \
--start-period=30s \
--retries=3 \
CMD /android/sdk/platform-tools/adb shell getprop dev.bootcomplete | grep "1"
# Date frequently changes, so we place this in the last layer.
LABEL maintainer="ntsk@linux" \
SystemImage.Abi=x86_64 \
SystemImage.TagId=google_apis \
SystemImage.GpuSupport=true \
AndroidVersion.ApiLevel=30 \
com.google.android.emulator.description="Pixel 2 Emulator, running API 30" \
com.google.android.emulator.version="google_apis-30-x86_64/30.3.4"
You can start it as you did the first time with docker build
-> docker run
.
docker build src
...
...
Successfully built 809a82460bb3
docker run -e ADBKEY="$(cat ~/.android/adbkey)" \ + master
--device /dev/kvm \
--publish 8554:8554/tcp \
--publish 5555:5555/tcp 809a82460bb3
For docker run
, there is a wrapper script in run.sh
, so you can use that as well.
https://github.com/google/android-emulator-container-scripts/blob/master/run.sh
In fact, there is an option to do the contents up to this point interactively, and by executing this, the image will be created interactively, and by specifying —start
, it will even start.
emu-docker interactive --start
A sample that enables access via the Web is prepared, and by using docker-compose, you can launch the following four containers and perform Web access to the emulator.
Envoy is used as an edge proxy or service proxy, and the React application running on Nginx draws the emulator with WebRTC. It has become. It also comes with a simple basic authentication sample using JWT.
js/docker-compose.yaml
version: "3.7"
services:
front-envoy:
image: emulator_envoy:latest
container_name: emulator_envoy
networks:
- envoymesh
expose:
- "8080"
- "8001"
- "8443"
ports:
- "80:8080"
- "443:8443"
- "8001:8001"
emulator:
image: emulator_emulator:latest
container_name: emulator_emulator
networks:
envoymesh:
aliases:
- emulator
devices: [/dev/kvm]
shm_size: 128M
expose:
- "8554"
jwt_signer:
image: emulator_jwt_signer:latest
container_name: emulator_jwt_signer
networks:
envoymesh:
aliases:
- jwt_signer
expose:
- "8080"
nginx:
image: emulator_nginx:latest
container_name: emulator_nginx
networks:
envoymesh:
aliases:
- nginx
expose:
- "80"
networks:
envoymesh: {}
As with the previous item, create a container in advance using the emulator and system image.
emu-docker create emulator-linux-7020230.zip sys-img-google_apis-30-R-x86_64.zip
After creating, run ./create_web_container.sh
. By passing the user id and password with the -p
option, the token service is configured according to the user, and the key pair used for encryption/decryption of the JWT token is generated. Node.js, npm is required for execution.
./create_web_container.sh -p user,password
Specify js/docker/docker-compose.yml
and docker-compose up
.
docker-compose -f js/docker/docker-compose.yaml up
If you want to use adb, also specify js/docker/development.yaml
as follows.
docker-compose -f js/docker/docker-compose.yaml -f js/docker/development.yaml up
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c9dda3ce35c emulator_jwt_signer:latest "python jwt-provider…" About a minute ago Up About a minute 8080/tcp emulator_jwt_signer
d8537ef89c1a emulator_emulator:latest "/android/sdk/launch…" About a minute ago Up About a minute (healthy) 5554-5555/tcp, 8554/tcp emulator_emulator
49f29b2717d1 emulator_envoy:latest "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:8001->8001/tcp, 10000/tcp, 0.0.0.0:80->8080/tcp, 0.0.0.0:443->8443/tcp emulator_envoy
b1eec8500916 emulator_nginx:latest "nginx -g 'daemon of…" About a minute ago Up About a minute 80/tcp emulator_nginx
When you connect to localhost, the login screen will be launched, so log in with the id/password specified at the time of creation.
After logging in, you can operate the emulator on the browser.
The emulator drawing is displayed in real time using WebRTC if a P2P connection can be created to the server hosting the emulator, but if not available it seems to create an image every second and display it in the browser ( Performance is low).
When launching the emulator on CI and testing, Firebase Test Lab and AWS Device Farm exist as tools that can be used casually, but refer to these samples. It seems that in-house production of CI environment using emulator will become easier.
I am very grateful that Google provided a sample for building such a CI environment, and I will continue to check the trends.
Recommended Posts