Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Building a react native app in WSL2

Building a react native app in WSL2

Install, build and debug a react native app in WSL2 (Windows Subsystem for Linux) and Ubuntu.

Install tools in Windows

  • Install WSL2 and Ubuntu, see here
  • Install Android Studion, see here
  • Install Viusal Studio Code, see here

Install tools in WSL2

  • Install java-8-openjdk in WSL2 (sudo apt-get install openjdk-8-jre)
  • Install Android SDK cmdline tools in WSL2, see here and adjust directory structure, see here
  • Install nodejs in WSL2, see here

Set environment variables in .profile or .bash_profile

export ANDROID_HOME=/home/xxx/Android/cmdline-tools/latest
export ANDROID_SDK_ROOT=/home/xxx/Android

PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools
PATH=$PATH:$ANDROID_HOME/bin

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

Connect to android hardware device from WSL2

To debug on a hardware device connect to android device via usbip from WSL2 (thanks to @cjshearer):

Connect to android virtual device in Windows

To debug on a virtual device create a virtual device (e.g. Nexus_5X_API_29) in windows with Android Virtual Device Manager from Android Studio.

Start android virtual device in Windows

Start Android virtual device (e.g. Nexus_5X_API_29) in windows

"C:\Program Files (x86)\Android\android-sdk\emulator\emulator.exe" -avd Nexus_5X_API_29

Start adb server in Windows

adb kill-server
adb -a nodaemon server start

Change firewall rule for adb.exe on first usage in Defender Popup or with Windows Defender Firewall allowing access for the public profile, because the vEthernet (Wsl) adapter belongs to the public profile

Enable access to adb server from WSL2

Set environment variable to access adb server, WSL_HOST is ip of vEthernet (WSL) interface in windows

export WSL_HOST=$(tail -1 /etc/resolv.conf | cut -d' ' -f2)
export ADB_SERVER_SOCKET=tcp:$WSL_HOST:5037

Somtimes adb crashes using the environment variable config. One solution is to use socat (thanks to @tuanna1601).

Unset the environment variable if necessary.

unset ADB_SERVER_SOCKET

Install socat (eg. sudo apt-get install socat). Socat relays the requests from wsl2 to windows using the following command:

socat -d -d TCP-LISTEN:5037,reuseaddr,fork TCP:$(cat /etc/resolv.conf | tail -n1 | cut -d " " -f 2):5037

Enable access to metro bundler from Windows

The metro bundler is running in WSL2, listening on port 8081. Windows 10 version 2004 brings network forwarding from WSL2 to Windows. So the app can connect to the metro bundler from the emulator via Windows localhost.

Sometimes there are problems with the network forwarding. A work around is to use the following script.

WSL_CLIENT is ip of WSL2.

iex "netsh interface portproxy delete v4tov4 listenport=8081 listenaddress=127.0.0.1" | out-null;
$WSL_CLIENT = bash.exe -c "ifconfig eth0 | grep 'inet '";
$WSL_CLIENT -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
$WSL_CLIENT = $matches[0];
iex "netsh interface portproxy add v4tov4 listenport=8081 listenaddress=127.0.0.1 connectport=8081 connectaddress=$WSL_CLIENT"

Create react native app in WSL2

npx react-native init AwesomeProject

Build app in WSL2

Add paraameter in file proguard-rules.pro to ignore okhttp3 warnings

-dontwarn okhttp3.internal.platform.*

Start metro JavaScript bundler and bind to an ipv4 address to enable port forwarding to windows

npx react-native start --host 127.0.0.1

Build app, set device as parameter deviceId from result of adb devices

npx react-native run-android --variant=debug --deviceId emulator-5554

Debug app in Visual Studio Code from WSL2

Start vs code in WSL2

code .

and install extensions for VS Code

  • Remote - WSL
  • React Native Tools

VS Code UI runs in windows and the VS Code Server runs in WSL2, see here

Add a launch configuration in file launch.json with specified type and target

"type": "reactnative",
"target": "emulator-5554"

Start debugging.

@rickerp
Copy link

rickerp commented Jan 31, 2021

