├── .dockerignore ├── .github └── workflows │ └── docker-image.yml ├── .gitignore ├── Dockerfile ├── DockerfileWin ├── LICENSE ├── README.md ├── docker-compose.yml ├── start_appium.sh ├── start_emu.sh ├── start_emu_headless.sh └── start_vnc.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | .github 2 | README.md 3 | allure-results 4 | coverage 5 | .gitignore 6 | docker-compose.yml 7 | Jenkinsfile 8 | useful 9 | Dockerfile 10 | test-compose.yml 11 | allure_service.sh -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: docker push 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | Pushing-docker-image: 8 | runs-on: ${{ matrix.os }} 9 | 10 | steps: 11 | - uses: actions/checkout@v3 12 | 13 | - name: Docker Login 14 | uses: docker/login-action@v2.1.0 15 | with: 16 | username: ${{secrets.DOCKER_USERNAME}} 17 | password: ${{secrets.DOCKER_PASSWORD}} 18 | 19 | - name: Docker build and push image 20 | if: startsWith(matrix.os, 'ubuntu') 21 | env: 22 | ARCH: x86_64 23 | EMULATOR_DEVICE: ${{ matrix.emulator_device }} 24 | EMULATOR_NAME: ${{ matrix.emulator_name }} 25 | DOCKER_TAG: ${{ matrix.docker_tag }} 26 | run: | 27 | docker build --build-arg EMULATOR_DEVICE="${EMULATOR_DEVICE}" --build-arg ARCH="${ARCH}" --build-arg EMULATOR_NAME="${EMULATOR_NAME}" -t amrka/android-emulator:${DOCKER_TAG}-latest . 28 | docker push amrka/android-emulator:${DOCKER_TAG}-latest 29 | 30 | # - name: Docker build and push image (Windows) 31 | # if: startsWith(matrix.os, 'windows') 32 | # env: 33 | # EMULATOR_DEVICE: ${{ matrix.emulator_device }} 34 | # EMULATOR_NAME: ${{ matrix.emulator_name }} 35 | # DOCKER_TAG: ${{ matrix.docker_tag }} 36 | # run: | 37 | # docker build --build-arg EMULATOR_DEVICE="${EMULATOR_DEVICE}" --build-arg EMULATOR_NAME="${EMULATOR_NAME}" -f DockerfileWin -t amrka/android-emulator:${{ matrix.docker_tag }}-win-latest . 38 | # docker push amrka/android-emulator:${{ matrix.docker_tag }}-win-latest 39 | 40 | strategy: 41 | max-parallel: 2 42 | matrix: 43 | os: [ubuntu-latest, windows-latest] 44 | emulator_device: 45 | - pixel_c 46 | - Nexus 6 47 | emulator_name: 48 | - pixel_c 49 | - nexus 50 | docker_tag: ["nexus6_playstore", "pixelC_tablet_playstore"] 51 | exclude: 52 | - os: windows-latest 53 | emulator_device: Nexus 6 54 | emulator_name: nexus 55 | docker_tag: pixelC_tablet_playstore 56 | - os: windows-latest 57 | emulator_device: Nexus 6 58 | emulator_name: pixel_c 59 | docker_tag: nexus6_playstore 60 | - os: windows-latest 61 | emulator_device: Nexus 6 62 | emulator_name: pixel_c 63 | docker_tag: pixelC_tablet_playstore 64 | - os: windows-latest 65 | emulator_device: pixel_c 66 | emulator_name: nexus 67 | docker_tag: nexus6_playstore 68 | - os: windows-latest 69 | emulator_device: pixel_c 70 | emulator_name: nexus 71 | docker_tag: pixelC_tablet_playstore 72 | - os: windows-latest 73 | emulator_device: pixel_c 74 | emulator_name: pixel_c 75 | docker_tag: nexus6_playstore 76 | 77 | - os: ubuntu-latest 78 | emulator_device: Nexus 6 79 | emulator_name: nexus 80 | docker_tag: pixelC_tablet_playstore 81 | - os: ubuntu-latest 82 | emulator_device: Nexus 6 83 | emulator_name: pixel_c 84 | docker_tag: pixelC_tablet_playstore 85 | - os: ubuntu-latest 86 | emulator_device: Nexus 6 87 | emulator_name: pixel_c 88 | docker_tag: nexus6_playstore 89 | - os: ubuntu-latest 90 | emulator_device: pixel_c 91 | emulator_name: nexus 92 | docker_tag: nexus6_playstore 93 | - os: ubuntu-latest 94 | emulator_device: pixel_c 95 | emulator_name: nexus 96 | docker_tag: pixelC_tablet_playstore 97 | - os: ubuntu-latest 98 | emulator_device: pixel_c 99 | emulator_name: pixel_c 100 | docker_tag: nexus6_playstore 101 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | test-compose.yml 2 | .idea 3 | coverage 4 | useful 5 | nohup.out 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:18-jdk-slim 2 | 3 | LABEL maintainer "Amr Salem" 4 | 5 | ENV DEBIAN_FRONTEND noninteractive 6 | 7 | WORKDIR / 8 | #============================= 9 | # Install Dependenices 10 | #============================= 11 | SHELL ["/bin/bash", "-c"] 12 | 13 | RUN apt update && apt install -y curl sudo wget unzip bzip2 libdrm-dev libxkbcommon-dev libgbm-dev libasound-dev libnss3 libxcursor1 libpulse-dev libxshmfence-dev xauth xvfb x11vnc fluxbox wmctrl libdbus-glib-1-2 14 | 15 | #============================== 16 | # Android SDK ARGS 17 | #============================== 18 | ARG ARCH="x86_64" 19 | ARG TARGET="google_apis_playstore" 20 | ARG API_LEVEL="34" 21 | ARG BUILD_TOOLS="34.0.0" 22 | ARG ANDROID_ARCH=${ANDROID_ARCH_DEFAULT} 23 | ARG ANDROID_API_LEVEL="android-${API_LEVEL}" 24 | ARG ANDROID_APIS="${TARGET};${ARCH}" 25 | ARG EMULATOR_PACKAGE="system-images;${ANDROID_API_LEVEL};${ANDROID_APIS}" 26 | ARG PLATFORM_VERSION="platforms;${ANDROID_API_LEVEL}" 27 | ARG BUILD_TOOL="build-tools;${BUILD_TOOLS}" 28 | ARG ANDROID_CMD="commandlinetools-linux-11076708_latest.zip" 29 | ARG ANDROID_SDK_PACKAGES="${EMULATOR_PACKAGE} ${PLATFORM_VERSION} ${BUILD_TOOL} platform-tools emulator" 30 | 31 | #============================== 32 | # Set JAVA_HOME - SDK 33 | #============================== 34 | ENV ANDROID_SDK_ROOT=/opt/android 35 | ENV PATH "$PATH:$ANDROID_SDK_ROOT/cmdline-tools/tools:$ANDROID_SDK_ROOT/cmdline-tools/tools/bin:$ANDROID_SDK_ROOT/emulator:$ANDROID_SDK_ROOT/tools/bin:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/build-tools/${BUILD_TOOLS}" 36 | ENV DOCKER="true" 37 | 38 | #============================================ 39 | # Install required Android CMD-line tools 40 | #============================================ 41 | RUN wget https://dl.google.com/android/repository/${ANDROID_CMD} -P /tmp && \ 42 | unzip -d $ANDROID_SDK_ROOT /tmp/$ANDROID_CMD && \ 43 | mkdir -p $ANDROID_SDK_ROOT/cmdline-tools/tools && cd $ANDROID_SDK_ROOT/cmdline-tools && mv NOTICE.txt source.properties bin lib tools/ && \ 44 | cd $ANDROID_SDK_ROOT/cmdline-tools/tools && ls 45 | 46 | #============================================ 47 | # Install required package using SDK manager 48 | #============================================ 49 | RUN yes Y | sdkmanager --licenses 50 | RUN yes Y | sdkmanager --verbose --no_https ${ANDROID_SDK_PACKAGES} 51 | 52 | #============================================ 53 | # Create required emulator 54 | #============================================ 55 | ARG EMULATOR_NAME="nexus" 56 | ARG EMULATOR_DEVICE="Nexus 6" 57 | ENV EMULATOR_NAME=$EMULATOR_NAME 58 | ENV DEVICE_NAME=$EMULATOR_DEVICE 59 | RUN echo "no" | avdmanager --verbose create avd --force --name "${EMULATOR_NAME}" --device "${EMULATOR_DEVICE}" --package "${EMULATOR_PACKAGE}" 60 | 61 | #==================================== 62 | # Install latest nodejs, npm & appium 63 | #==================================== 64 | RUN curl -sL https://deb.nodesource.com/setup_20.x | bash && \ 65 | apt-get -qqy install nodejs && \ 66 | npm install -g npm && \ 67 | npm i -g appium --unsafe-perm=true --allow-root && \ 68 | appium driver install uiautomator2 && \ 69 | exit 0 && \ 70 | npm cache clean && \ 71 | apt-get remove --purge -y npm && \ 72 | apt-get autoremove --purge -y && \ 73 | apt-get clean && \ 74 | rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* 75 | 76 | 77 | #=================== 78 | # Alias 79 | #=================== 80 | ENV EMU=./start_emu.sh 81 | ENV EMU_HEADLESS=./start_emu_headless.sh 82 | ENV VNC=./start_vnc.sh 83 | ENV APPIUM=./start_appium.sh 84 | 85 | 86 | #=================== 87 | # Ports 88 | #=================== 89 | ENV APPIUM_PORT=4723 90 | 91 | #========================= 92 | # Copying Scripts to root 93 | #========================= 94 | COPY . / 95 | 96 | RUN chmod a+x start_vnc.sh && \ 97 | chmod a+x start_emu.sh && \ 98 | chmod a+x start_appium.sh && \ 99 | chmod a+x start_emu_headless.sh 100 | 101 | #======================= 102 | # framework entry point 103 | #======================= 104 | CMD [ "/bin/bash" ] 105 | -------------------------------------------------------------------------------- /DockerfileWin: -------------------------------------------------------------------------------- 1 | FROM --platform=windows/x86-64 ubuntu:latest 2 | 3 | LABEL maintainer "Amr Salem" 4 | 5 | ENV DEBIAN_FRONTEND noninteractive 6 | 7 | WORKDIR / 8 | #============================= 9 | # Install Dependenices 10 | #============================= 11 | SHELL ["/bin/bash", "-c"] 12 | 13 | RUN apt update && apt install -y curl sudo wget unzip bzip2 libdrm-dev libxkbcommon-dev libgbm-dev libasound-dev libnss3 libxcursor1 libpulse-dev libxshmfence-dev xauth xvfb x11vnc fluxbox wmctrl libdbus-glib-1-2 14 | 15 | #============================== 16 | # Android SDK ARGS 17 | #============================== 18 | ENV ANDROID_ARCH="x86_64" 19 | ENV ANDROID_TARGET="google_apis_playstore" 20 | ENV API_LEVEL="33" 21 | ENV BUILD_TOOLS="33.0.2" 22 | ARG ANDROID_ARCH=$ANDROID_ARCH 23 | ARG ANDROID_TARGET=$ANDROID_TARGET 24 | ARG ANDROID_API_LEVEL="android-$API_LEVEL" 25 | ARG ANDROID_APIS="$ANDROID_TARGET;$ANDROID_ARCH" 26 | ARG ANDROID_BUILD_TOOLS_VERSION=$BUILD_TOOLS 27 | ARG ANDROID_EMULATOR_PACKAGE="system-images;${ANDROID_API_LEVEL};${ANDROID_APIS}" 28 | ARG ANDROID_PLATFORM_VERSION="platforms;${ANDROID_API_LEVEL}" 29 | ARG ANDROID_BUILD_TOOLS="build-tools;${ANDROID_BUILD_TOOLS_VERSION}" 30 | ARG ANDROID_CMD_VERSION="commandlinetools-linux-8092744_latest.zip" 31 | ARG ANDROID_SDK_PACKAGES="${ANDROID_EMULATOR_PACKAGE} ${ANDROID_PLATFORM_VERSION} ${ANDROID_BUILD_TOOLS} platform-tools" 32 | 33 | #============================== 34 | # Set JAVA_HOME - SDK 35 | #============================== 36 | ENV ANDROID_SDK_ROOT=/opt/android 37 | ENV PATH "$PATH:$ANDROID_SDK_ROOT/cmdline-tools/tools:$ANDROID_SDK_ROOT/cmdline-tools/tools/bin:$ANDROID_SDK_ROOT/emulator:$ANDROID_SDK_ROOT/tools/bin:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/build-tools/${ANDROID_BUILD_TOOLS_VERSION}" 38 | ENV DOCKER="true" 39 | 40 | #============================================ 41 | # Install required Android CMD-line tools 42 | #============================================ 43 | RUN wget https://dl.google.com/android/repository/${ANDROID_CMD_VERSION} -P /tmp && \ 44 | unzip -d $ANDROID_SDK_ROOT /tmp/$ANDROID_CMD_VERSION && \ 45 | mkdir -p $ANDROID_SDK_ROOT/cmdline-tools/tools && cd $ANDROID_SDK_ROOT/cmdline-tools && mv NOTICE.txt source.properties bin lib tools/ && \ 46 | cd $ANDROID_SDK_ROOT/cmdline-tools/tools && ls 47 | 48 | #============================================ 49 | # Install required package using SDK manager 50 | #============================================ 51 | RUN yes Y | sdkmanager --licenses 52 | RUN yes Y | sdkmanager --verbose --no_https ${ANDROID_SDK_PACKAGES} 53 | 54 | #============================================ 55 | # Create required emulator 56 | #============================================ 57 | ARG EMULATOR_NAME="nexus" 58 | ARG EMULATOR_DEVICE="Nexus 6" 59 | ENV EMULATOR_NAME=$EMULATOR_NAME 60 | ENV EMULATOR_DEVICE_NAME=$EMULATOR_DEVICE 61 | RUN echo "no" | avdmanager --verbose create avd --force --name "${EMULATOR_NAME}" --device "${EMULATOR_DEVICE}" --package "${ANDROID_EMULATOR_PACKAGE}" 62 | 63 | #==================================== 64 | # Install latest nodejs, npm & appium 65 | #==================================== 66 | RUN curl -sL https://deb.nodesource.com/setup_18.x | bash && \ 67 | apt-get -qqy install nodejs && \ 68 | npm install -g npm && \ 69 | npm i -g appium@next --unsafe-perm=true --allow-root && \ 70 | appium driver install uiautomator2 && \ 71 | exit 0 && \ 72 | npm cache clean && \ 73 | apt-get remove --purge -y npm && \ 74 | apt-get autoremove --purge -y && \ 75 | apt-get clean && \ 76 | rm -Rf /tmp/* && rm -Rf /var/lib/apt/lists/* 77 | 78 | 79 | #=================== 80 | # Alias 81 | #=================== 82 | ENV START_EMU=./start_emu.sh 83 | ENV START_EMU_HEADLESS=./start_emu_headless.sh 84 | ENV START_VNC=./start_vnc.sh 85 | ENV START_APPIUM=./start_appium.sh 86 | 87 | 88 | #=================== 89 | # Ports 90 | #=================== 91 | ENV APPIUM_PORT=4723 92 | 93 | #========================= 94 | # Copying Scripts to root 95 | #========================= 96 | COPY . / 97 | 98 | RUN chmod a+x start_vnc.sh && \ 99 | chmod a+x start_emu.sh && \ 100 | chmod a+x start_appium.sh && \ 101 | chmod a+x start_emu_headless.sh 102 | 103 | #======================= 104 | # framework entry point 105 | #======================= 106 | CMD [ "/bin/bash" ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Amr Salem 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android emulator Image 2 | 3 | The use of this Docker image simplifies the process of running an Android emulator within a Docker container. This can be achieved through a few basic commands or by utilizing a simple Docker compose file. The image includes the latest version of the Android SDK, as well as the Appium server, which allows for the execution of mobile automation tests. 4 | for more info --> https://medium.com/@Amr.sa/running-android-emulator-in-a-docker-container-19ecb68e1909 5 | 6 | # Feature 7 | 8 | - Run android emulator in headless or in headed mode (through VNC) 9 | - Support Appium driver 10 | - Come with the latest JDK lts. 11 | 12 | 13 | # Setup 14 | 15 | ## Manual execution 16 | 17 | Down below is the list of the main scripts to launch the relevant service, certain environment variables should be passed during starting the container. 18 | 19 | 1. **build the docker image :** 20 | 21 | docker build -t android-emulator . 22 | 23 | OR for customized image 24 | 25 | docker build \ 26 | --build-arg ARCH=x86_64 \ 27 | --build-arg TARGET=google_apis_playstore\ 28 | --build-arg API_LEVEL=31 \ 29 | --build-arg BUILD_TOOLS=31.0.0 \ 30 | --build-arg EMULATOR_DEVICE="Nexus 6" \ 31 | --build-arg EMULATOR_NAME=nexus \ 32 | -t my-android-image . 33 | 34 | 2. **Start your container:** 35 | 36 | docker run -it --privileged -d -p 5900:5900 --name androidContainer --privileged android-emulator 37 | 38 | 3. **Launch the appium session :** 39 | 40 | docker exec --privileged -it androidContainer bash -c "appium -p 5900" 41 | 42 | OR 43 | 44 | docker exec --privileged -it androidContainer bash -c "./start_appium.sh" 45 | 46 | 47 | 4. **Start the emulator in headless mode :** 48 | 49 | docker exec --privileged -it -e EMULATOR_TIMEOUT=300 androidContainer bash -c "./start_emu_headless.sh" 50 | 51 | 5. **Starting VNC server:** 52 | 53 | docker exec --privileged -it androidContainer bash -c "./start_vnc.sh" 54 | 55 | 56 | 57 | ## Launch emulator in headed mode 58 | 59 | 60 | 1. **The following command must be used to initiate the Docker container:** 61 | 62 | docker run -it -d -p 5900:5900 --name androidContainer -e VNC_PASSWORD=password --privileged android-emulator 63 | 64 | 2. **Instantiate the VNC service by running:** 65 | 66 | docker exec --privileged -it androidContainer bash -c "./start_vnc.sh" 67 | 68 | 3. **Connect to the VNC server via remmina or any VNC viewer, on:** 69 | 70 | localhost:5900 71 | 72 | 4. **Open dash terminal in vnc viewer and right the following command:** 73 | 74 | #: ./start_emu.sh 75 | 76 | vnc gif 77 | 78 | *Note: 79 | - The "start_emu.sh" script will start the emulator in a visible mode, therefore it should not be used for integration with a pipeline such as GitHub Actions or CircleCI. Instead, use the "start_emu_headless.sh" script. 80 | - By default, Running emulator is 'Nexus 6' (emulator name: nexus) (Android 13) 81 | - It is not necessary to launch all services in the docker-compose file, instead you should only enable the services you require, and comment out the others in the file. 82 | 83 | 84 | ## Using Docker-compose 85 | 86 | The Docker Compose file simplifies the process of starting the service. It includes multiple services, such as launching the emulator with the Appium instance or launching the VNC server. You have the flexibility to enable or disable any service based on your needs. 87 | 88 | docker compose up 89 | 90 | ## Environments 91 | 92 | **When manually starting the container, ensure to set the necessary environment variables for proper operation** 93 | 94 | | Environments | Description | Required | Service | 95 | | ----------------- | -------------------------------------------------------------------------------------------------------- | ----------------- | -----------| 96 | | APPIUM_PORT | Port for the appium instance | optional | Android | 97 | | VNC_PASSWORD | Password needed to connect to VNC Server | optional | VNC | 98 | | OSTYPE | linux or macos/darwin | optional | Android | 99 | | EMULATOR_TIMEOUT | emulator booting up timeoue, default 240 second | optional | Android | 100 | | HW_ACCEL_OVERRIDE | Pass aceel options e.g "-accel on" or "-aceel off" | optional | Android 101 | 102 | ## Kill the container 103 | 104 | - **Run the following command to kill and remove the container:** 105 | 106 | docker rm -f androidContainer 107 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "4" 2 | services: 3 | # Launch emulator and appium instance 4 | android-service: 5 | image: android-emulator 6 | build: . 7 | ports: 8 | - 4725:4725 9 | container_name: android 10 | environment: 11 | - APPIUM_PORT=4725 12 | privileged: true 13 | command: 14 | - bash 15 | - -c 16 | - | 17 | ./start_emu_headless.sh 18 | tty: true 19 | stdin_open: true 20 | # # Starting VNC server 21 | # VNC-Service: 22 | # image: android-emulator 23 | # build: . 24 | # ports: 25 | # - 5900:5900 26 | # container_name: VNC-Service 27 | # environment: 28 | # VNC_PASSWORD: 123 29 | # privileged: true 30 | # command: 31 | # - bash 32 | # - -c 33 | # - | 34 | # $START_VNC 35 | # tty: true 36 | # stdin_open: true 37 | -------------------------------------------------------------------------------- /start_appium.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BL='\033[0;34m' 4 | G='\033[0;32m' 5 | RED='\033[0;31m' 6 | YE='\033[1;33m' 7 | NC='\033[0m' # No Color 8 | 9 | function start_appium () { 10 | if [ "$APPIUM_PORT" == "" ] || [ "$APPIUM_PORT" == null ]; 11 | then 12 | printf "${G}==> ${YE}No port provided, instance will run on 4723 ${G}<==${NC}""\n" 13 | sleep 0.5 14 | appium 15 | else 16 | printf "${G}==> ${BL}Instance will run on ${YE}${APPIUM_PORT} ${G}<==${NC}""\n" 17 | sleep 0.5 18 | appium -p $APPIUM_PORT 19 | fi 20 | }; 21 | 22 | start_appium -------------------------------------------------------------------------------- /start_emu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BL='\033[0;34m' 4 | G='\033[0;32m' 5 | RED='\033[0;31m' 6 | YE='\033[1;33m' 7 | NC='\033[0m' # No Color 8 | 9 | function wait_emulator_to_be_ready() { 10 | emulator_name=${EMULATOR_NAME} 11 | emulator -avd "${emulator_name}" -no-boot-anim -gpu off 12 | printf "${G}==> ${BL}Emulator has ${YE}${EMULATOR_NAME} ${BL}started in headed mode! ${G}<==${NC}""\n" 13 | } 14 | 15 | function disable_animation() { 16 | adb shell "settings put global window_animation_scale 0.0" 17 | adb shell "settings put global transition_animation_scale 0.0" 18 | adb shell "settings put global animator_duration_scale 0.0" 19 | } 20 | 21 | wait_emulator_to_be_ready 22 | sleep 1 23 | disable_animation -------------------------------------------------------------------------------- /start_emu_headless.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BL='\033[0;34m' 4 | G='\033[0;32m' 5 | RED='\033[0;31m' 6 | YE='\033[1;33m' 7 | NC='\033[0m' # No Color 8 | 9 | emulator_name=${EMULATOR_NAME} 10 | 11 | function check_hardware_acceleration() { 12 | if [[ "$HW_ACCEL_OVERRIDE" != "" ]]; then 13 | hw_accel_flag="$HW_ACCEL_OVERRIDE" 14 | else 15 | if [[ "$OSTYPE" == "darwin"* ]]; then 16 | # macOS-specific hardware acceleration check 17 | HW_ACCEL_SUPPORT=$(sysctl -a | grep -E -c '(vmx|svm)') 18 | else 19 | # generic Linux hardware acceleration check 20 | HW_ACCEL_SUPPORT=$(grep -E -c '(vmx|svm)' /proc/cpuinfo) 21 | fi 22 | 23 | if [[ $HW_ACCEL_SUPPORT == 0 ]]; then 24 | hw_accel_flag="-accel off" 25 | else 26 | hw_accel_flag="-accel on" 27 | fi 28 | fi 29 | 30 | echo "$hw_accel_flag" 31 | } 32 | 33 | 34 | hw_accel_flag=$(check_hardware_acceleration) 35 | 36 | function launch_emulator () { 37 | adb devices | grep emulator | cut -f1 | xargs -I {} adb -s "{}" emu kill 38 | options="@${emulator_name} -no-window -no-snapshot -noaudio -no-boot-anim -memory 2048 ${hw_accel_flag} -camera-back none" 39 | if [[ "$OSTYPE" == *linux* ]]; then 40 | echo "${OSTYPE}: emulator ${options} -gpu off" 41 | nohup emulator $options -gpu off & 42 | fi 43 | if [[ "$OSTYPE" == *darwin* ]] || [[ "$OSTYPE" == *macos* ]]; then 44 | echo "${OSTYPE}: emulator ${options} -gpu swiftshader_indirect" 45 | nohup emulator $options -gpu swiftshader_indirect & 46 | fi 47 | 48 | if [ $? -ne 0 ]; then 49 | echo "Error launching emulator" 50 | return 1 51 | fi 52 | } 53 | 54 | 55 | function check_emulator_status () { 56 | printf "${G}==> ${BL}Checking emulator booting up status 🧐${NC}\n" 57 | start_time=$(date +%s) 58 | spinner=( "⠹" "⠺" "⠼" "⠶" "⠦" "⠧" "⠇" "⠏" ) 59 | i=0 60 | # Get the timeout value from the environment variable or use the default value of 300 seconds (5 minutes) 61 | timeout=${EMULATOR_TIMEOUT:-300} 62 | 63 | while true; do 64 | result=$(adb shell getprop sys.boot_completed 2>&1) 65 | 66 | if [ "$result" == "1" ]; then 67 | printf "\e[K${G}==> \u2713 Emulator is ready : '$result' ${NC}\n" 68 | adb devices -l 69 | adb shell input keyevent 82 70 | break 71 | elif [ "$result" == "" ]; then 72 | printf "${YE}==> Emulator is partially Booted! 😕 ${spinner[$i]} ${NC}\r" 73 | else 74 | printf "${RED}==> $result, please wait ${spinner[$i]} ${NC}\r" 75 | i=$(( (i+1) % 8 )) 76 | fi 77 | 78 | current_time=$(date +%s) 79 | elapsed_time=$((current_time - start_time)) 80 | if [ $elapsed_time -gt $timeout ]; then 81 | printf "${RED}==> Timeout after ${timeout} seconds elapsed 🕛.. ${NC}\n" 82 | break 83 | fi 84 | sleep 4 85 | done 86 | }; 87 | 88 | 89 | function disable_animation() { 90 | adb shell "settings put global window_animation_scale 0.0" 91 | adb shell "settings put global transition_animation_scale 0.0" 92 | adb shell "settings put global animator_duration_scale 0.0" 93 | }; 94 | 95 | function hidden_policy() { 96 | adb shell "settings put global hidden_api_policy_pre_p_apps 1;settings put global hidden_api_policy_p_apps 1;settings put global hidden_api_policy 1" 97 | }; 98 | 99 | launch_emulator 100 | sleep 2 101 | check_emulator_status 102 | sleep 1 103 | disable_animation 104 | sleep 1 105 | hidden_policy 106 | sleep 1 -------------------------------------------------------------------------------- /start_vnc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | readonly G_LOG_I='[INFO]' 4 | readonly G_LOG_W='[WARN]' 5 | readonly G_LOG_E='[ERROR]' 6 | BL='\033[0;34m' 7 | G='\033[0;32m' 8 | NC='\033[0m' # No Color 9 | 10 | main() { 11 | launch_xvfb 12 | launch_window_manager 13 | run_vnc_server 14 | printf "${G}==> ${BL}Welcome to android-emulator VNC by amrsa ${G}<==${NC}""\n" 15 | } 16 | 17 | launch_xvfb() { 18 | # Set defaults if the user did not specify envs. 19 | export DISPLAY=${XVFB_DISPLAY:-:1} 20 | local screen=${XVFB_SCREEN:-0} 21 | local resolution=${XVFB_RESOLUTION:-1280x1024x24} 22 | local timeout=${XVFB_TIMEOUT:-5} 23 | 24 | # Start and wait for either Xvfb to be fully up or we hit the timeout. 25 | Xvfb ${DISPLAY} -screen ${screen} ${resolution} & 26 | local loopCount=0 27 | until xdpyinfo -display ${DISPLAY} > /dev/null 2>&1 28 | do 29 | loopCount=$((loopCount+1)) 30 | sleep 1 31 | if [ ${loopCount} -gt ${timeout} ] 32 | then 33 | echo "${G_LOG_E} xvfb failed to start." 34 | exit 1 35 | fi 36 | done 37 | } 38 | 39 | launch_window_manager() { 40 | local timeout=${XVFB_TIMEOUT:-5} 41 | 42 | # Start and wait for either fluxbox to be fully up or we hit the timeout. 43 | fluxbox & 44 | local loopCount=0 45 | until wmctrl -m > /dev/null 2>&1 46 | do 47 | loopCount=$((loopCount+1)) 48 | sleep 1 49 | if [ ${loopCount} -gt ${timeout} ] 50 | then 51 | echo "${G_LOG_E} fluxbox failed to start." 52 | exit 1 53 | fi 54 | done 55 | } 56 | 57 | run_vnc_server() { 58 | local passwordArgument='-nopw' 59 | 60 | if [ -n "${VNC_PASSWORD}" ] 61 | then 62 | local passwordFilePath="${HOME}/x11vnc.pass" 63 | if ! x11vnc -storepasswd "${VNC_PASSWORD}" "${passwordFilePath}" 64 | then 65 | echo "${G_LOG_E} Failed to store x11vnc password." 66 | exit 1 67 | fi 68 | passwordArgument=-"-rfbauth ${passwordFilePath}" 69 | echo "${G_LOG_I} The VNC server will ask for a password." 70 | else 71 | echo "${G_LOG_W} The VNC server will NOT ask for a password." 72 | fi 73 | 74 | x11vnc -ncache_cr -display ${DISPLAY} -forever ${passwordArgument} & 75 | wait $! 76 | } 77 | 78 | 79 | control_c() { 80 | echo "" 81 | exit 82 | } 83 | 84 | trap control_c SIGINT SIGTERM SIGHUP 85 | 86 | main 87 | 88 | exit --------------------------------------------------------------------------------