Skip to content

Commit

Permalink
feat: read main activity from AndroidManifest.xml automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
szymonrybczak committed Jun 14, 2023
1 parent 4650a8d commit 3113c8b
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type AndroidProjectConfig = {
sourceDir: string;
appName: string;
packageName: string;
mainActivity: string;
dependencyConfiguration?: string;
watchModeCommandParams: string;
};
Expand Down
1 change: 1 addition & 0 deletions packages/cli-platform-android/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"@react-native-community/cli-tools": "12.0.0-alpha.4",
"chalk": "^4.1.2",
"execa": "^5.0.0",
"fast-xml-parser": "^4.2.4",
"glob": "^7.1.3",
"logkitty": "^0.7.1"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ async function runAndroid(_argv: Array<string>, config: Config, args: Flags) {
link.setVersion(config.reactNativeVersion);
}

if (!args.mainActivity && config.project.android?.mainActivity) {
args.mainActivity = config.project.android?.mainActivity;
}

if (args.binaryPath) {
if (args.tasks) {
throw new CLIError(
Expand Down Expand Up @@ -283,7 +287,6 @@ export default {
{
name: '--main-activity <string>',
description: 'Name of the activity to start',
default: 'MainActivity',
},
{
name: '--deviceId <string>',
Expand Down
8 changes: 8 additions & 0 deletions packages/cli-platform-android/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {findLibraryName} from './findLibraryName';
import {findComponentDescriptors} from './findComponentDescriptors';
import {findBuildGradle} from './findBuildGradle';
import {CLIError} from '@react-native-community/cli-tools';
import readAndroidManifest from './readAndroidManifest';

/**
* Gets android project config by analyzing given folder and taking some
Expand Down Expand Up @@ -59,10 +60,17 @@ export function projectConfig(
);
}

const mainActivity = readAndroidManifest(manifestPath || '');

if (!mainActivity) {
throw new CLIError(`Main activity not found in ${manifestPath}`);
}

return {
sourceDir,
appName,
packageName,
mainActivity,
dependencyConfiguration: userConfig.dependencyConfiguration,
watchModeCommandParams: userConfig.watchModeCommandParams,
unstable_reactLegacyComponentNames:
Expand Down
110 changes: 110 additions & 0 deletions packages/cli-platform-android/src/config/readAndroidManifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import fs from 'fs';
import {XMLParser, XMLValidator} from 'fast-xml-parser';

const MAIN_ACTION = 'android.intent.action.MAIN';
const LAUNCHER = 'android.intent.category.LAUNCHER';

interface Activity {
[x: string]: any;
}

interface IntentFilter {
action:
| {
'@_android:name': string;
}
| {
'@_android:name': string;
}[];
category:
| {
'@_android:name': string;
}
| {
'@_android:name': string;
}[];
}

/**
* Reads the AndroidManifest.xml file and returns the name of the main activity.
*/

export default function readAndroidManifest(
manifestPath: string,
): string | null {
try {
const xmlParser = new XMLParser({ignoreAttributes: false});
const manifestContent = fs.readFileSync(manifestPath, {encoding: 'utf8'});

if (XMLValidator.validate(manifestContent)) {
const {manifest} = xmlParser.parse(manifestContent);

const application = manifest.application || {};
const activity = application.activity || {};

let activities: Activity[] = [];

if (!Array.isArray(activity)) {
activities = [activity];
} else {
activities = activity;
}

const mainActivity = activities.find((act: Activity) => {
let intentFilters = act['intent-filter'];

if (!intentFilters) {
return false;
}

if (!Array.isArray(intentFilters)) {
intentFilters = [intentFilters];
}

return intentFilters.find((intentFilter: IntentFilter) => {
const {action, category} = intentFilter;

let actions;
let categories;

if (!Array.isArray(action)) {
actions = [action];
} else {
actions = action;
}

if (!Array.isArray(category)) {
categories = [category];
} else {
categories = category;
}

if (actions && categories) {
const parsedActions: string[] = actions.map(
({'@_android:name': name}) => name,
);

const parsedCategories: string[] = categories.map(
({'@_android:name': name}) => name,
);

return (
parsedActions.includes(MAIN_ACTION) &&
parsedCategories.includes(LAUNCHER)
);
}

return false;
});
});

return mainActivity
? mainActivity['@_android:name'].replace('.', '')
: null;
} else {
return null;
}
} catch {
return null;
}
}
1 change: 1 addition & 0 deletions packages/cli-types/src/android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export interface AndroidProjectConfig {
sourceDir: string;
appName: string;
packageName: string;
mainActivity: string;
dependencyConfiguration?: string;
watchModeCommandParams?: string[];
unstable_reactLegacyComponentNames?: string[] | null;
Expand Down
7 changes: 7 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6104,6 +6104,13 @@ fast-xml-parser@^4.0.12:
dependencies:
strnum "^1.0.5"

fast-xml-parser@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.4.tgz#6e846ede1e56ad9e5ef07d8720809edf0ed07e9b"
integrity sha512-fbfMDvgBNIdDJLdLOwacjFAPYt67tr31H9ZhWSm45CDAxvd0I6WTlSOUo7K2P/K5sA5JgMKG64PI3DMcaFdWpQ==
dependencies:
strnum "^1.0.5"

fastparse@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
Expand Down

0 comments on commit 3113c8b

Please sign in to comment.