Yes I did. I found out now it was caused by issue with firewall.
I am getting both emulator and phone on the list but when I try to run expo start -a I hit Couldn't start project on Android: could not connect to TCP port 5554: Connection refused

Yes I did. I found out now it was caused by issue with firewall.
I am getting both emulator and phone on the list but when I try to run expo start -a I hit Couldn't start project on Android: could not connect to TCP port 5554: Connection refused

@murbanowicz , were you able to fix this issue? I have the same problem.
@romonsalve

Having the same problem, anyone was able to fix the issue?

@romonsalve
Copy link

romonsalve commented Jan 31, 2021

@rickerp actually you must use the deviceID param to connect to the emulator
like this npx react-native run-android --variant=debug --deviceId emulator-5554

But for a react native "problem" (or decision?) it always target release build, even if you specify other variant.
For a expo build i don't how to specify that deviceId.

The same problem happen when i try npx react-native run-android, that by default selects the firts emulator or device, but it fails

I ended runing react native from windows with nvm.

@rickerp
Copy link

rickerp commented Feb 3, 2021

@romonsalve hmm, still trying with expo and can't specify the deviceId
Another speculation is that expo is trying the port of the deviceId number. For emulator-5554 it is trying the 5554 port, and not the port that we allow to connect to Windows (5037)

@sobhanb-eth
Copy link

sobhanb-eth commented Feb 21, 2021

Is there a complete version of this guide updated for the latest changes?
It's been 2 days now playing around this, no LUCK!
tried everything, either gives an error for expecting the android tools folder to be in some other place or for unaccepted licenses or can't connect to adb or there are so many other things ... please kindly guide me through the updated process.

Windows 10 20H2 19042.804
WSL 2 Ubuntu 20 LTS
Android Studio in Windows ...

I am facing all kinds of problems ... please please help

@georgealan
Copy link

georgealan commented Feb 22, 2021

Is there a complete version of this guide updated for the latest changes?
It's been 2 days now playing around this, no LUCK!

@ViperTechnologies-RnD Hey man, look at my post on the gist, I made a guide and some people were successful, maybe I can help you, it's in Brazilian Portuguese.

https://gist.github.com/georgealan/353a548814fe9b82a3a502926c7a42c6

@e4basil
Copy link

e4basil commented Mar 10, 2021

I followed your tutorial but i stuck with

Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release

how I resolve this issue

@seklyza
Copy link

seklyza commented Mar 18, 2021

@romonsalve hmm, still trying with expo and can't specify the deviceId
Another speculation is that expo is trying the port of the deviceId number. For emulator-5554 it is trying the 5554 port, and not the port that we allow to connect to Windows (5037)

Did you manage to solve this? When running adb devices I do see my Emulator, but Expo just says Connection Refused.

@rickerp
Copy link

rickerp commented Mar 21, 2021

@seklyza No, just started using tunnel mode or private network ip

@dbconrado
Copy link

dbconrado commented Apr 14, 2021

I was unable to connect to the Metro Bundler from the emulator. I was getting "Unable to load script".

I get it to work by disabling the firewall and omitting the --host part when running npx react-native start.

@davisjr
Copy link

davisjr commented May 10, 2021

Despite setting ADB_SERVER_SOCKET, my gradle task is trying to start adb on WSL. It hangs at 99% and the app is not installed on the emulator. Anyone else hitting this?

12:56:53 D/ddms: Launching '/home/davisj/Android/Sdk/platform-tools/adb start-server' to ensure ADB is running.
12:56:53 D/ddms: '/home/davisj/Android/Sdk/platform-tools/adb start-server' succeeded
12:56:53 I/DeviceMonitor: adb restarted
12:56:54 D/DeviceMonitor: Opening adb connection
12:56:54 E/DeviceMonitor: Unable to open connection to: localhost/127.0.0.1:5037, due to: java.net.ConnectException: Connection refused
12:56:54 E/DeviceMonitor: Connection attempts: 1570

@davisjr
Copy link

davisjr commented May 10, 2021

