docker android 模拟器

背景

android 应用开发后,会有ci和自动化测试的需求,如何将android模拟器运行在docker上,
google 几年前在github上发布过相关的脚本解决这个问题,https://github.com/google/android-emulator-container-scripts
本文介绍实际操作和脚本的一些含义。

操作

本文操作环境是ubuntu 20.04.3
安装好Python
安装好 Docker
安装好 Docker-compose
首先clone

git clone https://github.com/google/android-emulator-container-scripts

目录结构如下

#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

安装脚本命令,该命令会创建Python独立环境,同时安装emu_docker命令,emu_docker命令本质就是 emu_docker脚本

# source ./configure.sh
....
Ready to run emu-docker

列出可用的android系统镜像和模拟器

#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开头是模拟器,其他是系统镜像,我们选择其中一个版本下载,同时下载linux版本模拟器。

//下载系统镜像 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

基于系统镜像和模拟器创建dockerfile,dockerfile用于创建android 模拟器 的 docker image

//emu-docker create <emulator-zip> <system-image-zip>  [--dest docker-src-dir (getcwd()/src by default)]
emu-docker create  模拟器.zip 系统镜像.zip --dest src
//--dest 指定生成dockerfile的存放路径,默认就是 pwd/src. 所以--dest src可以不加

官方说emu-docker create没有生成可用的镜像,需要 docker build 生成。 但实际生成了。也就是不用 src 目录下docker build . 镜像也存在了。
当然也可以跟官方的操作执行docker build . 再创建一个镜像。

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系统docker镜像
us-docker.pkg.dev/android-emulator-268719/images/sys-31-aosp-x64

上面android 系统镜像的docker镜像,基于模板 Dockerfile.system_image 生成.
Dockerfile.system_image主要步骤
拷贝android系统镜像,解压
基于 nvidia/opengl:1.2-glvnd-runtime-ubuntu20.04 创建镜像
拷贝解压的系统镜像到容器 /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系统docker镜像
安装相关依赖
拷贝 launch-emulator.sh 脚本(容器启动用) 到 容器 /android/sdk/目录
设置容器启动命令:启动执行 launch-emulator.sh

src目录下生成的docekrfile 就是基于Dockerfile.emulator模板的,这也是为什么说(官方说emu-docker create没有生成可用的镜像,需要 docker build 生成。 但实际生成了).

运行容器

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设备用于硬件加速,所以宿主机要支持kvm,本地机器没问题,但是放到阿里云k8s服务上会有问题,因为没有kvm。不过阿里云有个 弹性云手机服务
通过adb 连接设备

 adb connect localhost:5555

也可以安装 scrcpy投屏


image.png

launch-emulator.sh

介绍下launch-emulator.sh
主要是安装证书,运行模拟器

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}}

上面是构造运行模拟器的命令 emulator/emulator ....
其中 -grpc 8554 是用于对客户端开放 grpc服务,被 android-emulator-webrtc 用到。
也是网页端显示和操纵模拟器的基础。
模拟器 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 组件。

运行

docker-compose -f js/docker/docker-compose.yaml up

Docker-compose 文件对emulator_nginx,emulator_envoy,emulator_emulator 3个服务作了编排。
启动3个容器后就可以通过浏览器访问模拟器了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容