背景
android 應(yīng)用開發(fā)后,會有ci和自動化測試的需求,如何將android模擬器運(yùn)行在docker上,
google 幾年前在github上發(fā)布過相關(guān)的腳本解決這個問題,https://github.com/google/android-emulator-container-scripts
本文介紹實(shí)際操作和腳本的一些含義。
操作
本文操作環(huán)境是ubuntu 20.04.3
安裝好Python
安裝好 Docker
安裝好 Docker-compose
首先clone
git clone https://github.com/google/android-emulator-container-scripts
目錄結(jié)構(gòu)如下
#ls -l
-rw-r--r-- 1 root root 157 12月 16 08:37 aemu-container.code-workspace
drwxr-xr-x 2 root root 4096 12月 16 08:37 cloud-init
-rwxr-xr-x 1 root root 1583 12月 16 08:37 configure.sh
-rw-r--r-- 1 root root 1101 12月 16 08:37 CONTRIBUTING.md
-rwxr-xr-x 1 root root 4034 12月 16 08:37 create_web_container.sh
drwxr-xr-x 4 root root 4096 12月 16 08:37 emu
drwxr-xr-x 8 root root 4096 12月 16 08:37 js
-rw-r--r-- 1 root root 11332 12月 16 08:37 LICENSE
-rw-r--r-- 1 root root 46 12月 16 08:37 MANIFEST.in
-rw-r--r-- 1 root root 164 12月 16 08:37 pyproject.toml
-rw-r--r-- 1 root root 18644 12月 16 08:37 README.md
-rw-r--r-- 1 root root 4359 12月 16 08:37 REGISTRY.MD
-rwxr-xr-x 1 root root 1440 12月 16 08:37 run-in-script-example.sh
-rwxr-xr-x 1 root root 899 12月 16 08:37 run.sh
-rwxr-xr-x 1 root root 1222 12月 16 08:37 run-with-gpu.sh
-rw-r--r-- 1 root root 781 12月 16 08:37 setup.cfg
-rw-r--r-- 1 root root 8386 12月 16 08:37 setup.py
drwxr-xr-x 3 root root 4096 12月 16 08:37 tests
-rw-r--r-- 1 root root 730 12月 16 08:37 tox.ini
-rw-r--r-- 1 root root 8553 12月 16 08:37 TROUBLESHOOTING.md
-rw-r--r-- 1 root root 68611 12月 16 08:37 versioneer.py
安裝腳本命令,該命令會創(chuàng)建Python獨(dú)立環(huán)境,同時安裝emu_docker命令,emu_docker命令本質(zhì)就是 emu_docker腳本
# source ./configure.sh
....
Ready to run emu-docker
列出可用的android系統(tǒng)鏡像和模擬器
#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 android-tv x86 21 https://dl.google.com/android/repository/sys-img/android-tv/x86-21_r03.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 android-tv x86 22 https://dl.google.com/android/repository/sys-img/android-tv/x86-22_r03.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 android-tv x86 23 https://dl.google.com/android/repository/sys-img/android-tv/x86-23_r21.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 android-tv x86 24 https://dl.google.com/android/repository/sys-img/android-tv/x86-24_r22.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 android-tv x86 25 https://dl.google.com/android/repository/sys-img/android-tv/x86-25_r16.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 android-tv x86 26 https://dl.google.com/android/repository/sys-img/android-tv/x86-26_r14.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 android-tv x86 27 https://dl.google.com/android/repository/sys-img/android-tv/x86-27_r09.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 android-tv x86 28 https://dl.google.com/android/repository/sys-img/android-tv/x86-28_r10.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 x86 28 https://dl.google.com/android/repository/sys-img/google_apis/x86-28_r12.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 Q android x86_64 29 https://dl.google.com/android/repository/sys-img/android/x86_64-29_r08-linux.zip
SYSIMG Q android x86 29 https://dl.google.com/android/repository/sys-img/android/x86-29_r08-linux.zip
SYSIMG Q android-tv x86 29 https://dl.google.com/android/repository/sys-img/android-tv/x86-29_r03.zip
SYSIMG Q google_apis x86_64 29 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-29_r12.zip
SYSIMG Q google_apis x86 29 https://dl.google.com/android/repository/sys-img/google_apis/x86-29_r12.zip
SYSIMG Q google_apis_playstore x86_64 29 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86_64-29_r08-linux.zip
SYSIMG Q google_apis_playstore x86 29 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86-29_r08-linux.zip
SYSIMG R android x86_64 30 https://dl.google.com/android/repository/sys-img/android/x86_64-30_r10.zip
SYSIMG R android-tv x86 30 https://dl.google.com/android/repository/sys-img/android-tv/x86-30_r03.zip
SYSIMG R google_apis x86_64 30 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-30_r11.zip
SYSIMG R google_apis x86 30 https://dl.google.com/android/repository/sys-img/google_apis/x86-30_r10.zip
SYSIMG R google_apis_playstore x86_64 30 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86_64-30_r10-linux.zip
SYSIMG R google_apis_playstore x86 30 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86-30_r09-linux.zip
SYSIMG S android x86_64 31 https://dl.google.com/android/repository/sys-img/android/x86_64-31_r03.zip
SYSIMG S android-tv x86 31 https://dl.google.com/android/repository/sys-img/android-tv/x86-31_r03.zip
SYSIMG S google_apis x86_64 31 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-31_r09.zip
SYSIMG S google_apis_playstore x86_64 31 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86_64-31_r09.zip
SYSIMG S google_apis x86_64 32 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-32_r03.zip
SYSIMG Tiramisu google_apis x86_64 32 https://dl.google.com/android/repository/sys-img/google_apis/x86_64-Tiramisu_r01.zip
SYSIMG S google_apis_playstore x86_64 32 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86_64-32_r03-linux.zip
SYSIMG Tiramisu google_apis_playstore x86_64 32 https://dl.google.com/android/repository/sys-img/google_apis_playstore/x86_64-Tiramisu_r01.zip
EMU canary 31.3.4 macosx https://dl.google.com/android/repository/emulator-darwin_x64-8220659.zip
EMU canary 31.3.4 linux https://dl.google.com/android/repository/emulator-linux_x64-8220659.zip
EMU canary 31.3.4 windows https://dl.google.com/android/repository/emulator-windows_x64-8220659.zip
EMU stable 31.2.8 linux https://dl.google.com/android/repository/emulator-linux_x64-8143646.zip
EMU stable 31.2.8 windows https://dl.google.com/android/repository/emulator-windows_x64-8143646.zip
EMU stable 31.2.8 macosx https://dl.google.com/android/repository/emulator-darwin_x64-8143646.zip
EMU開頭是模擬器,其他是系統(tǒng)鏡像,我們選擇其中一個版本下載,同時下載linux版本模擬器。
//下載系統(tǒng)鏡像 SYSIMG S android x86_64 31
wget https://dl.google.com/android/repository/sys-img/android/x86_64-31_r03.zip
//下載模擬器 EMU stable 31.2.8 linux
wget https://dl.google.com/android/repository/emulator-linux_x64-8143646.zip
基于系統(tǒng)鏡像和模擬器創(chuàng)建dockerfile,dockerfile用于創(chuàng)建android 模擬器 的 docker image
//emu-docker create <emulator-zip> <system-image-zip> [--dest docker-src-dir (getcwd()/src by default)]
emu-docker create 模擬器.zip 系統(tǒng)鏡像.zip --dest src
//--dest 指定生成dockerfile的存放路徑,默認(rèn)就是 pwd/src. 所以--dest src可以不加
官方說emu-docker create沒有生成可用的鏡像,需要 docker build 生成。 但實(shí)際生成了。也就是不用 src 目錄下docker build . 鏡像也存在了。
當(dāng)然也可以跟官方的操作執(zhí)行docker build . 再創(chuàng)建一個鏡像。
This places all the right elements to run a docker image, but does not build, run or publish yet. A Linux emulator zip file must be used.
cd src
docker build .
主要生成的docker鏡像有2個
#android系統(tǒng)docker鏡像
us-docker.pkg.dev/android-emulator-268719/images/sys-31-aosp-x64
上面android 系統(tǒng)鏡像的docker鏡像,基于模板 Dockerfile.system_image 生成.
Dockerfile.system_image主要步驟
拷貝android系統(tǒng)鏡像,解壓
基于 nvidia/opengl:1.2-glvnd-runtime-ubuntu20.04 創(chuàng)建鏡像
拷貝解壓的系統(tǒng)鏡像到容器 /android/sdk/system-images/android/ 目錄
拷貝 adb
chmod +x adb
#模擬器docker鏡像
us-docker.pkg.dev/android-emulator-268719/images/31-aosp-x64-no-metrics
模擬器docker鏡像 基于模板 Dockerfile.emulator 生成
Dockerfile.emulator主要步驟
基于 上面的android系統(tǒng)docker鏡像
安裝相關(guān)依賴
拷貝 launch-emulator.sh 腳本(容器啟動用) 到 容器 /android/sdk/目錄
設(shè)置容器啟動命令:啟動執(zhí)行 launch-emulator.sh
src目錄下生成的docekrfile 就是基于Dockerfile.emulator模板的,這也是為什么說(官方說emu-docker create沒有生成可用的鏡像,需要 docker build 生成。 但實(shí)際生成了).
運(yùn)行容器
docker run -d \
-e ADBKEY="$(cat ~/.android/adbkey)" \
--device /dev/kvm \
--publish 8554:8554/tcp \
--publish 5555:5555/tcp \
us-docker.pkg.dev/android-emulator-268719/images/31-aosp-x64-no-metrics
--device /dev/kvm 表示需要用到kvm設(shè)備用于硬件加速,所以宿主機(jī)要支持kvm,本地機(jī)器沒問題,但是放到阿里云k8s服務(wù)上會有問題,因?yàn)闆]有kvm。不過阿里云有個 彈性云手機(jī)服務(wù)
通過adb 連接設(shè)備
adb connect localhost:5555
也可以安裝 scrcpy投屏

