How can you connect your app on an Android emulator to a development server running on the localhost of your computer?
The problem#
Since Android emulators create their own virtual network, they cannot access devices on your local network.
This means:
localhost
refers to the emulator, not your laptop- local MDNS addresses
jmols.local
are not accessible
So accessing our development server at https://jmols.local:3000
results in the following error:
Method 1: use your computers IP address#
Huge thanks to Eduard-Cristian BoloČ™ for suggesting this solution.
Since Android emulators can access IP addresses on your network, you can directly point to the IP address of your computer.
Instead of loading https://jmols.local:3000
, you can load https://<YOUR_COMPUTER_IP>:3000
(e.g. https://192.168.1.123
).
This works on both emulators and Android phones!
However you may have to update the IP after connecting to a different network or when your IP lease expires.
Method 2: the loopback address#
Another approach is to change the server URL in your app and point it to 10.0.2.2
. This is a special alias to your host loopback interface (127.0.0.1 on your development machine).
So instead of loading https://jmols.local:3000
, our app will load https://10.0.2.2:3000
instead.
That fixes the emulator, but now our app no longer works on real devices. (since the loopback IP doesn’t exist there).
Can we find a single solution that works on both emulators and devices?
Method 3: redirect the emulator#
In this solution, we’ll instruct the emulator to redirect the IP address from the host machine to the loopback IP address automatically. We’ll do this by editing the etc/hosts
file on the Android emulator.
First, we need to ensure the etc/hosts
file is writable:
- Create a new emulator (non Google Play services, so we have access to root)
- Find the emulator AVD name of the emulator
emulator -list-avds
- Start your emulator from the command line with the option to enable a writable system
emulator -avd "<AVD_NAME_HERE>" -writable-system
- Run ADB as root
adb root
- Disable verified boot
adb disable-verity
- Reboot the device
adb reboot
- Wait for the device to be rebooted (ready when
adb shell
works) - Run ADB as root (again)
adb root
- Remount partitions as read-write
adb remount
Now we can overwrite the etc/hosts
file!
- First get the existing hosts file
adb pull etc/hosts
- Add an entry to direct your local server domain to the loopback address:
10.0.2.2 <YOUR_LOCAL_HOSTNAME>
. Your hostfile should look like this:
127.0.0.1 localhost
::1 ip6-localhost
10.0.2.2 jmols.local
- Save and push the file back to the emulator:
adb push hosts etc/hosts
Now our emulator can access our development server at https://jmols.local:3000
!
Notice how this solution can easily be generalized to any IP address on your local network.
Bonus: ADB reverse#
Huge thanks to Jeff Lewis for suggesting this solution.
React native uses ADB reverse to bind an emulator port to a port on your computer.
adb reverse tcp:3000 tcp:3000
Similarly to the loopback address, this solution isn’t suitable for a physical device.
Wrap-up#
Depending on your situation, there are several ways to connect an emulator to a local server. A universal - though complicated way - is to make etc/hosts
writable so you can access your development server using your local MDNS name.
If this was helpful to you, please let me know on Mastodon!