I was able to get past this by using socat. Looks like WSL port forwarding wasn't working as expected although I was able to talk to the adb server on Windows from the command line.

@cjshearer
Copy link

cjshearer commented May 12, 2021

If you're going to use socat, I would suggest using adb -a -P 5037 nodaemon server when running adb on windows, before using socat -d -d TCP-LISTEN:5037,reuseaddr,fork TCP:$(cat /etc/resolv.conf | tail -n1 | cut -d " " -f 2):5037 on wsl.

When forwarding the metro bundler ports I had to use the following to open a firewall on windows:

  • $WSL_CLIENT = bash.exe -c "ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'"
  • iex "netsh interface portproxy add v4tov4 listenport=8081 listenaddress=127.0.0.1 connectport=8081 connectaddress=$WSL_CLIENT"

@robba86
Copy link

robba86 commented May 29, 2021

C:\Users\<me>\AppData\Local\Android\sdk\tools\emulator.exe

@raulpesilva
Copy link

raulpesilva commented Jun 16, 2021

This work for me to ubuntu 20.04.
script to get windows ip and wls ip and foward port and ip
and to display right ip on expo set this

REACT_NATIVE_PACKAGER_HOSTNAME=your_windows_host_ip
ex wsl terminal:
export REACT_NATIVE_PACKAGER_HOSTNAME=192.168.38.16

#//wsl2Unlock.ps1
$windowsIp = bash -c "ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'"
$wslIp = wsl ~ -d Ubuntu-20.04 -e ip addr show eth0
$found = $wslIp -match '(?<=inet\s)\d+(\.\d+){3}';