launch-emulator.sh
介紹下launch-emulator.sh
主要是安裝證書,運(yùn)行模擬器
LAUNCH_CMD=emulator/emulator
var_append LAUNCH_CMD -avd Pixel2
var_append LAUNCH_CMD -ports 5556,5557 -grpc 8554 -no-window
var_append LAUNCH_CMD -skip-adb-auth -no-snapshot-save -wipe-data -no-boot-anim
var_append LAUNCH_CMD -shell-serial file:/tmp/android-unknown/kernel.log
var_append LAUNCH_CMD -logcat "*:V"
var_append LAUNCH_CMD -logcat-output /tmp/android-unknown/logcat.log
var_append LAUNCH_CMD -logcat "*:V"
var_append LAUNCH_CMD -feature AllowSnapshotMigration
var_append LAUNCH_CMD -gpu swiftshader_indirect {{extra}}
上面是構(gòu)造運(yùn)行模擬器的命令 emulator/emulator ....
其中 -grpc 8554 是用于對客戶端開放 grpc服務(wù),被 android-emulator-webrtc 用到。
也是網(wǎng)頁端顯示和操縱模擬器的基礎(chǔ)。
模擬器 grpc說明 emulator grpc
web端操作
生成3個鏡像
./create_web_container.sh -h
emulator_nginx
emulator_envoy
//就是us-docker.pkg.dev/android-emulator-268719/images/31-aosp-x64-no-metrics
emulator_emulator
web端操作主要是通過grpc和android-emulator-webrtc
ngnix用于web端代理.
Envoy 也是代理,istio中的sidecar就是用的Envoy。這里用于proxy grpc給 android-emulator-webrtc 組件。
運(yùn)行
docker-compose -f js/docker/docker-compose.yaml up
Docker-compose 文件對emulator_nginx,emulator_envoy,emulator_emulator 3個服務(wù)作了編排。
啟動3個容器后就可以通過瀏覽器訪問模擬器了。