Skip to content

Instantly share code, notes, and snippets.

@sergchil
Last active April 28, 2025 13:08
Show Gist options
  • Save sergchil/694544de77ec6c4f4b86238dcae86174 to your computer and use it in GitHub Desktop.
Save sergchil/694544de77ec6c4f4b86238dcae86174 to your computer and use it in GitHub Desktop.
A bash script to easily manage and run Android Emulators with a nice interactive terminal interface.
#!/bin/bash
# Android Emulator launcher script
# Created: April 28, 2025
# Author: Sergey Chilingaryan
#
# This script helps manage and run Android emulators with common configuration options.
# It detects the Android SDK location, lists available emulators with interactive
# arrow key navigation, and launches them with customizable options.
# Setup terminal for interactive mode
stty -echo
tput civis # Hide cursor
# Restore terminal settings on exit
cleanup() {
tput cnorm # Show cursor
stty echo
exit 0
}
trap cleanup EXIT
trap cleanup INT
# Colors for better readability
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
WHITE='\033[1;37m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# Symbols for menu
POINTER=""
UNSELECTED=" "
# Find Android SDK location
if [ -d "$HOME/Library/Android/sdk" ]; then
ANDROID_SDK="$HOME/Library/Android/sdk"
elif [ -d "$ANDROID_HOME" ]; then
ANDROID_SDK="$ANDROID_HOME"
elif [ -d "$ANDROID_SDK_ROOT" ]; then
ANDROID_SDK="$ANDROID_SDK_ROOT"
else
echo -e "${RED}Error: Android SDK not found.${NC}"
echo "Please set ANDROID_HOME or ANDROID_SDK_ROOT environment variable."
exit 1
fi
# Define paths to Android tools
EMULATOR="$ANDROID_SDK/emulator/emulator"
AVDMANAGER="$ANDROID_SDK/cmdline-tools/latest/bin/avdmanager"
SDKMANAGER="$ANDROID_SDK/cmdline-tools/latest/bin/sdkmanager"
# Check if emulator exists
if [ ! -f "$EMULATOR" ]; then
# Try alternate locations
if [ -f "$ANDROID_SDK/tools/emulator" ]; then
EMULATOR="$ANDROID_SDK/tools/emulator"
else
echo -e "${RED}Error: Emulator not found at $EMULATOR${NC}"
echo -e "${YELLOW}Please ensure the Android emulator is installed correctly.${NC}"
exit 1
fi
fi
# Check for avdmanager in different locations
if [ ! -f "$AVDMANAGER" ]; then
# Try alternate locations
if [ -f "$ANDROID_SDK/tools/bin/avdmanager" ]; then
AVDMANAGER="$ANDROID_SDK/tools/bin/avdmanager"
fi
fi
# Function to get all available emulators
get_emulators() {
emulators=$("$EMULATOR" -list-avds)
if [ $? -ne 0 ] || [ -z "$emulators" ]; then
echo -e "${YELLOW}No emulators found. Create one using Android Studio or avdmanager.${NC}"
exit 0
fi
# Convert string to array using a more compatible method
EMULATOR_ARRAY=()
while IFS= read -r line; do
[ -n "$line" ] && EMULATOR_ARRAY+=("$line")
done <<< "$emulators"
# Verify we have emulators
if [ ${#EMULATOR_ARRAY[@]} -eq 0 ]; then
echo -e "${YELLOW}No emulators found. Create one using Android Studio or avdmanager.${NC}"
exit 0
fi
}
# Function to read a single keypress
read_key() {
# Use a simpler method to read keys without timeout
escape_char=$(printf "\033")
IFS= read -r -s -n1 key
# Handle multi-character sequences like arrow keys
if [[ $key = $escape_char ]]; then
# It's an escape sequence
read -r -s -n1 k1
read -r -s -n1 k2
key="${escape_char}${k1}${k2}"
fi
echo "$key"
}
# Function to clear screen and display header
display_header() {
clear
echo -e "${GREEN}${BOLD}========================================${NC}"
echo -e "${GREEN}${BOLD} Android Emulator Launcher${NC}"
echo -e "${GREEN}${BOLD}========================================${NC}"
echo
}
# Function to display emulator list with selection
display_emulator_list() {
display_header
local selected_idx=$1
local total=${#EMULATOR_ARRAY[@]}
echo -e "${BLUE}${BOLD}Available Android Virtual Devices:${NC}"
echo -e "${YELLOW}Use arrow keys to navigate, Enter to select${NC}"
echo
for i in "${!EMULATOR_ARRAY[@]}"; do
if [ "$i" -eq "$selected_idx" ]; then
echo -e "${CYAN}${POINTER} ${WHITE}${BOLD}${EMULATOR_ARRAY[$i]}${NC}"
else
echo -e "${UNSELECTED} ${EMULATOR_ARRAY[$i]}"
fi
done
}
# Function to select an emulator using arrow keys
select_emulator() {
get_emulators
# If no emulators found, exit
if [ ${#EMULATOR_ARRAY[@]} -eq 0 ]; then
echo -e "${YELLOW}No emulators found. Create one using Android Studio or avdmanager.${NC}"
exit 0
fi
local selected=0
local key=""
display_emulator_list $selected
while true; do
key=$(read_key)
case "$key" in
$'\e[A') # Up arrow
((selected--))
if [ $selected -lt 0 ]; then
selected=$((${#EMULATOR_ARRAY[@]} - 1))
fi
display_emulator_list $selected
;;
$'\e[B') # Down arrow
((selected++))
if [ $selected -ge ${#EMULATOR_ARRAY[@]} ]; then
selected=0
fi
display_emulator_list $selected
;;
'') # Enter key
AVD_NAME="${EMULATOR_ARRAY[$selected]}"
break
;;
'q') # Quit
echo
echo "Exiting..."
exit 0
;;
esac
done
}
# Function to display boot options menu
display_boot_options() {
display_header
local selected_idx=$1
local options=("Run normally" "Run with cold boot" "Run with wipe data" "Run with wipe data and cold boot")
echo -e "${BLUE}${BOLD}Selected Emulator: ${WHITE}${AVD_NAME}${NC}"
echo -e "${YELLOW}Use arrow keys to navigate, Enter to select${NC}"
echo
for i in "${!options[@]}"; do
if [ "$i" -eq "$selected_idx" ]; then
echo -e "${CYAN}${POINTER} ${WHITE}${BOLD}${options[$i]}${NC}"
else
echo -e "${UNSELECTED} ${options[$i]}"
fi
done
}
# Function to select boot option using arrow keys
select_boot_option() {
local selected=0
local key=""
local options=("Run normally" "Run with cold boot" "Run with wipe data" "Run with wipe data and cold boot")
# Set default emulator options
EMULATOR_OPTS=""
display_boot_options $selected
while true; do
key=$(read_key)
case "$key" in
$'\e[A') # Up arrow
((selected--))
if [ $selected -lt 0 ]; then
selected=$((${#options[@]} - 1))
fi
display_boot_options $selected
;;
$'\e[B') # Down arrow
((selected++))
if [ $selected -ge ${#options[@]} ]; then
selected=0
fi
display_boot_options $selected
;;
'') # Enter key
case $selected in
0) # Run normally
EMULATOR_OPTS=""
;;
1) # Run with cold boot
EMULATOR_OPTS="$EMULATOR_OPTS -no-boot-anim -no-snapshot"
;;
2) # Run with wipe data
EMULATOR_OPTS="$EMULATOR_OPTS -wipe-data"
;;
3) # Run with wipe data and cold boot
EMULATOR_OPTS="$EMULATOR_OPTS -wipe-data -no-boot-anim -no-snapshot"
;;
esac
break
;;
'q') # Quit
echo
echo "Exiting..."
exit 0
;;
esac
done
}
# Function to display help menu
show_help() {
echo -e "${GREEN}Android Emulator Launcher${NC}"
echo "Usage: $0 [options] [avd_name]"
echo
echo "Options:"
echo " -h, --help Show this help message"
echo " -l, --list List available emulators"
echo " -n, --no-snapshot Start without loading snapshot"
echo " -w, --wipe-data Wipe user data"
echo " -c, --cold-boot Perform a cold boot (no quickboot)"
echo " -g, --gpu MODE Set GPU emulation mode (auto, host, swiftshader, angle)"
echo " -d, --debug Run with debug logging enabled"
echo
echo "Examples:"
echo " $0 --list # List all AVDs"
echo " $0 Pixel_4_API_30 # Run the Pixel_4_API_30 emulator"
echo " $0 -n -w Pixel_4_API_30 # Run with no snapshot and wipe data"
echo
}
# Advanced options menu
display_advanced_options() {
display_header
local selected_idx=$1
local options=(
"GPU Mode: auto"
"GPU Mode: host"
"GPU Mode: swiftshader"
"Debug Mode: Off"
"Debug Mode: On"
"Done - Return to previous menu"
)
echo -e "${BLUE}${BOLD}Advanced Options${NC}"
echo -e "${YELLOW}Use arrow keys to navigate, Enter to toggle option${NC}"
echo
for i in "${!options[@]}"; do
if [ "$i" -eq "$selected_idx" ]; then
echo -e "${CYAN}${POINTER} ${WHITE}${BOLD}${options[$i]}${NC}"
else
echo -e "${UNSELECTED} ${options[$i]}"
fi
done
}
# Function to select advanced options
select_advanced_options() {
local selected=0
local key=""
local GPU_MODE="auto"
local DEBUG_MODE="off"
local return_to_main=false
while [ "$return_to_main" = false ]; do
display_advanced_options $selected
key=$(read_key)
case "$key" in
$'\e[A') # Up arrow
((selected--))
if [ $selected -lt 0 ]; then
selected=5
fi
;;
$'\e[B') # Down arrow
((selected++))
if [ $selected -gt 5 ]; then
selected=0
fi
;;
'') # Enter key
case $selected in
0) # GPU Mode: auto
GPU_MODE="auto"
EMULATOR_OPTS=$(echo "$EMULATOR_OPTS" | sed 's/-gpu [^ ]*//g')
EMULATOR_OPTS="$EMULATOR_OPTS -gpu auto"
;;
1) # GPU Mode: host
GPU_MODE="host"
EMULATOR_OPTS=$(echo "$EMULATOR_OPTS" | sed 's/-gpu [^ ]*//g')
EMULATOR_OPTS="$EMULATOR_OPTS -gpu host"
;;
2) # GPU Mode: swiftshader
GPU_MODE="swiftshader"
EMULATOR_OPTS=$(echo "$EMULATOR_OPTS" | sed 's/-gpu [^ ]*//g')
EMULATOR_OPTS="$EMULATOR_OPTS -gpu swiftshader"
;;
3) # Debug Mode: Off
DEBUG_MODE="off"
EMULATOR_OPTS=$(echo "$EMULATOR_OPTS" | sed 's/-verbose//g')
;;
4) # Debug Mode: On
DEBUG_MODE="on"
EMULATOR_OPTS="$EMULATOR_OPTS -verbose"
;;
5) # Done
return_to_main=true
;;
esac
;;
'q') # Quit
echo
echo "Exiting..."
exit 0
;;
esac
done
}
# Main function to run the interactive menu system
main_menu() {
# Default emulator options
EMULATOR_OPTS=""
# Step 1: Select emulator
select_emulator
# Step 2: Select boot options
select_boot_option
# Launch the emulator
display_header
# Create logs directory if it doesn't exist
LOGS_DIR="$HOME/.android/emulator_logs"
mkdir -p "$LOGS_DIR"
# Create log file with timestamp
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
LOG_FILE="$LOGS_DIR/${AVD_NAME}_${TIMESTAMP}.log"
echo -e "${GREEN}Launching Android emulator: ${WHITE}${BOLD}${AVD_NAME}${NC}"
echo -e "${BLUE}With options: ${WHITE}${EMULATOR_OPTS}${NC}"
echo
echo -e "${GREEN}Emulator will run in the background and continue running after terminal is closed.${NC}"
echo -e "${BLUE}Log file: ${WHITE}${LOG_FILE}${NC}"
echo
# Show cursor again before running the emulator
tput cnorm
stty echo
# Launch the emulator in the background using nohup
nohup "$EMULATOR" -avd "$AVD_NAME" $EMULATOR_OPTS > "$LOG_FILE" 2>&1 &
# Store the PID
EMULATOR_PID=$!
echo -e "${YELLOW}Emulator started with PID: ${WHITE}${EMULATOR_PID}${NC}"
echo -e "${YELLOW}To stop the emulator later, run: ${WHITE}kill $EMULATOR_PID${NC}"
echo
# Wait a moment to make sure the emulator starts
sleep 2
# Check if the process is still running
if ps -p $EMULATOR_PID > /dev/null; then
echo -e "${GREEN}Emulator is running successfully in the background.${NC}"
return 0
else
echo -e "${RED}Failed to start emulator. Check the log file: ${WHITE}${LOG_FILE}${NC}"
return 1
fi
}
# Parse command line arguments
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
show_help
exit 0
fi
# Call main menu to start the interactive interface
main_menu
# Exit with the status from the emulator
exit $?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment