Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,30 @@ class ReactPlugin : Plugin<Project> {
configureCodegen(project, extension, rootExtension, isLibrary = false)
configureResources(project, extension)
configureBuildTypesForApp(project)

// Apply the namespace fallback to every Android library in the build, including third-party
// libraries that don't apply the `com.facebook.react` plugin and still rely on the manifest
// `package` attribute (which AGP 9 no longer accepts as a namespace). The per-library hook
// below only covers libraries that apply our plugin, so we additionally sweep all library
// subprojects from the app. We do this once, from the application project, because re-running
// a rootProject-wide traversal from every library breaks on AGP 9, which errors when
// `finalizeDsl` is registered after a project's DSL has been finalized.
// See https://github.com/facebook/react-native/pull/57038.
//
// We skip projects that have already been evaluated: AGP finalizes a project's DSL during/
// after its evaluation, so registering a `finalizeDsl` callback on an already-evaluated
// project is "too late" and fails on AGP 9. In a regular app build the app is evaluated
// before its libraries (see ReactRootProjectPlugin's `evaluationDependsOn(":app")`), so every
// library is still pending here. In composite/monorepo builds (e.g. rn-tester, where
// ReactAndroid is a sibling) some library projects are already evaluated by this point; those
// already define their own namespace, so skipping them is safe.
project.rootProject.allprojects { subproject ->
subproject.pluginManager.withPlugin("com.android.library") {
if (!subproject.state.executed) {
configureNamespaceForLibraries(subproject)
}
}
}
}

// Library Only Configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ internal object AgpConfiguratorUtils {
}

fun configureNamespaceForLibraries(project: Project) {
// This helper can be reached both from a library's own application of the React plugin and
// from the app-level sweep in ReactPlugin (which also covers libraries that don't apply
// `com.facebook.react`). A project's `finalizeDsl` callback must be registered before AGP
// finalizes its DSL — registering it twice (or after finalization) is a hard error on AGP 9+ —
// so we guard to register the namespace fallback at most once per project.
if (project.extensions.extraProperties.has(NAMESPACE_CONFIGURED_PROPERTY)) {
return
}
project.extensions.extraProperties.set(NAMESPACE_CONFIGURED_PROPERTY, true)
project.extensions.getByType(LibraryAndroidComponentsExtension::class.java).finalizeDsl { ext ->
if (ext.namespace == null) {
val manifestFile =
Expand All @@ -122,6 +131,8 @@ internal object AgpConfiguratorUtils {
}
}

private const val NAMESPACE_CONFIGURED_PROPERTY = "com.facebook.react.internal.namespaceConfigured"

const val DEFAULT_DEV_SERVER_PORT = "8081"

fun getPackageNameFromManifest(manifest: File): String? {
Expand Down
Loading