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!