if ( $found ) {
  $found[0] -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
  $wslIp = $matches[0]
}
else {
  Write-Output "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}
Write-Output $wslIp
Write-Output $windowsIp

# show all portproxy
Invoke-Expression "netsh interface portproxy show v4tov4"

#remove all 
Invoke-Expression "netsh int portproxy reset all"

# Remove Firewall Exception Rules
Invoke-Expression "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";

# [Ports]
# All the ports you want to forward separated by coma
$ports = @(19000, 19001, 19002, 19003, 19004, 19005, 19006);
$ports_a = $ports -join ",";


# #adding Exception Rules for inbound and outbound Rules
Invoke-Expression "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";
Invoke-Expression "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";

for ( $i = 0; $i -lt $ports.length; $i++ ) {
  $port = $ports[$i];
  Invoke-Expression "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$windowsIp connectport=$port connectaddress=$wslIp";
}

@AnthonyTailer
Copy link

AnthonyTailer commented Jul 1, 2021

I always have to execute the Metro Bundler Forwarding to connect to react-native... anyone knows why? Is there a definitive way to do this?

@pelarejo
Copy link

pelarejo commented Aug 18, 2021

I also have to execute the Metro Bundler Forwarding on startup before npm start.
I created a simple script executable from WSL to start the forwarding, along with starting the adb server.
I thought I'd share it here:

  • some/wsl/folder/start_adb.sh
#!/usr/bin/env sh

winpwd=$(printf "%s" "$PWD" | sed 's/\//\\/g')
powershell.exe Start-Process -Verb runas powershell.exe -ArgumentList "\"-NoExit -ExecutionPolicy Bypass \\\\wsl\$\\Ubuntu$winpwd\\proxy_adb.ps1\""
  • some/wsl/folder/proxy_adb.ps1
# Forward metro
iex "netsh interface portproxy delete v4tov4 listenport=8081 listenaddress=127.0.0.1" | out-null;
$WSL_CLIENT = bash.exe -c "ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'";
$WSL_CLIENT -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
$WSL_CLIENT = $matches[0];
iex "netsh interface portproxy add v4tov4 listenport=8081 listenaddress=127.0.0.1 connectport=8081 connectaddress=$WSL_CLIENT"
# Start adb server
adb kill-server
adb -a nodaemon server start

Simply launch the start_adb script, it will prompt you for admin rights. Remember to add adb to windows path.

@cjshearer
Copy link

cjshearer commented Nov 7, 2021

New Method for Android

  1. Install the sdk manager (without needing android studio).

  2. For physical devices: usbipd-win can now be used to expose your android device (or any usb device) directly in WSL2. I've tested and used this to deploy react-native apps to my android device. In addition, this method will work with debugging tools like Flipper, as it doesn't rely on a Windows ADB server.

See the discussion here if you have any issues getting it working for ADB: dorssel/usbipd-win#60

@bergmannjg
Copy link
Author

bergmannjg commented Nov 8, 2021

@cjshearer thank you very much, got it work on my box

@RakaDoank
Copy link

RakaDoank commented Dec 20, 2021

@cjshearer @bergmannjg i'm trying to connect my Android device from WSL2. Everything is fine with usbipd-win, even my device shows up in "adb devices" command (WSL2). But i get an error when i try "npx react-native run-android"

error Failed to install the app. Make sure you have the Android development environment set up: https://facebook.github.io/react-native/docs/getting-started.html#android-development-environment. Run CLI with --verbose flag for more details.Error: Command failed: ./gradlew app:installDebug -PreactNativeDevServerPort=8081

Also, i've tried with "npx react-native run-android --deviceId=", still i get an error, but it says

error Failed to build the app. Run CLI with --verbose flag for more details. Error: Command failed: ./gradlew build -x lint

How do you guys make it work?
My last last last step is use Ubuntu directly (dual boot alongside Windows).

@bergmannjg By the way, i've also tried connecting android virtual device in Windows from WSL2, and i also get the second error.

@bergmannjg
Copy link
Author

bergmannjg commented Dec 23, 2021

@RakaDoank what is the error msg of

./gradlew app:installDebug -PreactNativeDevServerPort=8081

@RakaDoank
Copy link

RakaDoank commented Dec 24, 2021

@bergmannjg i get

bash: ./gradlew: No such file or directory

i only found out the error after you asked. So, i tried gradle wrapper first and run the ./gradlew command again, then i get this new error

Project 'app' not found in root project 'myProject'

I'm sorry, this is probably not a WSL issue.

@iamdevlinph
Copy link

iamdevlinph commented Mar 21, 2022

Has anyone have an updated version of the guide? Been stuck on different places.

@sprngLf
Copy link

sprngLf commented Apr 7, 2022

ERROR ON:

adb kill-server
adb -a nodaemon server start

emulator-5554: already offline
what does this mean?
error

@luizwhite
Copy link

luizwhite commented Apr 30, 2022

For those struggling with Expo with the error Couldn't start project on Android: could not connect to TCP port 5554: Connection refused

I'm no expert, but debugging things a little with variables EXPO_DEBUG=1 and ADB_TRACE=adb, I found out that expo start was executing the command adb -s emulator-5554 emu avd name , and somehow this command from the Ubuntu side didn't work (maybe someone here can help fix this), but the adb running on Windows could run that command from Ubuntu with adb.exe.

So, I successfully overrode that with sudo ln -s /mnt/c/Android/Sdk/platform-tools/adb.exe ~/Android/sdk/platform-tools/adb after backing up the original ubuntu adb executable (just fix that path with your windows adb path and your possible custom ubuntu adb path)
image

I did that only when running the expo start command and all worked smoothly (until now at least)

If anyone can help us to find out why adb on ubuntu side cannot access the emulator, I would appreciate it (even when adb devices runs normally and lists the device)


PS: all worked without

  • any netsh interface portproxy or
  • any adb reverse or
  • firewall rule to allow WSL ports (only rule to allow adb program)
  • admin rights command execution
  • socat alternative

But I used the variables below:

export WSL_HOST=$(tail -1 /etc/resolv.conf | cut -d' ' -f2)
export ADB_SERVER_SOCKET=tcp:$WSL_HOST:5037
export ADB_TRACE=adb
export EXPO_DEBUG=1
export ANDROID_SERIAL=emulator-5554
export REACT_NATIVE_PACKAGER_HOSTNAME=$(ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')

and...

  • used same version of platform-tools on both windows and ubuntu
  • used adb kill-server && adb -a -P 5037 nodaemon server start on Windows side after emulator loaded

versions...

  • Windows 11 and Ubuntu 20.04
  • expo-cli 5.4.3
  • last version of node and npm (v16.15.0 - v8.8.0)
  • emulator running avd Pixel_4_API_30 with Google APIs
  • usb debug mode enabled on emulator
  • adb version 1.0.41 and platform-tools 33.0.1

@OptimBro
Copy link

OptimBro commented May 3, 2022

For those struggling with Expo with the error Couldn't start project on Android: could not connect to TCP port 5554: Connection refused

I'm no expert, but debugging things a little with variables EXPO_DEBUG=1 and ADB_TRACE=adb, I found out that expo start was executing the command adb -s emulator-5554 emu avd name , and somehow this command from the Ubuntu side didn't work (maybe someone here can help fix this), but the adb running on Windows could run that command from Ubuntu with adb.exe.

So, I successfully overrode that with sudo ln -s /mnt/c/Android/Sdk/platform-tools/adb.exe ~/Android/sdk/platform-tools/adb after backing up the original ubuntu adb executable (just fix that path with your windows adb path and your possible custom ubuntu adb path) image

I did that only when running the expo start command and all worked smoothly (until now at least)

If anyone can help us to find out why adb on ubuntu side cannot access the emulator, I would appreciate it (even when adb devices runs normally and lists the device)

PS: all worked without

  • any netsh interface portproxy or
  • any adb reverse or
  • firewall rule to allow WSL ports (only rule to allow adb program)
  • admin rights command execution
  • socat alternative

But I used the variables below:

export WSL_HOST=$(tail -1 /etc/resolv.conf | cut -d' ' -f2)
export ADB_SERVER_SOCKET=tcp:$WSL_HOST:5037
export ADB_TRACE=adb
export EXPO_DEBUG=1
export ANDROID_SERIAL=emulator-5554
export REACT_NATIVE_PACKAGER_HOSTNAME=$(ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')

and...

  • used same version of platform-tools on both windows and ubuntu
  • used adb kill-server && adb -a -P 5037 nodaemon server start on Windows side after emulator loaded

versions...

  • Windows 11 and Ubuntu 20.04
  • expo-cli 5.4.3
  • last version of node and npm (v16.15.0 - v8.8.0)
  • emulator running avd Pixel_4_API_30 with Google APIs
  • usb debug mode enabled on emulator
  • adb version 1.0.41 and platform-tools 33.0.1

Thanks, @luizwhite , it really helped. It was the easiest one I found on the internet so far 😊 . Let's wait for someone who got some ideas about it.

@bongofury
Copy link

bongofury commented May 6, 2022

@luizwhite thanks a lot! Your solution works like a charm. That's what I was searching for. 🍺

@amaxalov
Copy link

amaxalov commented Jun 16, 2022

For the proxy to work properly with socat. still need to run npx react-native start --host 0.0.0.0 without 127.0.0.1

@iago-silva
Copy link

iago-silva commented Jul 20, 2022

Wonderful!

@dkornilove
Copy link

dkornilove commented Jul 26, 2022

I had the experience of successfully setting up and running react native applications on WSL + Windows AVD emulator with using socat command. But recently I moved to a new computer and did everything as it was on the last machine, only with a newer SDK and tools versions and after running the adb devices command on the WSL, I get this error
adb: failed to check server version: protocol fault (couldn't read status): Success
while windows adb server and socat command run successfully.
And when I kill the socat process, adb devices command works well, but without seeing the windows emulator for sure.
All SDK and tool versions are the same on Windows and WSL.
Can someone help me figure out what it is?

socat log for the adb devices query

2022/07/26 17:28:34 socat[2129] N opening connection to AF=2 172.17.96.1:5037
2022/07/26 17:29:07 socat[2129] E connect(5, AF=2 172.17.96.1:5037, 16): Connection timed out
2022/07/26 17:29:07 socat[2129] N exit(1)

upd: solved by adding the firewall rule for adb.exe

@kicksent
Copy link

kicksent commented Aug 30, 2022

and adjust directory structure, see here

Wish this section was more clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment