How can I use android virtual device (or emulator) running on my windows host through Android studio's device manager to run my React Native RN expo app in dev container?
I'm developing my RN expo app inside a dev container (devcontainer extension on vscode) in order to don't have to install any dependency on my host and have things nicely separated. Everithing works, I can run the app with command npx expo start and access it with expo go app on my real android phone with the QR code.
Now I would like to test in a emulator (to test multiple phones model for examples). So I need to type 'a' or npx start expo --android. But how this can use my android virtaul device (aka emulator) running on my windows host?
For now : My .devcontainer.json file :
{
"name": "Node.js & TypeScript",
"image": "mcr.microsoft/devcontainers/typescript-node:1-22-bookworm",
"forwardPorts": [8081],
"initializeCommand": ["C:\\Program Files\\Git\\bin\\bash.exe", "-c", "bash .devcontainer/initializeCommand.sh"],
"postCreateCommand": "bash .devcontainer/postCreateCommand.sh",
"runArgs": ["-p=8081:8081", "--env-file", ".devcontainer/.env"]
}
my .env file
REACT_NATIVE_PACKAGER_HOSTNAME=192.168.1.4
my initializeCommand.sh:
#!/bin/bash
echo "Gathering your IP for the dev container..."
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
# Windows (Git Bash or WSL)
echo "Windows detected..."
ip=$(ipconfig | grep -oE 'Adresse IPv4[. ]+: ([0-9.]+)' | awk '{print $NF}' | head -n 1)
else
# Linux/Mac
echo "Linux/Mac detected..."
iname=$(ip -o link show | sed -rn '/^[0-9]+: en/{s/.: ([^:]*):.*/\1/p}')
ip=$(ifconfig $iname | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | sed 's/inet //g')
fi
echo "REACT_NATIVE_PACKAGER_HOSTNAME=$ip" > .devcontainer/.env
My postCreateCommand.sh :
echo -e "\nStarting post creat command script..."
echo "Dev machine:"
uname -a
echo -e "\nInstalling expo boiler plate..."
npm install --save-dev -y [email protected]
echo -e "\nInstalling watchman...\n"
sudo apt update
sudo apt install watchman
watchman version
echo -e "\n*******************************"
echo -e "\nDev container ready!".
echo -e "\n*******************************\n"
The avd is running. On my host git bash terminal : $ adb devices List of devices attached emulator-5554 device
$ netstat -ano | findstr 5555 TCP 127.0.0.1:5555 0.0.0.0:0 LISTENING 23332 TCP 127.0.0.1:5555 127.0.0.1:61694 ESTABLISHED 23332 TCP 127.0.0.1:5555 127.0.0.1:61929 ESTABLISHED 23332 TCP 127.0.0.1:61694 127.0.0.1:5555 ESTABLISHED 3000 TCP 127.0.0.1:61929 127.0.0.1:5555 ESTABLISHED 15596 TCP [::1]:5555 [::]:0 LISTENING 23332
on the container : node ➜ /workspaces/myapp/my-app (master) $ npx expo start --android Starting project at /workspaces/myapp/my-app Starting Metro Bundler The following packages should be updated for best compatibility with the installed expo version: [email protected] - expected version: ~4.0.19 Your project may not work correctly until you install the expected versions of the packages. Failed to resolve the Android SDK path. Default install location not found: /home/node/Android/sdk. Use ANDROID_HOME to set the Android SDK location. Failed to resolve the Android SDK path. Default install location not found: /home/node/Android/sdk. Use ANDROID_HOME to set the Android SDK location. Failed to resolve the Android SDK path. Default install location not found: /home/node/Android/sdk. Use ANDROID_HOME to set the Android SDK location. Failed to resolve the Android SDK path. Default install location not found: /home/node/Android/sdk. Use ANDROID_HOME to set the Android SDK location. Error: could not connect to TCP port 5554: Connection refused Error: adb -s emulator-5554 emu avd name exited with non-zero code: 1 at ChildProcesspletionListener (/workspaces/myapp/my-app/node_modules/@expo/spawn-async/src/spawnAsync.ts:67:13) at Object.onceWrapper (node:events:639:26) at ChildProcess.emit (node:events:524:28) at maybeClose (node:internal/child_process:1101:16) at Socket. (node:internal/child_process:456:11) at Socket.emit (node:events:524:28) at Pipe. (node:net:350:12) ... at spawnAsync (/workspaces/myapp/my-app/node_modules/@expo/spawn-async/src/spawnAsync.ts:28:21) at ADBServer.runAsync (/workspaces/myapp/my-app/node_modules/@expo/cli/src/start/platforms/android/ADBServer.ts:85:59) at processTicksAndRejections (node:internal/process/task_queues:105:5) at getAdbNameForDeviceIdAsync (/workspaces/myapp/my-app/node_modules/@expo/cli/src/start/platforms/android/adb.ts:329:19) at /workspaces/myapp/my-app/node_modules/@expo/cli/src/start/platforms/android/adb.ts:312:14 at async Promise.all (index 0) at startAdbReverseAsync (/workspaces/myapp/my-app/node_modules/@expo/cli/src/start/platforms/android/adbReverse.ts:25:19) at AndroidPlatformManager.openAsync (/workspaces/myapp/my-app/node_modules/@expo/cli/src/start/platforms/android/AndroidPlatformManager.ts:64:5) at async Promise.allSettled (index 0) at openPlatformsAsync (/workspaces/myapp/my-app/node_modules/@expo/cli/src/start/server/openPlatforms.ts:10:19)
Tried to add in my initializeCommand.sh :
adb -a tcpip 5555
adb connect 127.0.0.1:5555
and in postCreateCommand.sh :
adb connect $REACT_NATIVE_PACKAGER_HOSTNAME
But I get : in initializeCommand (on my host) : restarting in TCP mode port: 5555 connected to 127.0.0.1:5555
in postCreateCommand (in container) : cannot connect to 192.168.1.4:5555: Aucune connexion n’a pu être établie car l’ordinateur cible l’a expressément refusée. (10061)