diff --git a/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleBuild.gradle b/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleBuild.gradle
new file mode 100644
index 000000000..0a74052c4
--- /dev/null
+++ b/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleBuild.gradle
@@ -0,0 +1,150 @@
+apply plugin: "com.android.application"
+
+import com.android.build.OutputFile
+
+/**
+ * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
+ * and bundleReleaseJsAndAssets).
+ * These basically call `react-native bundle` with the correct arguments during the Android build
+ * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
+ * bundle directly from the development server. Below you can see all the possible configurations
+ * and their defaults. If you decide to add a configuration block, make sure to add it before the
+ * `apply from: "../../node_modules/react-native/react.gradle"` line.
+ *
+ * project.ext.react = [
+ * // the name of the generated asset file containing your JS bundle
+ * bundleAssetName: "index.android.bundle",
+ *
+ * // the entry file for bundle generation
+ * entryFile: "index.android.js",
+ *
+ * // whether to bundle JS and assets in debug mode
+ * bundleInDebug: false,
+ *
+ * // whether to bundle JS and assets in release mode
+ * bundleInRelease: true,
+ *
+ * // whether to bundle JS and assets in another build variant (if configured).
+ * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
+ * // The configuration property can be in the following formats
+ * // 'bundleIn${productFlavor}${buildType}'
+ * // 'bundleIn${buildType}'
+ * // bundleInFreeDebug: true,
+ * // bundleInPaidRelease: true,
+ * // bundleInBeta: true,
+ *
+ * // whether to disable dev mode in custom build variants (by default only disabled in release)
+ * // for example: to disable dev mode in the staging build type (if configured)
+ * devDisabledInStaging: true,
+ * // The configuration property can be in the following formats
+ * // 'devDisabledIn${productFlavor}${buildType}'
+ * // 'devDisabledIn${buildType}'
+ *
+ * // the root of your project, i.e. where "package.json" lives
+ * root: "../../",
+ *
+ * // where to put the JS bundle asset in debug mode
+ * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
+ *
+ * // where to put the JS bundle asset in release mode
+ * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
+ *
+ * // where to put drawable resources / React Native assets, e.g. the ones you use via
+ * // require('./image.png')), in debug mode
+ * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
+ *
+ * // where to put drawable resources / React Native assets, e.g. the ones you use via
+ * // require('./image.png')), in release mode
+ * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
+ *
+ * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
+ * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
+ * // date; if you have any other folders that you want to ignore for performance reasons (gradle
+ * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
+ * // for example, you might want to remove it from here.
+ * inputExcludes: ["android/**", "ios/**"],
+ *
+ * // override which node gets called and with what additional arguments
+ * nodeExecutableAndArgs: ["node"],
+ *
+ * // supply additional arguments to the packager
+ * extraPackagerArgs: []
+ * ]
+ */
+
+project.ext.react = [
+ entryFile: "index.js"
+]
+
+apply from: "../../node_modules/react-native/react.gradle"
+
+android {
+ compileSdkVersion rootProject.ext.compileSdkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ applicationId "com.mycompany.app"
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
+
+ versionCode 1
+ versionName "1.0.0"
+ }
+ splits {
+ abi {
+ reset()
+ enable enableSeparateBuildPerCPUArchitecture
+ universalApk false
+ include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
+ }
+ }
+ buildTypes {
+ debug {
+ applicationIdSuffix ".debug"
+ versionNameSuffix "-build-" + getDate()
+ }
+
+ releaseStaging {
+ applicationIdSuffix ".staging"
+ versionNameSuffix "-staging"
+ matchingFallbacks = ['release']
+ }
+
+ release {
+ minifyEnabled enableProguardInReleaseBuilds
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
+ }
+ }
+
+ applicationVariants.all { variant ->
+ variant.outputs.each { output ->
+ def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3, "x86_64": 4]
+ def abi = output.getFilter(OutputFile.ABI)
+ if (abi != null) {
+ output.versionCodeOverride =
+ versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
+ }
+ }
+ }
+}
+
+dependencies {
+ implementation project(':react-native-config')
+ implementation project(':react-native-webview')
+ implementation project(':react-native-sound')
+ implementation project(':react-native-gesture-handler')
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+ implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
+ implementation "com.facebook.react:react-native:+" // From node_modules
+}
+
+// Run this once to be able to run the application with BUCK
+// puts all compile dependencies into folder libs for BUCK to use
+task copyDownloadableDepsToLibs(type: Copy) {
+ from configurations.compile
+ into 'libs'
+}
diff --git a/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleBuildWithFlavor.gradle b/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleBuildWithFlavor.gradle
new file mode 100644
index 000000000..6a5abcba3
--- /dev/null
+++ b/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleBuildWithFlavor.gradle
@@ -0,0 +1,166 @@
+apply plugin: "com.android.application"
+
+import com.android.build.OutputFile
+
+/**
+ * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
+ * and bundleReleaseJsAndAssets).
+ * These basically call `react-native bundle` with the correct arguments during the Android build
+ * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
+ * bundle directly from the development server. Below you can see all the possible configurations
+ * and their defaults. If you decide to add a configuration block, make sure to add it before the
+ * `apply from: "../../node_modules/react-native/react.gradle"` line.
+ *
+ * project.ext.react = [
+ * // the name of the generated asset file containing your JS bundle
+ * bundleAssetName: "index.android.bundle",
+ *
+ * // the entry file for bundle generation
+ * entryFile: "index.android.js",
+ *
+ * // whether to bundle JS and assets in debug mode
+ * bundleInDebug: false,
+ *
+ * // whether to bundle JS and assets in release mode
+ * bundleInRelease: true,
+ *
+ * // whether to bundle JS and assets in another build variant (if configured).
+ * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
+ * // The configuration property can be in the following formats
+ * // 'bundleIn${productFlavor}${buildType}'
+ * // 'bundleIn${buildType}'
+ * // bundleInFreeDebug: true,
+ * // bundleInPaidRelease: true,
+ * // bundleInBeta: true,
+ *
+ * // whether to disable dev mode in custom build variants (by default only disabled in release)
+ * // for example: to disable dev mode in the staging build type (if configured)
+ * devDisabledInStaging: true,
+ * // The configuration property can be in the following formats
+ * // 'devDisabledIn${productFlavor}${buildType}'
+ * // 'devDisabledIn${buildType}'
+ *
+ * // the root of your project, i.e. where "package.json" lives
+ * root: "../../",
+ *
+ * // where to put the JS bundle asset in debug mode
+ * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
+ *
+ * // where to put the JS bundle asset in release mode
+ * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
+ *
+ * // where to put drawable resources / React Native assets, e.g. the ones you use via
+ * // require('./image.png')), in debug mode
+ * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
+ *
+ * // where to put drawable resources / React Native assets, e.g. the ones you use via
+ * // require('./image.png')), in release mode
+ * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
+ *
+ * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
+ * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
+ * // date; if you have any other folders that you want to ignore for performance reasons (gradle
+ * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
+ * // for example, you might want to remove it from here.
+ * inputExcludes: ["android/**", "ios/**"],
+ *
+ * // override which node gets called and with what additional arguments
+ * nodeExecutableAndArgs: ["node"],
+ *
+ * // supply additional arguments to the packager
+ * extraPackagerArgs: []
+ * ]
+ */
+
+project.ext.react = [
+ entryFile: "index.js"
+]
+
+apply from: "../../node_modules/react-native/react.gradle"
+
+android {
+ compileSdkVersion rootProject.ext.compileSdkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ applicationId "com.mycompany.app"
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
+
+ versionCode 1
+ versionName "1.0.0"
+ }
+ splits {
+ abi {
+ reset()
+ enable enableSeparateBuildPerCPUArchitecture
+ universalApk false
+ include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
+ }
+ }
+ buildTypes {
+ debug {
+ applicationIdSuffix ".debug"
+ versionNameSuffix "-build-" + getDate()
+ }
+
+ releaseStaging {
+ applicationIdSuffix ".staging"
+ versionNameSuffix "-staging"
+ matchingFallbacks = ['release']
+ }
+
+ release {
+ minifyEnabled enableProguardInReleaseBuilds
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
+ }
+ }
+ // Specifies one flavor dimension.
+ flavorDimensions "version"
+ productFlavors {
+ demo {
+ // Assigns this product flavor to the "version" flavor dimension.
+ // This property is optional if you are using only one dimension.
+ dimension "version"
+ applicationIdSuffix ".demo"
+ versionNameSuffix "-demo"
+ }
+ full {
+ dimension "version"
+ applicationIdSuffix ".full"
+ versionNameSuffix "-full"
+ }
+ }
+
+ applicationVariants.all { variant ->
+ variant.outputs.each { output ->
+ def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3, "x86_64": 4]
+ def abi = output.getFilter(OutputFile.ABI)
+ if (abi != null) {
+ output.versionCodeOverride =
+ versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
+ }
+ }
+ }
+}
+
+dependencies {
+ implementation project(':react-native-config')
+ implementation project(':react-native-webview')
+ implementation project(':react-native-sound')
+ implementation project(':react-native-gesture-handler')
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+ implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
+ implementation "com.facebook.react:react-native:+" // From node_modules
+}
+
+// Run this once to be able to run the application with BUCK
+// puts all compile dependencies into folder libs for BUCK to use
+task copyDownloadableDepsToLibs(type: Copy) {
+ from configurations.compile
+ into 'libs'
+}
diff --git a/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleGeneratedDebugManifest.xml b/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleGeneratedDebugManifest.xml
new file mode 100644
index 000000000..1b3ff2e54
--- /dev/null
+++ b/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleGeneratedDebugManifest.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleGeneratedDemoDebugManifest.xml b/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleGeneratedDemoDebugManifest.xml
new file mode 100644
index 000000000..9de785d19
--- /dev/null
+++ b/packages/platform-android/src/commands/runAndroid/__fixtures__/sampleGeneratedDemoDebugManifest.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/platform-android/src/commands/runAndroid/__tests__/getLaunchPackageName.test.js b/packages/platform-android/src/commands/runAndroid/__tests__/getLaunchPackageName.test.js
new file mode 100644
index 000000000..20f0ff41a
--- /dev/null
+++ b/packages/platform-android/src/commands/runAndroid/__tests__/getLaunchPackageName.test.js
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow
+ */
+
+import getLaunchPackageName from '../getLaunchPackageName';
+import {createBuildGradleMocks} from './testHelpers';
+
+describe('run-android::getLaunchPackageName', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('returns a well formed package name for unflavored build type', () => {
+ createBuildGradleMocks(false);
+
+ const basePackageName = 'com.mycompany.app';
+
+ expect(getLaunchPackageName('debug')).toBe(`${basePackageName}.debug`);
+ });
+
+ it('returns a well formed package for flavored build type', () => {
+ createBuildGradleMocks(true);
+
+ const basePackageName = 'com.mycompany.app';
+
+ expect(getLaunchPackageName('demoDebug')).toBe(
+ `${basePackageName}.demo.debug`,
+ );
+ });
+
+ afterAll(() => {
+ jest.clearAllMocks();
+ });
+});
diff --git a/packages/platform-android/src/commands/runAndroid/__tests__/runOnAllDevices.test.js b/packages/platform-android/src/commands/runAndroid/__tests__/runOnAllDevices.test.js
index 840e5cb54..4c1f660da 100644
--- a/packages/platform-android/src/commands/runAndroid/__tests__/runOnAllDevices.test.js
+++ b/packages/platform-android/src/commands/runAndroid/__tests__/runOnAllDevices.test.js
@@ -7,6 +7,7 @@
*/
import runOnAllDevices from '../runOnAllDevices';
+import {createBuildGradleMocks} from './testHelpers';
jest.mock('child_process', () => ({
execFileSync: jest.fn(),
@@ -19,6 +20,8 @@ const {execFileSync} = require('child_process');
describe('--appFolder', () => {
beforeEach(() => {
jest.clearAllMocks();
+
+ createBuildGradleMocks(false);
});
it('uses installDebug as default if no arguments', () => {
diff --git a/packages/platform-android/src/commands/runAndroid/__tests__/testHelpers.js b/packages/platform-android/src/commands/runAndroid/__tests__/testHelpers.js
new file mode 100644
index 000000000..8a3c2596e
--- /dev/null
+++ b/packages/platform-android/src/commands/runAndroid/__tests__/testHelpers.js
@@ -0,0 +1,37 @@
+import fs from 'fs';
+
+jest.mock('fs');
+jest.mock('path');
+
+export function createBuildGradleMocks(useFlavor) {
+ const actualFs = jest.requireActual('fs');
+ const actualPath = jest.requireActual('path');
+
+ fs.readFileSync = jest.fn(filename => {
+ switch (filename) {
+ case actualPath.join('app', 'build.gradle'):
+ return actualFs.readFileSync(
+ actualPath.join(
+ __dirname,
+ '..',
+ '__fixtures__',
+ useFlavor ? 'sampleBuildWithFlavor.gradle' : 'sampleBuild.gradle',
+ ),
+ 'utf8',
+ );
+ // Use default case to catch generated debug manifest
+ default:
+ return actualFs.readFileSync(
+ actualPath.join(
+ __dirname,
+ '..',
+ '__fixtures__',
+ useFlavor
+ ? 'sampleGeneratedDemoDebugManifest.xml'
+ : 'sampleGeneratedDebugManifest.xml',
+ ),
+ 'utf8',
+ );
+ }
+ });
+}
diff --git a/packages/platform-android/src/commands/runAndroid/getLaunchPackageName.js b/packages/platform-android/src/commands/runAndroid/getLaunchPackageName.js
new file mode 100644
index 000000000..3e0092a28
--- /dev/null
+++ b/packages/platform-android/src/commands/runAndroid/getLaunchPackageName.js
@@ -0,0 +1,120 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @flow
+ */
+
+import fs from 'fs';
+import path from 'path';
+
+function findPreviousTerm(content, endPos) {
+ let pos = endPos;
+
+ while (content[pos] === ' ') {
+ --pos;
+ }
+ const regex = /\w/;
+ const word = [];
+ while (regex.exec(content[pos])) {
+ word.push(content[pos]);
+ --pos;
+ }
+ return word.reverse().join('');
+}
+
+function findBuildTypes(filePath) {
+ // Read the gradle file and get list of buildTypes defined for the project.
+ const content = fs.readFileSync(filePath, 'utf8');
+ const regex = /buildTypes+/gi;
+ const buildTypes = [];
+ const match = regex.exec(content);
+ if (!match) {
+ // Assume default types if buildTypes is not present
+ return ['debug', 'release'];
+ }
+ const buildTypeStartPos = regex.lastIndex;
+ let counter = 1;
+ let pos = buildTypeStartPos + 1;
+ while (counter > 0) {
+ if (content[pos] === '{') {
+ counter += 1;
+ if (counter === 2) {
+ const previousTerm = findPreviousTerm(content, pos - 1);
+ if (buildTypes.indexOf(previousTerm) === -1) {
+ buildTypes.push(previousTerm);
+ }
+ }
+ } else if (content[pos] === '}') {
+ --counter;
+ }
+ ++pos;
+ }
+ return buildTypes;
+}
+
+function splitVariant(gradleFilePath, variant) {
+ // Split the variant into buildType and flavor
+ const buildTypes = findBuildTypes(gradleFilePath);
+ const regexp = new RegExp(buildTypes.join('|'), 'gi');
+ const match = regexp.exec(variant);
+ let flavor = null;
+ let buildType = variant;
+ if (match) {
+ flavor = variant.substring(0, match.index);
+ buildType = variant.substring(match.index);
+ }
+ return {buildType, flavor};
+}
+
+function isSeparateBuildEnabled(gradleFilePath) {
+ // Check if separate is build enabled for different processors
+ const content = fs.readFileSync(gradleFilePath, 'utf8');
+ const match = content.match(/(\w+)\senableSeparateBuildPerCPUArchitecture/);
+ let separateBuild = '';
+ if (match != null) {
+ separateBuild = match[1];
+ }
+ return separateBuild.toLowerCase() === 'enable';
+}
+
+function getManifestFile(variant) {
+ // get the path to the correct manifest file to find the correct package name to be used while
+ // starting the app
+ const gradleFilePath = path.join('app', 'build.gradle');
+
+ // We first need to identify build type and flavor from the specified variant
+ const {buildType, flavor} = splitVariant(gradleFilePath, variant);
+
+ // Using the buildtype and flavor we create the path to the correct AndroidManifest.xml
+ const paths = ['app', 'build', 'intermediates', 'merged_manifests'];
+ if (flavor) {
+ paths.push(flavor);
+ }
+
+ if (isSeparateBuildEnabled(gradleFilePath)) {
+ paths.push('x86');
+ }
+
+ paths.push(buildType);
+ paths.push('AndroidManifest.xml');
+ return path.join(...paths);
+}
+
+export default function getLaunchPackageName(variant: string) {
+ // Get the complete launch path, as specified by the gradle build script
+ const manifestFile = getManifestFile(variant || 'debug');
+ const content = fs.readFileSync(manifestFile, 'utf8');
+
+ // Get the package name to launch, specified by the generated manifest file
+ const matched = content.match(/package="(.+?)"/);
+ let packageName = '';
+
+ if (matched != null) {
+ packageName = matched[1];
+ }
+
+ return packageName;
+}
diff --git a/packages/platform-android/src/commands/runAndroid/index.js b/packages/platform-android/src/commands/runAndroid/index.js
index 09c7f71c5..023d2cf1e 100644
--- a/packages/platform-android/src/commands/runAndroid/index.js
+++ b/packages/platform-android/src/commands/runAndroid/index.js
@@ -18,6 +18,7 @@ import runOnAllDevices from './runOnAllDevices';
import tryRunAdbReverse from './tryRunAdbReverse';
import tryLaunchAppOnDevice from './tryLaunchAppOnDevice';
import getAdbPath from './getAdbPath';
+import getLaunchPackageName from './getLaunchPackageName';
import {
isPackagerRunning,
logger,
@@ -59,17 +60,6 @@ function runAndroid(argv: Array, ctx: ConfigT, args: Object) {
});
}
-function getPackageNameWithSuffix(appId, appIdSuffix, packageName) {
- if (appId) {
- return appId;
- }
- if (appIdSuffix) {
- return `${packageName}.${appIdSuffix}`;
- }
-
- return packageName;
-}
-
// Builds the app and runs it on a connected emulator / device.
function buildAndRun(args) {
process.chdir(path.join(args.root, 'android'));
@@ -82,53 +72,23 @@ function buildAndRun(args) {
// $FlowFixMe
.match(/package="(.+?)"/)[1];
- const packageNameWithSuffix = getPackageNameWithSuffix(
- args.appId,
- args.appIdSuffix,
- packageName,
- );
-
const adbPath = getAdbPath();
if (args.deviceId) {
if (typeof args.deviceId === 'string') {
- return runOnSpecificDevice(
- args,
- cmd,
- packageNameWithSuffix,
- packageName,
- adbPath,
- );
+ return runOnSpecificDevice(args, cmd, packageName, adbPath);
}
logger.error('Argument missing for parameter --deviceId');
} else {
- return runOnAllDevices(
- args,
- cmd,
- packageNameWithSuffix,
- packageName,
- adbPath,
- );
+ return runOnAllDevices(args, cmd, packageName, adbPath);
}
}
-function runOnSpecificDevice(
- args,
- gradlew,
- packageNameWithSuffix,
- packageName,
- adbPath,
-) {
+function runOnSpecificDevice(args, gradlew, packageName, adbPath) {
const devices = adb.getDevices(adbPath);
if (devices && devices.length > 0) {
if (devices.indexOf(args.deviceId) !== -1) {
buildApk(gradlew);
- installAndLaunchOnDevice(
- args,
- args.deviceId,
- packageNameWithSuffix,
- packageName,
- adbPath,
- );
+ installAndLaunchOnDevice(args, args.deviceId, packageName, adbPath);
} else {
logger.error(
`Could not find device with the id: "${
@@ -215,18 +175,12 @@ function getInstallApkName(
throw new Error('Not found the correct install APK file!');
}
-function installAndLaunchOnDevice(
- args,
- selectedDevice,
- packageNameWithSuffix,
- packageName,
- adbPath,
-) {
+function installAndLaunchOnDevice(args, selectedDevice, packageName, adbPath) {
tryRunAdbReverse(args.port, selectedDevice);
tryInstallAppOnDevice(args, adbPath, selectedDevice);
tryLaunchAppOnDevice(
selectedDevice,
- packageNameWithSuffix,
+ getLaunchPackageName(args.variant),
packageName,
adbPath,
args.mainActivity,
diff --git a/packages/platform-android/src/commands/runAndroid/runOnAllDevices.js b/packages/platform-android/src/commands/runAndroid/runOnAllDevices.js
index 3eb59ae44..8e60079f8 100644
--- a/packages/platform-android/src/commands/runAndroid/runOnAllDevices.js
+++ b/packages/platform-android/src/commands/runAndroid/runOnAllDevices.js
@@ -11,6 +11,7 @@ import {spawnSync, execFileSync} from 'child_process';
import {logger} from '@react-native-community/cli-tools';
import adb from './adb';
import tryRunAdbReverse from './tryRunAdbReverse';
+import getLaunchPackageName from './getLaunchPackageName';
import tryLaunchAppOnDevice from './tryLaunchAppOnDevice';
function getCommand(appFolder, command) {
@@ -20,7 +21,6 @@ function getCommand(appFolder, command) {
function runOnAllDevices(
args: Object,
cmd: string,
- packageNameWithSuffix: string,
packageName: string,
adbPath: string,
) {
@@ -69,13 +69,14 @@ function runOnAllDevices(
// `logger.info(e.stderr)`
return Promise.reject(e);
}
+
const devices = adb.getDevices(adbPath);
if (devices && devices.length > 0) {
devices.forEach(device => {
tryRunAdbReverse(args.port, device);
tryLaunchAppOnDevice(
device,
- packageNameWithSuffix,
+ getLaunchPackageName(args.variant),
packageName,
adbPath,
args.mainActivity,
@@ -90,7 +91,7 @@ function runOnAllDevices(
'am',
'start',
'-n',
- `${packageNameWithSuffix}/${packageName}.MainActivity`,
+ `${getLaunchPackageName(args.variant)}/${packageName}.MainActivity`,
];
logger.info(
`Starting the app (${adbPath} ${fallbackAdbArgs.join(' ')}...`,
diff --git a/packages/platform-android/src/commands/runAndroid/tryLaunchAppOnDevice.js b/packages/platform-android/src/commands/runAndroid/tryLaunchAppOnDevice.js
index a2b88d021..a756ec098 100644
--- a/packages/platform-android/src/commands/runAndroid/tryLaunchAppOnDevice.js
+++ b/packages/platform-android/src/commands/runAndroid/tryLaunchAppOnDevice.js
@@ -12,7 +12,7 @@ import {logger} from '@react-native-community/cli-tools';
function tryLaunchAppOnDevice(
device: string,
- packageNameWithSuffix: string,
+ launchPackageName: string,
packageName: string,
adbPath: string,
mainActivity: string,
@@ -25,7 +25,7 @@ function tryLaunchAppOnDevice(
'am',
'start',
'-n',
- `${packageNameWithSuffix}/${packageName}.${mainActivity}`,
+ `${launchPackageName}/${packageName}.${mainActivity}`,
];
logger.info(
`Starting the app on ${device} (${adbPath} ${adbArgs.join(' ')})...`,
diff --git a/packages/platform-android/src/config/__tests__/getProjectConfig-test.js b/packages/platform-android/src/config/__tests__/getProjectConfig-test.js
index 5dae615c6..2de31df9d 100644
--- a/packages/platform-android/src/config/__tests__/getProjectConfig-test.js
+++ b/packages/platform-android/src/config/__tests__/getProjectConfig-test.js
@@ -86,4 +86,8 @@ describe('android::getProjectConfig', () => {
expect(getProjectConfig(folder, userConfig)).toBeNull();
});
+
+ afterAll(() => {
+ jest.clearAllMocks();
+ });
});