android - 通过 VNC 连接到 Docker 容器中的 Android 模拟器(API 28 错误)
问题描述
我正在使用 VNC 客户端 (Remmina) 连接到在 Docker 容器中运行的 Android 模拟器,它可以使用 19 到 27 的 API,但是在使用 VNC 选项时出现 28 个错误(但在没有 VNC 的情况下也可以使用):
qemu-system-x86_64: VNC supports only guest GPU, add "-gpu guest" option
我的环境:
myrepo/app-tools:android-dev-1.0.2
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND noninteractive
RUN echo "debconf shared/accepted-oracle-license-v1-1 select true" | debconf-set-selections && \
echo "debconf shared/accepted-oracle-license-v1-1 seen true" | debconf-set-selections
ENV SDK_URL="https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip" \
ANDROID_HOME="/usr/local/android-sdk" \
ANDROID_VERSION="28" \
ANDROID_BUILD_TOOLS_VERSION="28.0.3" \
GRADLE_VERSION="5.0"
ENV GRADLE_URL="https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" \
GRADLE_HOME="/opt/gradle/gradle-${GRADLE_VERSION}" \
PATH="/opt/gradle/gradle-${GRADLE_VERSION}/bin:${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools"
COPY android/repositories.cfg /root/.android/
# Download JDK-8 and fix certificate issues
RUN apt-get update \
&& apt-get install -y openjdk-8-jdk \
&& apt-get install -y ant \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/cache/oracle-jdk8-installer \
&& apt-get update \
&& apt-get install -y ca-certificates-java \
&& apt-get clean \
&& update-ca-certificates -f \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/cache/oracle-jdk8-installer
# Download Android SDK
RUN cd /tmp \
&& apt-get update \
&& apt-get install -y nano zip curl net-tools socat \
&& curl -o gradle.zip -L "$GRADLE_URL" \
&& unzip -d /opt/gradle gradle.zip \
&& rm gradle.zip \
&& mkdir "$ANDROID_HOME" .android \
&& cd "$ANDROID_HOME" \
&& curl -o sdk.zip $SDK_URL \
&& unzip sdk.zip \
&& rm sdk.zip \
&& yes | "$ANDROID_HOME/tools/bin/sdkmanager" --licenses \
&& "$ANDROID_HOME/tools/bin/sdkmanager" --update \
&& "$ANDROID_HOME/tools/bin/sdkmanager" \
"build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
"platforms;android-${ANDROID_VERSION}" \
"platform-tools" \
"emulator"
RUN mkdir /main
WORKDIR /main
安卓/repositories.cfg
### User Sources for Android SDK Manager
#Fri Nov 03 10:11:27 CET 2017 count=0
android-dev.dockerfile
FROM myrepo/app-tools:android-dev-1.0.2
ENV ANDROID_SDK="/usr/local/android-sdk"
ENV PATH="$ANDROID_SDK/emulator:$ANDROID_SDK/tools:$PATH"
RUN /usr/local/android-sdk/tools/bin/sdkmanager "system-images;android-19;google_apis;x86" \
&& /usr/local/android-sdk/tools/bin/sdkmanager --licenses
RUN /usr/local/android-sdk/tools/bin/sdkmanager "system-images;android-23;google_apis;x86" \
&& /usr/local/android-sdk/tools/bin/sdkmanager --licenses
RUN /usr/local/android-sdk/tools/bin/sdkmanager "system-images;android-28;google_apis;x86" \
&& /usr/local/android-sdk/tools/bin/sdkmanager --licenses
RUN /usr/local/android-sdk/tools/bin/avdmanager create avd -n avd19 -k "system-images;android-19;google_apis;x86" -b x86 -d 7 -f \
&& /usr/local/android-sdk/tools/bin/avdmanager create avd -n avd23 -k "system-images;android-23;google_apis;x86" -b x86 -d 7 -f \
&& /usr/local/android-sdk/tools/bin/avdmanager create avd -n avd28 -k "system-images;android-28;google_apis;x86" -b x86 -d 7 -f
COPY scripts/android-dev-startup.sh /root/start.sh
脚本/android-dev-startup.sh
#!/bin/bash
set -eou pipefail
socat tcp-listen:5037,bind=android-dev,fork tcp:127.0.0.1:5037 &
socat tcp-listen:5554,bind=android-dev,fork tcp:127.0.0.1:5554 &
socat tcp-listen:5555,bind=android-dev,fork tcp:127.0.0.1:5555 &
sleep infinity
码头工人撰写
android-dev:
build:
context: ./
dockerfile: android-dev.dockerfile
hostname: android-dev
volumes:
- .:/main:rw
devices:
- "/dev/kvm:/dev/kvm"
ports:
- "5037:5037"
- "5554:5554"
- "5555:5555"
- "5900:5900"
command: /root/start.sh
然后,如果我运行命令来启动模拟器,它在所有情况下都可以工作,除非将模拟器与android-28
(使用 VNC 时)一起使用:
# works
emulator -memory 4096 -avd avd19 -noaudio -no-window -gpu off -verbose -qemu -vnc :0
# works
emulator -memory 4096 -avd avd23 -noaudio -no-window -gpu off -verbose -qemu -vnc :0
# works
emulator -memory 4096 -avd avd28 -noaudio -no-window -gpu off -verbose -qemu
# doesn't work
# qemu-system-x86_64: VNC supports only guest GPU, add "-gpu guest" option
emulator -memory 4096 -avd avd28 -noaudio -no-window -gpu off -verbose -qemu -vnc :0
# doesn't work
# qemu-system-x86_64: VNC supports only guest GPU, add "-gpu guest" option
emulator -memory 4096 -avd avd28 -noaudio -no-window -gpu guest -verbose -qemu -vnc :0
我认为错误来自此文件:
https://android.googlesource.com/platform/external/qemu/+/emu-master-dev/vl.c
有没有办法让它与 VNC 一起工作?
解决方案
我在 emulator-headless 的输出中发现了一些有趣的东西:
emulator: WARNING: Your AVD has been configured with an in-guest renderer, but the system image does not support guest rendering.Falling back to 'swiftshader_indirect' mode.
emulator: GPU emulation enabled using 'swiftshader_indirect' mode
emulator: Initializing hardware OpenGLES emulation support
https://androidstudio.googleblog.com/2018/11/emulator-28016-stable.html?m=1
-gpu guest (software rendering in the guest) has been deprecated. API 28+ system images will now auto switch to using Swiftshader (-gpu swiftshader_indirect).
所以它切换到 swiftshader_indirect,这使得它无法使用 vnc。哦哦。
所以现在我想知道是否可以使用环境变量 DISPLAY 使仿真器无头将图形渲染到虚拟显示器中,该显示器将与另一台 VNC 服务器创建...
编辑: 是的,它似乎在 2 个 Xeon 内核 3.3Ghz 和 4GB RAM 上运行良好。
echo 'no' | avdmanager create avd --force --name android-28-x86 --abi google_apis_playstore/x86 --package 'system-images;android-28;google_apis_playstore;x86'
apt install tightvnc
apt install xfonts-base
sudo apt-get install gnome-core xfce4 firefox nano -y --force-yes
# ~/.vnc/xstatup
unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS startxfce4 & [ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources xsetroot -solid grey vncconfig -iconic &
vncserver :2 -geometry 1080x1920 -depth 24
export DISPLAY=:2.0
emulator @android-28-x86 -verbose -memory 2048 -gpu swiftshader_indirect -no-audio -no-snapshot -wipe-data -no-boot-anim -skin 768x1280
我仍然不知道为什么android 模拟器开发人员决定在他们的产品中禁用 vnc 支持,如果一切都与独立 vnc 服务器上的 gpu 软件模拟运行良好..?
Edit2: 虽然它总是加载 100% 的 CPU。显然它需要修复。https://gist.github.com/yazinsai/652f0e6e77c9594a2356dd6314a9c3d8 LMK 如果你想实现它。
推荐阅读
- javascript - 使用 axios 从 react-native 将文件上传到 rails 6 api 后端
- python - UDP下使用Swift向Python服务器发送数据
- rust - 如何匹配 Rust 匹配表达式中的多个字符?
- rest - OpenAPI 3 - 只读属性,但允许写入 POST/PUT
- swift - RxSwift asDriver 映射和强自我
- python - cv2 圆值错误
- java - 从 firebase 数据库读取数据到自定义 listView
- mysql - 当我加入一个表时,为什么一列变得不明确?
- pytest - Pytest - 测试特定目录的 conftest.py 以覆盖 pytest_terminal_summary
- python - 在 django 模型中更改 primary_key