Connect to an Android Emulator running on Linux from Windows

Say what? (Photo by David Clode on Unsplash)

Once upon a time I needed to connect to an Android emulator running on a Linux box from a Windows virtual machine. Yes, it was very strange. In case you every find yourself in a similar situation, here’s one way to do it.

On the Linux side

  • On the Linux box, install Android Studio, including the Platform SDK tools
  • Use the AVD Manager to install and run an android emulator
  • Kill the existing adb server: ~/Android/Sdk/platform-tools/adb kill-server
  • See which port the emulator is listening on (Usually 5555): lsof -iTCP -sTCP:LISTEN -P | grep 'emulator\|qemu'
  • Create a named pipe named /tmp/emupipe (Could be called anything):
cd /tmp
mkfifo emupipe
  • Use Netcat to shuttle TCP traffic from an external port to localhost:5555
nc -kl 15555 0<emupipe | nc 127.0.0.1 5555 > emupipe

On the Windows side

  • On the Windowds side, add C:\Program Files (x86)\Android\android-sdk\platform-tools to your PATH so that you have easy access to adb
  • Connect adb to the remote emulator: adb connect <IP>:15555

The IP address could be an address of a remote server, the VM host, etc. In this case, Windows was inside a qemu VM, which lets us connect to the host using 10.0.2.2. So the adb command looked like:

adb connect 10.0.2.2:15555

Tear down the connection

When you’re done emulating, all you have to do is kill the nc command.

Automate starting the emulator and setting up the backpipe

Getting up and running involves a lot of steps, so here’s a zsh script that starts the android emulator and sets up that netcat traffic forwarding.

#!/usr/bin/env zsh

zmodload zsh/zutil
zparseopts -D -E -F -- -cold=cold || exit 1

optColdBoot='-no-snapshot-load'
if [ -z $cold ]; then
	optColdBoot=''
fi

autoload colors; colors

#-----
echo "$fg[green]\n# Searching for AVDs$reset_color"

avds=$(~/Android/Sdk/emulator/emulator -list-avds)
echo "$fg[yellow]👇 Found:"
echo "$fg[blue]$avds$reset_color"

avd=$(echo $avds | head -1)
echo "$fg[green]\n# Starting '$avd'$reset_color"
~/Android/Sdk/emulator/emulator @$avd -netdelay none -netspeed full -gpu host -cores 8 -memory 3072 $optColdBoot &

waitSeconds=45
if [ -z $cold ]; then
	waitSeconds=10
fi
# Countdown
while [ $waitSeconds -gt 0 ]; do
   echo -ne "Countdown: $waitSeconds\033[0K\r"
   sleep 1
   : $((waitSeconds--))
done

#-----
pipe="/tmp/emupipe"
echo "$fg[green]\n# Creating named pipe '$pipe'$reset_color"

echo "$fg[yellow]--Removing any existing$reset_color"
rm -f $pipe
echo "$fg[yellow]--Creating new pipe$reset_color"
mkfifo $pipe

#----
listenPort=15555
forwardPort=5555
echo "$fg[green]\n# Forwarding port $fg[magenta]$listenPort$fg[green] to $fg[magenta]$forwardPort$reset_color"

ip=$(ip -4 a show eno1 | grep -Po 'inet \K[0-9.]+')
echo "$fg[yellow]--$fg[gray]From the VM run $fg[cyan]adb connect $ip:$listenPort'$reset_color"

echo "$fg[green]\nListening...(keep terminal open)$reset_color"

nc -kl $listenPort 0<$pipe | nc 127.0.0.1 $forwardPort > $pipe
Avatar
Ty Walls
Digital Construction Worker

Ty Walls is a software engineer in love with creating, learning, and teaching.

Related