Skip to content

Commit

Permalink
Fix run-android to execute app on all connected devices
Browse files Browse the repository at this point in the history
Summary:**EDIT: **

This has been updated to simply fix the `run-android` command so that it runs on all connected devices instead of throwing an error.

**Original PR description:**

This adds a new command to the react-native CLI. When executed this command will install and successfully execute your app on all connected Android devices:

`react-native run-android-all`

Closes #5901

**Note:** I wasn't sure how to approach this API since it seems a bit like a flag, but I didn't see any other flags implemented in the cli so it seems like the current trend is to keep all commands to a single phrase. I am open to changing this if need be.
Closes #5902

Differential Revision: D2976580

Pulled By: mkonicek

fb-gh-sync-id: e7f734478f719cf59e0192b5f4be3f6408c31964
shipit-source-id: e7f734478f719cf59e0192b5f4be3f6408c31964
  • Loading branch information
jimthedev authored and Facebook Github Bot 0 committed Mar 8, 2016
1 parent b5ae8a8 commit 10ad47a
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 15 deletions.
52 changes: 52 additions & 0 deletions local-cli/runAndroid/adb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/

const child_process = require('child_process');

/**
* Parses the output of the 'adb devices' command
*/
function parseDevicesResult(result: string): Array<string> {
if (!result) {
return [];
}

const devices = [];
const lines = result.trim().split(/\r?\n/);

for (let i=0; i < lines.length; i++) {
let words = lines[i].split(/[ ,\t]+/).filter((w) => w !== '');

if (words[1] === 'device') {
devices.push(words[0]);
}
}
return devices;
}

/**
* Executes the commands needed to get a list of devices from ADB
*/
function getDevices(): Array<string> {
try {
const devicesResult = child_process.execSync('adb devices');
return parseDevicesResult(devicesResult.toString());
} catch (e) {
return [];
}


}

module.exports = {
parseDevicesResult: parseDevicesResult,
getDevices: getDevices
};
45 changes: 30 additions & 15 deletions local-cli/runAndroid/runAndroid.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const path = require('path');
const parseCommandLine = require('../util/parseCommandLine');
const isPackagerRunning = require('../util/isPackagerRunning');
const Promise = require('promise');
const adb = require('./adb');

/**
* Starts the app on a connected Android emulator or device.
Expand Down Expand Up @@ -49,12 +50,12 @@ function _runAndroid(argv, config, resolve, reject) {

resolve(isPackagerRunning().then(result => {
if (result === 'running') {
console.log(chalk.bold('JS server already running.'));
console.log(chalk.bold(`JS server already running.`));
} else if (result === 'unrecognized') {
console.warn(chalk.yellow('JS server not recognized, continuing with build...'));
console.warn(chalk.yellow(`JS server not recognized, continuing with build...`));
} else {
// result == 'not_running'
console.log(chalk.bold('Starting JS server...'));
console.log(chalk.bold(`Starting JS server...`));
startServerInNewWindow();
}
buildAndRun(args, reject);
Expand Down Expand Up @@ -88,8 +89,7 @@ function buildAndRun(args, reject) {
}

console.log(chalk.bold(
'Building and installing the app on the device (cd android && ' + cmd +
' ' + gradleArgs.join(' ') + ')...'
`Building and installing the app on the device (cd android && ${cmd} ${gradleArgs.join(' ')}...`
));

child_process.execFileSync(cmd, gradleArgs, {
Expand Down Expand Up @@ -119,18 +119,34 @@ function buildAndRun(args, reject) {
? process.env.ANDROID_HOME + '/platform-tools/adb'
: 'adb';

const adbArgs = [
'shell', 'am', 'start', '-n', packageName + '/.MainActivity'
];
const devices = adb.getDevices();

if (devices && devices.length > 0) {
devices.forEach((device) => {

console.log(chalk.bold(
'Starting the app (' + adbPath + ' ' + adbArgs.join(' ') + ')...'
));
const adbArgs = ['-s', device, 'shell', 'am', 'start', '-n', packageName + '/.MainActivity'];

console.log(chalk.bold(
`Starting the app on ${device} (${adbPath} ${adbArgs.join(' ')})...`
));

child_process.spawnSync(adbPath, adbArgs, {stdio: 'inherit'});
});
} else {
// If we cannot execute based on adb devices output, fall back to
// shell am start
const fallbackAdbArgs = [
'shell', 'am', 'start', '-n', packageName + '/.MainActivity'
];
console.log(chalk.bold(
`Starting the app (${adbPath} ${fallbackAdbArgs.join(' ')}...`
));
child_process.spawnSync(adbPath, fallbackAdbArgs, {stdio: 'inherit'});
}

child_process.spawnSync(adbPath, adbArgs, {stdio: 'inherit'});
} catch (e) {
console.log(chalk.red(
'adb invocation failed. Do you have adb in your PATH?'
`adb invocation failed. Do you have adb in your PATH?`
));
// stderr is automatically piped from the gradle process, so the user
// should see the error already, there is no need to do
Expand Down Expand Up @@ -168,8 +184,7 @@ function startServerInNewWindow() {
'Windows on a daily basis.\n' +
'Would you be up for sending a pull request?');
} else {
console.log(chalk.red('Cannot start the packager. Unknown platform ' +
process.platform));
console.log(chalk.red(`Cannot start the packager. Unknown platform ${process.platform}`));
}
}

Expand Down

0 comments on commit 10ad47a

Please sign in to comment.