Skip to content

Instantly share code, notes, and snippets.

@bergmannjg
Last active July 17, 2024 10:19
Show Gist options
  • Save bergmannjg/461958db03c6ae41a66d264ae6504ade to your computer and use it in GitHub Desktop.
Save bergmannjg/461958db03c6ae41a66d264ae6504ade to your computer and use it in GitHub Desktop.
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"

Connect to Windows Subsystem for Android

To debug the app running on Windows Subsystem for Android (WSA).

Install Windows Subsystem for Android.

Start adb server in Windows.

Enable access to adb server from WSL2.

Enable access to metro bundler from Windows Subsystem for Android

The metro bundler is running in WSL2, listening on port 8081.

To enable access from WSA to WSL2, configure adb reverse port forwarding on WSA.

Connect to the WSA via 127.0.0.1:58526 and execute adb reverse.

adb connect 127.0.0.1:58526
adb reverse tcp:8081 tcp:8081 

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

  • deviceId emulator: emulator-5554
  • deviceId WSA: 127.0.0.1:58526
npx react-native run-android --variant=debug --deviceId <deviceId>

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 request

"name": "Attach to packager",
"cwd": "${workspaceFolder}",
"type": "reactnative",
"request": "attach"

Build app, attach to packager and start debugging, see here.

@vagnerlandio
Copy link

I didn't follow the guide and I didn't need to do any extra config to make the react native environment work in WSL and testing on a physical device or WSA (Windows Subsystem for Android).

Just on physical device I enabled wifi debugging and on WSL:

adb pair <ip:port of physical device connected on the same network of the host computer that is running the WSL>
adb connect <ip:port>

npx react-native start
npx react-native run-android

After the build process then the app started both on the physical device and also on the WSA

@AdalZayas
Copy link

@vagnerlandio Thanks for that solution, i was trying to not leave wsl because i so greate for me, and my workspace is all around windows, so trying to find a solution to not use a device connected to my pc it was hard. To all who wants to usea a emulator, just install the WSA (Windows Subsystem for Android) and having the command line tools from android installed on WSL, you just do:

adb connect <ip:port> (try with 127.0.0.1:58526 if isn't working use yout local ip ex: 10.5.0.2:58526)

The port you can find it on the WSA > Advance Settings > Developer mode

Then run:

adb devices

List of devices attached
6pt8t8dqzhtwswz5        device
10.5.0.2:58526      device

With that now you can just run your command to run your RN app on the WSA

@ben-rochlin
Copy link

this is more of a comment, but all this feels very un-intuitive and damn near impossible.

@jeroenwienk
Copy link

Why do we need to start the metro bundle with --host 127.0.0.1. I can access the bundle fine from windows with a browser without setting the host but its not possible with the emulator that runs in windows. I fail to understand why.

@sepsol
Copy link

sepsol commented Jan 4, 2024

(@luizwhite regarding this comment) for the record, react-native run-android --interactive and react-native run-android --list-devices also call adb -s emulator-5554 emu avd name.

Calling that from Windows returns:

> adb -s emulator-5554 emu avd name
company-tablet
OK

While calling it from WSL returns:

$ adb -s emulator-5554 emu avd name
error: could not connect to TCP port 5554: Connection refused

And if I run it after I call socat, although the packets are captured, my adb session just hangs indefinitely:

$ socat -d -d TCP-LISTEN:5554,reuseaddr,fork TCP:$WSL_HOST:5554
2024/01/03 19:47:27 socat[22203] N listening on AF=2 0.0.0.0:5554
2024/01/03 19:47:33 socat[22203] N accepting connection from AF=2 127.0.0.1:51001 on AF=2 127.0.0.1:5554
2024/01/03 19:47:33 socat[22203] N forked off child process 22205
2024/01/03 19:47:33 socat[22203] N listening on AF=2 0.0.0.0:5554
2024/01/03 19:47:33 socat[22205] N opening connection to AF=2 172.27.208.1:5554
################ Long amount of time passes ################
2024/01/03 19:49:47 socat[22205] E connect(5, AF=2 172.27.208.1:5554, 16): Connection timed out
2024/01/03 19:49:47 socat[22205] N exit(1)
2024/01/03 19:49:47 socat[22203] N childdied(): handling signal 17

I can issue adb devices, adb shell and any other adb commands from my WSL without any issues, it is just this command that is the culprit.

P.S. react-native start and react-native run-android work fine without any issues with socat for port 5037 (ADB server). Linking Windows ADB to WSL ADB helped the other commands to execute fine as well.

@corysimmons
Copy link

@vagnerlandio Genius solution! Thank you. It works well!

@AdalZayas WSA + WSL sounds ideal, but when I try to run

# WSL Terminal
$ adb connect 127.0.0.1:58526 # this is the correct IP:PORT from the WSA Developer Settings area
failed to connect to '127.0.0.1:58526': Connection refused

Any ideas what I may be doing wrong? I've been trying to coax ChatGPT into helping but we've tried about everything including toggling my firewalls. 🙃

For everyone complaining about how insanely, overly-complicated this is, WELCOME TO REACT NATIVE, friends! 🎉 🫠

@AdalZayas
Copy link

@corysimmons Try using the ip of your windows machine

@corysimmons
Copy link

@AdalZayas I've tried using every IPv4 that appears in my ipconfig on my Windows machine + that port.

@AdalZayas
Copy link

@corysimmons have you tried to turn off all the firewall of wondows, idk why this make a conflict and this block the connection

@corysimmons
Copy link

@AdalZayas Yep. I'm not sure either. I mostly just wanted to confirm you were running adb connect 127.0.0.1:58526 in your WSL Terminal.

@AdalZayas
Copy link

AdalZayas commented Feb 14, 2024

@corysimmons Right now im running with my local ip

@iongion
Copy link

iongion commented Mar 4, 2024

Added these in my shell rc file

export WSL_HOST_IP="$(tail -1 /etc/resolv.conf | cut -d' ' -f2)"
export ADB_SERVER_SOCKET=tcp:$WSL_HOST_IP: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}')

