Skip to content

Instantly share code, notes, and snippets.

@0tii
Created March 1, 2024 21:28
Show Gist options
  • Save 0tii/b5e5852b609ccf02414fd8075713caa8 to your computer and use it in GitHub Desktop.
Save 0tii/b5e5852b609ccf02414fd8075713caa8 to your computer and use it in GitHub Desktop.
Start an Android Virtual Device on Windows from a WSL shell
/* eslint-disable @typescript-eslint/no-var-requires */
const exec = require('child_process').exec;
const spawn = require('child_process').spawn;
const readline = require('readline');
// utility to add ansii escape codes to strings (external)
const { green, yellow, red } = require('./util/console-color');
// utility to shallow-validate the android sdk path (external)
const { validateAndroidHomeWin } = require('./util/validate-android-home');
/*
ANDROID_HOME_WIN points to the mounted Windows Android SDK path
e.g. /mnt/c/Users/<user>/AppData/Local/Android/Sdk
*/
const RUN_CMD = `${process.env.ANDROID_HOME_WIN}/emulator/emulator`;
const LIST_CMD = `${process.env.ANDROID_HOME_WIN}/emulator/emulator -avd -list-avds`;
if (validateAndroidHomeWin(process.env.ANDROID_HOME_WIN, false))
(async () => {
await runEmulator();
})();
function getDevices() {
return new Promise((resolve, reject) => {
exec(LIST_CMD, (error, stdout) => {
if (error) {
if (error.message.includes('emulator/emulator:')) {
console.error(
'Error retrieving device list, unpatched Sdk directory. Please run wsl-setup first.' // <-- .exe files have not been copied to their non-exe counterparts
);
} else {
console.error(`Error retrieving list of devices: ${error.message}`);
}
reject(error);
return;
}
const result = stdout;
const devices = result
.split('\n')
.map((name) => name.trim())
.filter((name) => name);
resolve(devices);
});
});
}
async function runEmulator() {
const emulators = await getDevices();
if (emulators.length === 0) {
console.log('No devices available.');
return;
}
console.log('Select an emulator:\n');
emulators.forEach((emulator, index) => {
console.log(` [${index + 1}] ${emulator}`);
});
const selectedEmulatorIndex = await getUserInput('\nEmulator: ');
if (isValidIndex(selectedEmulatorIndex, emulators.length)) {
const selectedEmulator = emulators[selectedEmulatorIndex - 1];
console.log(green(`\nStarting ${selectedEmulator}...`));
try {
const emulatorProcess = spawn(RUN_CMD, ['-avd', selectedEmulator]);
emulatorProcess.on('close', (code) => {
if (code !== 0)
console.log(red(`${selectedEmulator} exited with error.`));
else console.log(yellow(`${selectedEmulator} exited gracefully.`));
});
emulatorProcess.stderr.on('error', () => {
console.log(
red(
`${selectedEmulator} encountered an error and had to be shut down.`
)
);
});
} catch (err) {
console.error('Error running emulator.');
}
} else {
console.log('Invalid selection.');
}
}
function getUserInput(prompt) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve) => {
rl.question(prompt, (answer) => {
rl.close();
resolve(answer.trim());
});
});
}
function isValidIndex(index, arrayLength) {
return !isNaN(index) && index >= 1 && index <= arrayLength;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment