diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..048b1cf --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [blueimp] diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..e44eb9e --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,10 @@ +name: Test + +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: shellcheck bin/*.sh diff --git a/bin/android-emulator.sh b/bin/android-emulator.sh index e9c301b..6d78302 100755 --- a/bin/android-emulator.sh +++ b/bin/android-emulator.sh @@ -1,12 +1,15 @@ #!/bin/sh # -# Starts the Android virtual device with a writeable filesystem. +# Starts an Android virtual device with a writeable filesystem. # If the -hosts option is provided, replaces /etc/hosts on the device with the # given hosts file. -# If no -avd option is given, starts the first AVD in the list. +# If the -return option is given, returns to the caller when the emulator is +# ready, otherwise waits for the emulator process to stop. +# If no emulator -avd option is given, starts the first AVD in the list. +# If no existing AVD is available, creates a new one. # -# Usage: ./android-emulator.sh [-hosts file] [emulator options] +# Usage: ./android-emulator.sh [-hosts file] [-return] [-- emulator options] # # Copyright 2019, Sebastian Tschan # https://blueimp.net @@ -17,67 +20,130 @@ set -e +DEVICE_ID='pixel' +SYSTEM_IMAGE_REGEXP='system-images;android-[0-9]*;google_apis;x86\>' +WRITABLE_SYSTEM_IMAGE='system-images;android-28;google_apis;x86' +SDCARD='512M' + if [ -z "$ANDROID_HOME" ]; then echo 'Error: ANDROID_HOME is not defined.' >&2 exit 1 fi -# shellcheck disable=SC2139 -alias emulator="$ANDROID_HOME/emulator/emulator" -# shellcheck disable=SC2139 -alias adb="$ANDROID_HOME/platform-tools/adb" +adb() { + "$ANDROID_HOME/platform-tools/adb" "$@" +} + +emulator() { + "$ANDROID_HOME/emulator/emulator" "$@" +} + +avdmanager() { + "$ANDROID_HOME/cmdline-tools/latest/bin/avdmanager" "$@" +} + +sdkmanager() { + "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" "$@" +} + +normalize() { + echo "$1" | sed 's/[^a-z A-Z 0-9._-]/-/g' +} -# Echos first AVD listed -avd() { +get_avd() { emulator -list-avds | head -n 1 } -is_boot_completed() { - test "$(adb shell getprop sys.boot_completed | tr -d '\r')" = 1 +get_image() { + if [ -n "$HOSTS_FILE" ]; then + echo "$WRITABLE_SYSTEM_IMAGE" + else + sdkmanager --list | grep -o "$SYSTEM_IMAGE_REGEXP" | tail -1 + fi +} + +download_image() { + sdkmanager "$1" } -has_avd_arg() { +create_avd() { + echo 'Downloading system image ...' + download_image "$1" + echo 'System image downloaded.' + echo 'Creating Android Virtual Device ...' + avdmanager create avd \ + --name "$(normalize "$DEVICE_ID-${1#*;}")" \ + --package "$1" \ + --device "$DEVICE_ID" \ + --sdcard "$SDCARD" + echo 'Virtual Device created.' +} + +has_arg() { while test $# -gt 0; do - test "$1" = -avd && return 0 + test "$1" = "$ARG" && return 0 shift done return 1 } -update_hosts_file() { +has_system_prop() { + test "$(adb shell getprop "$1" | tr -d '\r')" = "$2" +} + +wait_for_device() { echo 'Waiting for device to be ready ...' adb wait-for-device - while ! is_boot_completed; do + while ! has_system_prop sys.boot_completed 1; do sleep 1 done + echo 'Device ready.' +} + +update_hosts_file() { adb root + wait_for_device adb remount adb push "$1" /etc/hosts adb unroot + wait_for_device } -shutdown() { - kill "$PID" -} - -# Initiate a shutdown on SIGINT and SIGTERM: -trap 'shutdown; exit' INT TERM - if [ "$1" = -hosts ]; then HOSTS_FILE=$2 shift 2 fi -if ! has_avd_arg "$@"; then - set -- -avd "$(avd)" "$@" +if [ "$1" = -return ]; then + RETURN=true + shift +fi + +if [ "$1" = -- ]; then + shift +fi + +if ! ARG=-avd has_arg "$@"; then + if [ -z "$(get_avd)" ]; then + create_avd "$(get_image)" + fi + set -- -avd "$(get_avd)" "$@" fi -set -- -writable-system "$@" +if [ -n "$HOSTS_FILE" ]; then + set -- -writable-system "$@" +fi emulator "$@" & PID=$! +wait_for_device + if [ -n "$HOSTS_FILE" ]; then update_hosts_file "$HOSTS_FILE" fi +if [ "$RETURN" = true ]; then + exit +fi + wait "$PID"