From d87a53b2f88683296a1b2124407077062dd95fbf Mon Sep 17 00:00:00 2001 From: kagawagao Date: Thu, 19 Dec 2019 15:32:40 +0800 Subject: [PATCH 1/3] feat: auto detect android adb args --- packages/platform-android/package.json | 4 + .../src/commands/runAndroid/getApp.ts | 83 +++++++++++++++++++ .../src/commands/runAndroid/index.ts | 29 +++++-- yarn.lock | 34 ++++++++ 4 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 packages/platform-android/src/commands/runAndroid/getApp.ts diff --git a/packages/platform-android/package.json b/packages/platform-android/package.json index 27b287b3b..f79d13d28 100644 --- a/packages/platform-android/package.json +++ b/packages/platform-android/package.json @@ -10,6 +10,9 @@ "@react-native-community/cli-tools": "^3.0.0", "chalk": "^2.4.2", "execa": "^1.0.0", + "fast-xml-parser": "^3.15.1", + "flat": "^5.0.0", + "gradle-to-js": "^2.0.0", "jetifier": "^1.6.2", "logkitty": "^0.6.0", "slash": "^3.0.0", @@ -22,6 +25,7 @@ "devDependencies": { "@react-native-community/cli-types": "^3.0.0", "@types/execa": "^0.9.0", + "@types/flat": "^0.0.28", "@types/fs-extra": "^8.0.0", "@types/glob": "^7.1.1", "@types/xmldoc": "^1.1.4" diff --git a/packages/platform-android/src/commands/runAndroid/getApp.ts b/packages/platform-android/src/commands/runAndroid/getApp.ts new file mode 100644 index 000000000..a4c577835 --- /dev/null +++ b/packages/platform-android/src/commands/runAndroid/getApp.ts @@ -0,0 +1,83 @@ +import xmlParser from 'fast-xml-parser'; +import fs from 'fs'; +// @ts-ignore +import g2js from 'gradle-to-js/lib/parser'; +import flatten from 'flat'; + +const MAIN_ACTION = 'android.intent.action.MAIN'; +const LAUNCHER = 'android.intent.category.LAUNCHER'; + +interface Activity { + [x: string]: any; +} + +interface Variants { + [k: string]: string; +} + +export interface App { + packageName: string; + mainActivity: string; + name: string; + variants: Variants; +} + +// runtime cache +let app: App = { + packageName: '', + mainActivity: '', + name: '', + variants: {}, +}; + +export async function getApp(appFolder: string): Promise { + if (app.packageName) { + return app; + } + const manifestPath = `${appFolder}/src/main/AndroidManifest.xml`; + const appGradlePath = `${appFolder}/build.gradle`; + const manifestContent = fs.readFileSync(manifestPath, {encoding: 'utf8'}); + if (xmlParser.validate(manifestContent)) { + const {manifest} = xmlParser.parse(manifestContent, { + attributeNamePrefix: '', + ignoreAttributes: false, + ignoreNameSpace: true, + }); + + const {package: packageName, application = {}} = manifest; + const {activity: activities = [], name} = application; + + const mainActivity = activities.find((activity: Activity) => { + const intentFilter = activity['intent-filter']; + if (intentFilter) { + const {action, category} = intentFilter; + if (action && category) { + return action.name === MAIN_ACTION && category.name === LAUNCHER; + } + } + return false; + }); + let variants: Variants = {}; + try { + const appBuildConfig = flatten( + await g2js.parseFile(appGradlePath), + ) as any; + Object.keys(appBuildConfig).forEach(key => { + if (key.endsWith('applicationId')) { + // get defaultConfig and flavor + // key: android.defaultConfig.applicationId | android.productFlavor.flavor.applicationId + const variant = key.split('.').slice(-2)[0] as string; + variants[variant] = appBuildConfig[key]; + } + }); + } catch (error) {} + return { + packageName, + name, + mainActivity: mainActivity ? mainActivity.name : '', + variants, + }; + } else { + throw TypeError('Invalid Manifest'); + } +} diff --git a/packages/platform-android/src/commands/runAndroid/index.ts b/packages/platform-android/src/commands/runAndroid/index.ts index a9fa9db00..93d3a0db9 100644 --- a/packages/platform-android/src/commands/runAndroid/index.ts +++ b/packages/platform-android/src/commands/runAndroid/index.ts @@ -22,6 +22,7 @@ import { CLIError, } from '@react-native-community/cli-tools'; import warnAboutManuallyLinkedLibs from '../../link/warnAboutManuallyLinkedLibs'; +import {getApp} from './getApp'; // Verifies this is an Android project function checkAndroid(root: string) { @@ -118,16 +119,32 @@ function getPackageNameWithSuffix( } // Builds the app and runs it on a connected emulator / device. -function buildAndRun(args: Flags) { +async function buildAndRun(args: Flags) { process.chdir(path.join(args.root, 'android')); const cmd = process.platform.startsWith('win') ? 'gradlew.bat' : './gradlew'; // "app" is usually the default value for Android apps with only 1 app const {appFolder} = args; - // @ts-ignore - const packageName = fs - .readFileSync(`${appFolder}/src/main/AndroidManifest.xml`, 'utf8') - .match(/package="(.+?)"/)[1]; + const app = await getApp(appFolder); + + const {packageName, mainActivity, variants} = app; + + if (!args.mainActivity) { + // `mainActivity` start with `.`, remove it + args.mainActivity = mainActivity.replace('.', ''); + } + + if (!args.appId) { + if (args.variant) { + // variant always end with `Debug` or `Release` + const flavor = args.variant.replace(/Debug$/, '').replace(/Release$/, ''); + const appId = variants[flavor] || variants.defaultConfig; + + if (appId) { + args.appId = appId; + } + } + } const packageNameWithSuffix = getPackageNameWithSuffix( args.appId, @@ -403,7 +420,7 @@ export default { { name: '--main-activity [string]', description: 'Name of the activity to start', - default: 'MainActivity', + default: '', }, { name: '--deviceId [string]', diff --git a/yarn.lock b/yarn.lock index 9d4c2f829..8f855d4f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2626,6 +2626,11 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" +"@types/flat@^0.0.28": + version "0.0.28" + resolved "https://registry.yarnpkg.com/@types/flat/-/flat-0.0.28.tgz#5c788149d85a6cf8ff5f5f000acdd912cdea4274" + integrity sha1-XHiBSdhabPj/X18ACs3ZEs3qQnQ= + "@types/fs-extra@^8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.0.0.tgz#d3e2c313ca29f95059f198dd60d1f774642d4b25" @@ -5561,6 +5566,11 @@ fast-levenshtein@~2.0.4: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-xml-parser@^3.15.1: + version "3.15.1" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.15.1.tgz#7299ef53b00d5c0f9809599396a26e6d1af20603" + integrity sha512-MStlD6aNPZCd9msF5wBh2VJ0jAE2zz85ipk+OIPO+pZi64ckY//oGi5kskcTVRj2bMSmBI5F2SY1IGWHWZzbCA== + fastparse@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" @@ -5697,6 +5707,13 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" +flat@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.0.tgz#dab7d71d60413becb0ac2de9bf4304495e3af6af" + integrity sha512-6KSMM+cHHzXC/hpldXApL2S8Uz+QZv+tq5o/L0KQYleoG+GcwrnIJhTWC7tCOiKQp8D/fIvryINU1OZCCwevjA== + dependencies: + is-buffer "~2.0.4" + flush-write-stream@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" @@ -6045,6 +6062,13 @@ graceful-fs@^4.2.0: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +gradle-to-js@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gradle-to-js/-/gradle-to-js-2.0.0.tgz#b790a97376d3d713105a086590e569610f7e6bc4" + integrity sha512-eoYJiSoreHG0cS5aUmv7ISJhajuULlqdqG3QKVti6x1EFkBXE8rGH6ipGKWEesXpCkfNgzBrhzo5ztIH1JWZMw== + dependencies: + lodash.merge "4.6.2" + grapheme-breaker@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac" @@ -6546,6 +6570,11 @@ is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-buffer@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" @@ -7648,6 +7677,11 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= +lodash.merge@4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" From bf9c6c14e0b8cddf3150da857d36dfd536630a62 Mon Sep 17 00:00:00 2001 From: kagawagao Date: Thu, 19 Dec 2019 22:29:24 +0800 Subject: [PATCH 2/3] refactor: refactor readManifest.ts with fast-xml-parser --- packages/platform-android/package.json | 6 +- .../src/commands/runAndroid/getApp.ts | 73 +++++-------------- .../__fixtures__/files/AndroidManifest.xml | 17 ++++- .../src/config/__tests__/readManifest.test.ts | 8 +- packages/platform-android/src/config/index.ts | 7 +- .../src/config/readManifest.ts | 61 +++++++++++++++- yarn.lock | 14 +--- 7 files changed, 102 insertions(+), 84 deletions(-) diff --git a/packages/platform-android/package.json b/packages/platform-android/package.json index f79d13d28..ce3315a98 100644 --- a/packages/platform-android/package.json +++ b/packages/platform-android/package.json @@ -15,8 +15,7 @@ "gradle-to-js": "^2.0.0", "jetifier": "^1.6.2", "logkitty": "^0.6.0", - "slash": "^3.0.0", - "xmldoc": "^1.1.2" + "slash": "^3.0.0" }, "files": [ "build", @@ -27,7 +26,6 @@ "@types/execa": "^0.9.0", "@types/flat": "^0.0.28", "@types/fs-extra": "^8.0.0", - "@types/glob": "^7.1.1", - "@types/xmldoc": "^1.1.4" + "@types/glob": "^7.1.1" } } diff --git a/packages/platform-android/src/commands/runAndroid/getApp.ts b/packages/platform-android/src/commands/runAndroid/getApp.ts index a4c577835..d0b00bdd0 100644 --- a/packages/platform-android/src/commands/runAndroid/getApp.ts +++ b/packages/platform-android/src/commands/runAndroid/getApp.ts @@ -1,25 +1,17 @@ -import xmlParser from 'fast-xml-parser'; -import fs from 'fs'; // @ts-ignore import g2js from 'gradle-to-js/lib/parser'; import flatten from 'flat'; +import readManifest, {Manifest} from '../../config/readManifest'; -const MAIN_ACTION = 'android.intent.action.MAIN'; -const LAUNCHER = 'android.intent.category.LAUNCHER'; - -interface Activity { - [x: string]: any; -} - -interface Variants { +interface VariantMap { [k: string]: string; } -export interface App { +interface App extends Manifest { packageName: string; mainActivity: string; name: string; - variants: Variants; + variants: VariantMap; } // runtime cache @@ -36,48 +28,21 @@ export async function getApp(appFolder: string): Promise { } const manifestPath = `${appFolder}/src/main/AndroidManifest.xml`; const appGradlePath = `${appFolder}/build.gradle`; - const manifestContent = fs.readFileSync(manifestPath, {encoding: 'utf8'}); - if (xmlParser.validate(manifestContent)) { - const {manifest} = xmlParser.parse(manifestContent, { - attributeNamePrefix: '', - ignoreAttributes: false, - ignoreNameSpace: true, - }); - - const {package: packageName, application = {}} = manifest; - const {activity: activities = [], name} = application; - - const mainActivity = activities.find((activity: Activity) => { - const intentFilter = activity['intent-filter']; - if (intentFilter) { - const {action, category} = intentFilter; - if (action && category) { - return action.name === MAIN_ACTION && category.name === LAUNCHER; - } + const manifest = readManifest(manifestPath); + let variants: VariantMap = {}; + try { + const appBuildConfig = flatten(await g2js.parseFile(appGradlePath)) as any; + Object.keys(appBuildConfig).forEach(key => { + if (key.endsWith('applicationId')) { + // get defaultConfig and flavor + // key: android.defaultConfig.applicationId | android.productFlavor.flavor.applicationId + const variant = key.split('.').slice(-2)[0] as string; + variants[variant] = appBuildConfig[key]; } - return false; }); - let variants: Variants = {}; - try { - const appBuildConfig = flatten( - await g2js.parseFile(appGradlePath), - ) as any; - Object.keys(appBuildConfig).forEach(key => { - if (key.endsWith('applicationId')) { - // get defaultConfig and flavor - // key: android.defaultConfig.applicationId | android.productFlavor.flavor.applicationId - const variant = key.split('.').slice(-2)[0] as string; - variants[variant] = appBuildConfig[key]; - } - }); - } catch (error) {} - return { - packageName, - name, - mainActivity: mainActivity ? mainActivity.name : '', - variants, - }; - } else { - throw TypeError('Invalid Manifest'); - } + } catch (error) {} + return { + ...manifest, + variants, + }; } diff --git a/packages/platform-android/src/config/__fixtures__/files/AndroidManifest.xml b/packages/platform-android/src/config/__fixtures__/files/AndroidManifest.xml index 83cf6c799..acb348087 100644 --- a/packages/platform-android/src/config/__fixtures__/files/AndroidManifest.xml +++ b/packages/platform-android/src/config/__fixtures__/files/AndroidManifest.xml @@ -1,4 +1,15 @@ - + + + + + + + + + + + + + + diff --git a/packages/platform-android/src/config/__tests__/readManifest.test.ts b/packages/platform-android/src/config/__tests__/readManifest.test.ts index 231e5844d..990e7043a 100644 --- a/packages/platform-android/src/config/__tests__/readManifest.test.ts +++ b/packages/platform-android/src/config/__tests__/readManifest.test.ts @@ -29,8 +29,12 @@ describe('android::readManifest', () => { it('returns manifest content if file exists in the folder', () => { const manifestPath = findManifest('/nested'); - expect(readManifest(manifestPath)).not.toBeNull(); - expect(typeof readManifest(manifestPath)).toBe('object'); + const manifest = readManifest(manifestPath); + expect(manifest).not.toBeNull(); + expect(typeof manifest).toBe('object'); + expect(manifest.packageName).toBe('com.some.example'); + expect(manifest.mainActivity).toBe('.MainActivity'); + expect(manifest.name).toBe('.MainApplication'); }); it('throws an error if there is no manifest in the folder', () => { diff --git a/packages/platform-android/src/config/index.ts b/packages/platform-android/src/config/index.ts index db069bb2d..0d706c6a5 100644 --- a/packages/platform-android/src/config/index.ts +++ b/packages/platform-android/src/config/index.ts @@ -15,9 +15,6 @@ import { AndroidProjectParams, AndroidDependencyParams, } from '@react-native-community/cli-types'; -import {XmlDocument} from 'xmldoc'; - -const getPackageName = (manifest: XmlDocument) => manifest.attr.package; /** * Gets android project config by analyzing given folder and taking some @@ -45,7 +42,7 @@ export function projectConfig( const manifest = readManifest(manifestPath); - const packageName = userConfig.packageName || getPackageName(manifest); + const packageName = userConfig.packageName || manifest.packageName; if (!packageName) { throw new Error(`Package name not found in ${manifestPath}`); @@ -119,7 +116,7 @@ export function dependencyConfig( } const manifest = readManifest(manifestPath); - const packageName = userConfig.packageName || getPackageName(manifest); + const packageName = userConfig.packageName || manifest.packageName; const packageClassName = findPackageClassName(sourceDir); /** diff --git a/packages/platform-android/src/config/readManifest.ts b/packages/platform-android/src/config/readManifest.ts index 452e55ae7..ff5b32fab 100644 --- a/packages/platform-android/src/config/readManifest.ts +++ b/packages/platform-android/src/config/readManifest.ts @@ -7,8 +7,63 @@ */ import fs from 'fs'; -import xml from 'xmldoc'; +import xmlParser from 'fast-xml-parser'; -export default function readManifest(manifestPath: string) { - return new xml.XmlDocument(fs.readFileSync(manifestPath, 'utf8')); +const MAIN_ACTION = 'android.intent.action.MAIN'; +const LAUNCHER = 'android.intent.category.LAUNCHER'; + +interface Activity { + [x: string]: any; +} + +export interface Manifest { + packageName: string; + mainActivity: string; + name: string; +} + +export default function readManifest(manifestPath: string): Manifest { + const manifestContent = fs.readFileSync(manifestPath, {encoding: 'utf8'}); + // generally, validate will always return `true` + if (xmlParser.validate(manifestContent)) { + const {manifest} = xmlParser.parse(manifestContent, { + attributeNamePrefix: '', + ignoreAttributes: false, + ignoreNameSpace: true, + }); + + const {package: packageName, application = {}} = manifest; + const {activity = [], name} = application; + + let activities: Activity[] = []; + + if (!Array.isArray(activity)) { + activities = [activity]; + } else { + activities = activity; + } + + const mainActivity = activities.find((act: Activity) => { + const intentFilter = act['intent-filter']; + if (intentFilter) { + const {action, category} = intentFilter; + if (action && category) { + return action.name === MAIN_ACTION && category.name === LAUNCHER; + } + } + return false; + }); + return { + packageName, + name, + mainActivity: mainActivity ? mainActivity.name : '', + }; + } else { + // no error throw, but return empty string + return { + packageName: '', + mainActivity: '', + name: '', + }; + } } diff --git a/yarn.lock b/yarn.lock index 8f855d4f2..9c09cafe6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2806,11 +2806,6 @@ dependencies: "@types/node" "*" -"@types/xmldoc@^1.1.4": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@types/xmldoc/-/xmldoc-1.1.4.tgz#5867d4e29739719c633bf16413c5a4a4c1c3c802" - integrity sha512-a/ONNCf9itbmzEz1ohx0Fv5TLJzXIPQTapxFu+DlYlDtn9UcAa1OhnrOOMwbU8125hFjrkJKL3qllD7vO5Bivw== - "@types/yargs@^12.0.2", "@types/yargs@^12.0.9": version "12.0.12" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916" @@ -10563,7 +10558,7 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sax@^1.2.1, sax@^1.2.4, sax@~1.2.4: +sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -12139,13 +12134,6 @@ xmlchars@^2.1.1: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xmldoc@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/xmldoc/-/xmldoc-1.1.2.tgz#6666e029fe25470d599cd30e23ff0d1ed50466d7" - integrity sha512-ruPC/fyPNck2BD1dpz0AZZyrEwMOrWTO5lDdIXS91rs3wtm4j+T8Rp2o+zoOYkkAxJTZRPOSnOGei1egoRmKMQ== - dependencies: - sax "^1.2.1" - xmldom@0.1.x: version "0.1.27" resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" From c98d7eb5c28b397aa0ef40d43adce0bc32626af9 Mon Sep 17 00:00:00 2001 From: kagawagao Date: Thu, 19 Dec 2019 22:46:56 +0800 Subject: [PATCH 3/3] test: add test case for readManifest --- .../src/config/__fixtures__/android.ts | 9 +++++++++ .../files/AndroidManifest-one-activity.xml | 14 ++++++++++++++ .../src/config/__tests__/readManifest.test.ts | 15 +++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 packages/platform-android/src/config/__fixtures__/files/AndroidManifest-one-activity.xml diff --git a/packages/platform-android/src/config/__fixtures__/android.ts b/packages/platform-android/src/config/__fixtures__/android.ts index a1fa32cec..742d1e067 100644 --- a/packages/platform-android/src/config/__fixtures__/android.ts +++ b/packages/platform-android/src/config/__fixtures__/android.ts @@ -15,6 +15,9 @@ const manifest = fs.readFileSync( const mainJavaClass = fs.readFileSync( path.join(__dirname, './files/Main.java'), ); +const oneActivityManifest = fs.readFileSync( + path.join(__dirname, './files/AndroidManifest-one-activity.xml'), +); function generateValidFileStructure(classFileName: string) { return { @@ -232,3 +235,9 @@ export const findPackagesClassNameJavaNotValid = [ } `, ]; + +export const oneActivity = { + src: { + 'AndroidManifest.xml': oneActivityManifest, + }, +}; diff --git a/packages/platform-android/src/config/__fixtures__/files/AndroidManifest-one-activity.xml b/packages/platform-android/src/config/__fixtures__/files/AndroidManifest-one-activity.xml new file mode 100644 index 000000000..f618f7f0e --- /dev/null +++ b/packages/platform-android/src/config/__fixtures__/files/AndroidManifest-one-activity.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/packages/platform-android/src/config/__tests__/readManifest.test.ts b/packages/platform-android/src/config/__tests__/readManifest.test.ts index 990e7043a..99b73395f 100644 --- a/packages/platform-android/src/config/__tests__/readManifest.test.ts +++ b/packages/platform-android/src/config/__tests__/readManifest.test.ts @@ -24,6 +24,11 @@ describe('android::readManifest', () => { app: mocks.valid, }, }, + one: { + android: { + app: mocks.oneActivity, + }, + }, }); }); @@ -37,6 +42,16 @@ describe('android::readManifest', () => { expect(manifest.name).toBe('.MainApplication'); }); + it('returns manifest content if only one activity in manifest', () => { + const manifestPath = findManifest('/one'); + const manifest = readManifest(manifestPath); + expect(manifest).not.toBeNull(); + expect(typeof manifest).toBe('object'); + expect(manifest.packageName).toBe('com.some.example'); + expect(manifest.mainActivity).toBe('.MainActivity'); + expect(manifest.name).toBe('.MainApplication'); + }); + it('throws an error if there is no manifest in the folder', () => { const fakeManifestPath = findManifest('/empty'); expect(() => {