I source it and then after adb deviecs I get

 adb devices                                    
03-04 11:55:52.779 81522 81522 D adb     : adb_trace.cpp:187 Android Debug Bridge version 1.0.41
03-04 11:55:52.779 81522 81522 D adb     : adb_trace.cpp:187 Version 35.0.0-11411520
03-04 11:55:52.779 81522 81522 D adb     : adb_trace.cpp:187 Installed as /home/user/SDKs/Android/platform-tools/adb
03-04 11:55:52.779 81522 81522 D adb     : adb_trace.cpp:187 Running on Linux 5.15.133.1-microsoft-standard-WSL2 (x86_64)
03-04 11:55:52.779 81522 81522 D adb     : adb_trace.cpp:187 
03-04 11:55:52.779 81522 81522 D adb     : commandline.cpp:1646 Using server socket: tcp:172.27.192.1:5037
03-04 11:55:52.779 81522 81522 D adb     : adb_client.cpp:160 _adb_connect: host:version
03-04 11:55:52.780 81522 81522 D adb     : adb_client.cpp:194 _adb_connect: return fd 3
List of devices attached
03-04 11:55:52.781 81522 81522 D adb     : adb_client.cpp:400 adb_query: host:devices
03-04 11:55:52.781 81522 81522 D adb     : adb_client.cpp:358 adb_connect: service: host:devices
03-04 11:55:52.781 81522 81522 D adb     : adb_client.cpp:160 _adb_connect: host:devices
03-04 11:55:52.782 81522 81522 D adb     : adb_client.cpp:194 _adb_connect: return fd 3
03-04 11:55:52.782 81522 81522 D adb     : adb_client.cpp:376 adb_connect: return fd 3
emulator-5554   device

I then proceed launching forwarding

  • Disabled windows firewall completely
  • In Windows powershell - adb kill-server && adb -a -P 5037 nodaemon server start
  • In WSL Ubuntu For port 3037 - socat -d -d TCP-LISTEN:5037,reuseaddr,fork TCP:$(cat /etc/resolv.conf | tail -n1 | cut -d " " -f 2):5037
  • In WSL Ubuntu For port 5554 - socat -d -d TCP-LISTEN:5037,reuseaddr,fork TCP:$(cat /etc/resolv.conf | tail -n1 | cut -d " " -f 2):5554

I try yarn android then it crashes

CommandError: Failed to get properties for device (03-04): Command failed: /home/user/SDKs/Android/platform-tools/adb -s 03-04 shell getprop ro.product.cpu.abilist
03-04 12:01:51.982 85678 85678 D adb     : adb_trace.cpp:187 Android Debug Bridge version 1.0.41
03-04 12:01:51.982 85678 85678 D adb     : adb_trace.cpp:187 Version 35.0.0-11411520
03-04 12:01:51.982 85678 85678 D adb     : adb_trace.cpp:187 Installed as /home/user/SDKs/Android/platform-tools/adb
03-04 12:01:51.982 85678 85678 D adb     : adb_trace.cpp:187 Running on Linux 5.15.133.1-microsoft-standard-WSL2 (x86_64)
03-04 12:01:51.982 85678 85678 D adb     : adb_trace.cpp:187 
03-04 12:01:51.982 85678 85678 D adb     : commandline.cpp:1646 Using server socket: tcp:172.27.192.1:5037
03-04 12:01:51.982 85678 85678 D adb     : adb_client.cpp:400 adb_query: host-serial:03-04:features
03-04 12:01:51.982 85678 85678 D adb     : adb_client.cpp:358 adb_connect: service: host-serial:03-04:features
03-04 12:01:51.982 85678 85678 D adb     : adb_client.cpp:160 _adb_connect: host:version
03-04 12:01:51.982 85678 85678 D adb     : adb_client.cpp:194 _adb_connect: return fd 3
03-04 12:01:51.982 85678 85678 D adb     : adb_client.cpp:160 _adb_connect: host-serial:03-04:features
03-04 12:01:51.983 85678 85678 D adb     : adb_client.cpp:372 _adb_connect error: device '03-04' not found
03-04 12:01:51.983 85678 85678 D adb     : adb_client.cpp:376 adb_connect: return fd -1
adb: device '03-04' not found

