├── .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 |
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
--------------------------------------------------------------------------------