Hi there!
If you've been working with React Native, you've likely encountered emulator issues. You run the React Native command, but the emulator isn’t detected. Even after setting all the necessary environment variables in your .zshrc
, .bash_profile
, or similar files, it still doesn’t work.
Here are some common problems and fixes:
-
Emulator Not Found: This can happen if the Android SDK path isn't correctly set. Double-check that the
ANDROID_HOME
andPATH
environment variables point to the correct directories. You can add these lines to your.zshrc
or.bash_profile
:
export ANDROID_HOME=$HOME/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/emulator export PATH=$PATH:$ANDROID_HOME/tools export PATH=$PATH:$ANDROID_HOME/tools/bin export PATH=$PATH:$ANDROID_HOME/platform-tools
After making these changes, restart your terminal or run
source ~/.zshrc
(orsource ~/.bash_profile
). -
Watchman Errors: Sometimes, Watchman—Facebook’s file watching service—can cause issues with stale file caches. To fix this, run:
watchman watch-del-all
Then, restart your React Native server.
-
adb reverse
to Connect tolocalhost
: If your app cannot connect tolocalhost
from within the Android emulator, you might need to run:
adb reverse tcp:8081 tcp:8081
This command routes traffic from the emulator to your local machine. Make sure
adb
is accessible from your terminal. -
Clear Cache and Rebuild: If you still face issues, try clearing the cache and rebuilding the project:
npm start -- --reset-cache cd android && ./gradlew clean cd ios && xcodebuild clean
Then run your React Native app again.
-
Using
react-native run-android
orrun-ios
Directly: If the emulator is not starting correctly from your IDE or terminal, try running the app directly with:
npx react-native run-android npx react-native run-ios
Debugging these issues can be frustrating, but these steps have helped me solve many common problems.
I created an easy-to-use script too
const {spawn, exec} = require('child_process');
const path = require('path');
// Define paths
const projectPath = path.resolve();
// Define commands
const watchDelCommand = `watchman watch-del '${projectPath}'`;
const watchProjectCommand = `watchman watch-project '${projectPath}'`;
// Function to execute commands
const clearWatchman = () => {
// Execute watch-del command
exec(watchDelCommand, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing watch-del command: ${error.message}`);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
return;
}
console.log(`watch-del command executed successfully: ${stdout}`);
// Execute watch-project command
exec(watchProjectCommand, (error, stdout, stderr) => {
if (error) {
console.error(
`Error executing watch-project command: ${error.message}`,
);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
return;
}
console.log(`watch-project command executed successfully: ${stdout}`);
});
});
};
async function reverseAdb() {
console.log('Running... adb reverse tcp:8080 tcp:8080');
// After the emulator has started adb reverse tcp:8080 tcp:8080
const adbReverse = spawn('adb', ['reverse', 'tcp:8080', 'tcp:8080']);
await new Promise((resolve, reject) => {
let output = '';
adbReverse.stdout.on('data', data => {
output += data.toString();
});
adbReverse.on('close', () => {
resolve();
});
adbReverse.stderr.on('error', reject);
}).catch(error => console.error('Error reversing ADB port to 8080:', error));
}
async function runEmulator() {
try {
clearWatchman();
// Check for running emulator
const adbDevices = spawn('adb', ['devices']);
const devices = await new Promise((resolve, reject) => {
let output = '';
adbDevices.stdout.on('data', data => {
output += data.toString();
});
adbDevices.on('close', () => {
resolve(output.includes('emulator'));
});
adbDevices.stderr.on('error', reject);
});
if (devices) {
console.log('Emulator is already running');
reverseAdb();
return;
}
// Get list of available emulators
const emulatorList = spawn('emulator', ['-list-avds']);
const emulatorName = await new Promise((resolve, reject) => {
let output = '';
emulatorList.stdout.on('data', data => {
output += data.toString();
});
emulatorList.on('close', () => {
const lines = output.split('\n').filter(Boolean); // Filter out empty lines
if (lines.length === 0) {
reject(new Error('No AVDs found'));
} else {
resolve(lines[lines.length - 1]); // Get the last non-empty line
}
});
emulatorList.stderr.on('error', reject);
});
// Start the emulator in detached mode
const emulatorProcess = spawn('emulator', ['-avd', emulatorName], {
detached: true,
stdio: 'ignore',
});
emulatorProcess.unref(); // Allow the parent process to exit independently of the child
reverseAdb();
console.log(`Starting emulator: ${emulatorName}`);
} catch (error) {
console.error('Error running emulator:', error);
}
}
runEmulator();
// package.json
"scripts": {
...
"dev:android": "yarn android:emulator && npx react-native@latest start",
"android:emulator": "node runEmulator.js",
...
},
By using the script above, you can run both the emulator and React Native simultaneously.
Thanks for reading!
Top comments (0)