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(); + }); });