Any clue ? It looks like parsing/extraction error - but who is responsible for this

  1. On native windows adb devices I get
adb devices
List of devices attached
emulator-5554   device
  1. On WSL linux adb devices I get
adb devices
03-04 12:29:44.557 16415 16415 D adb     : adb_trace.cpp:187 Android Debug Bridge version 1.0.41
03-04 12:29:44.557 16415 16415 D adb     : adb_trace.cpp:187 Version 35.0.0-11411520
03-04 12:29:44.557 16415 16415 D adb     : adb_trace.cpp:187 Installed as /home/user/SDKs/Android/platform-tools/adb
03-04 12:29:44.557 16415 16415 D adb     : adb_trace.cpp:187 Running on Linux 5.15.133.1-microsoft-standard-WSL2 (x86_64)
03-04 12:29:44.557 16415 16415 D adb     : adb_trace.cpp:187
03-04 12:29:44.557 16415 16415 D adb     : commandline.cpp:1646 Using server socket: tcp:172.27.192.1:5037
03-04 12:29:44.557 16415 16415 D adb     : adb_client.cpp:160 _adb_connect: host:version
03-04 12:29:44.558 16415 16415 D adb     : adb_client.cpp:194 _adb_connect: return fd 3
List of devices attached
03-04 12:29:44.558 16415 16415 D adb     : adb_client.cpp:400 adb_query: host:devices
03-04 12:29:44.558 16415 16415 D adb     : adb_client.cpp:358 adb_connect: service: host:devices
03-04 12:29:44.558 16415 16415 D adb     : adb_client.cpp:160 _adb_connect: host:devices
03-04 12:29:44.558 16415 16415 D adb     : adb_client.cpp:194 _adb_connect: return fd 3
03-04 12:29:44.558 16415 16415 D adb     : adb_client.cpp:376 adb_connect: return fd 3
emulator-5554   device

So there are extra lines coming from a DEBUG flag or something - found it, it is @expo/cli that gets confused

    const splitItems = output.trim().replace(/\n$/, "").split(_os.default.EOL);
    // First line is `"List of devices attached"`, remove it
    // @ts-ignore: todo
    const attachedDevices = splitItems.slice(1, splitItems.length).map((line)=>{
        // unauthorized: ['FA8251A00719', 'unauthorized', 'usb:338690048X', 'transport_id:5']
        // authorized: ['FA8251A00719', 'device', 'usb:336592896X', 'product:walleye', 'model:Pixel_2', 'device:walleye', 'transport_id:4']
        // emulator: ['emulator-5554', 'offline', 'transport_id:1']
        const props = line.split(" ").filter(Boolean);
        const isAuthorized = props[1] !== "unauthorized";
        const type = line.includes("emulator") ? "emulator" : "device";
        return {
            props,
            type,
            isAuthorized
        };
    }).filter(({ props: [pid]  })=>!!pid
    );
```

@audriusl
Copy link

audriusl commented Apr 2, 2024

@vagnerlandio thanks for tips. I think I almost there but Im getting error in the WSA when starting Expo in development build: "Unable to load script.Make sure you are running Metro." and then when i try to reload it loses connection to development server.
Does anybody here make it work with Expo ? Expo Go works on WSA.

@josersleal
Copy link

wsa is dead

@RenaudAubert
Copy link

@vagnerlandio Thank you so much !
This guide used to work for me but after upgrading to react-native 0.73 it stopped working.

⚠️ If you're planning on using react-native > 0.71 and can connect both your PC and smartphone to the same network I highly recommend doing what's described in this comment.

@Se7enSe7enSe7en
Copy link

Good news, using the new mirrored mode networking feature of WSL2, the setup part for connecting the device or emulator to the project server is now simpler.

  1. enable mirrored mode networking through the .wslconfig file (usually located in C:\Users\<user_name>)
[wsl2]
networkingMode=mirrored
  1. add this in the rc file (eg. .bashrc), so that when we run the project in wsl it uses the adb in windows
### Make alias for adb in Windows so that it can be called within WSL
alias adb="/mnt/c/Users/<user_name>/AppData/Local/Android/Sdk/platform-tools/adb.exe"

thats pretty much it.

Also make sure the firewall isn't the way by adding inbound rules with the ports for adb (5037) and the project server (usually 8081)

Before I had to add export WSL_HOST_IP="$(tail -1 /etc/resolv.conf | cut -d' ' -f2)", export ADB_SERVER_SOCKET=tcp:$WSL_HOST_IP:5037 and export REACT_NATIVE_PACKAGER_HOSTNAME=$(ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') in the rc file. And to connect my physical device and the project server I had to run adb kill-server and adb -a nodaemon server start in windows first, every time I want to start the project.

Now with this we can just start the project directly and it should now connect to the physical device.

Big thanks for the people who contributed to this guide, hope this helps someone.

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