From 558a6e1b9f84e66849bea3bf8158f322a2eae427 Mon Sep 17 00:00:00 2001 From: Tommy Nguyen <4123478+tido64@users.noreply.github.com> Date: Fri, 19 Jan 2024 16:23:29 +0100 Subject: [PATCH] fix(android): use default app setup for New Arch (#1774) Fixes a crash on startup and reduces our footprint. --- android/app/build.gradle | 8 +- .../app/src/main/jni/ComponentsRegistry.cpp | 11 ++- .../compat/ReactNativeHostCompat.kt | 44 ---------- .../reacttestapp/fabric/ComponentsRegistry.kt | 36 --------- .../turbomodule/TurboModuleManagerDelegate.kt | 39 --------- .../compat/ReactNativeHostCompat.kt | 81 +++++-------------- .../com/microsoft/reacttestapp/TestApp.kt | 5 ++ android/dependencies.gradle | 6 +- example/android/gradle.properties | 4 +- test/pack.test.mjs | 3 - 10 files changed, 41 insertions(+), 196 deletions(-) delete mode 100644 android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt delete mode 100644 android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/fabric/ComponentsRegistry.kt delete mode 100644 android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/turbomodule/TurboModuleManagerDelegate.kt diff --git a/android/app/build.gradle b/android/app/build.gradle index 471a20442..f3de9aec0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -206,13 +206,7 @@ android { main.java.srcDirs += [ project.ext.react.enableCamera ? "src/camera/java" : "src/no-camera/java", - !enableNewArchitecture - ? "src/old-arch/java" - // TODO: Remove this block when we drop support for 0.73 - // https://github.com/facebook/react-native/commit/65552055392a5996bf50548018953875dde4560b - : reactNativeVersion >= v(0, 74, 0) - ? "src/new-arch-0.74/java" - : "src/new-arch/java", + enableNewArchitecture ? "src/new-arch/java" : "src/old-arch/java", // TODO: Remove this block when we drop support for 0.67 // https://github.com/facebook/react-native/commit/ce74aa4ed335d4c36ce722d47937b582045e05c4 diff --git a/android/app/src/main/jni/ComponentsRegistry.cpp b/android/app/src/main/jni/ComponentsRegistry.cpp index 43e714c02..f04d404ea 100644 --- a/android/app/src/main/jni/ComponentsRegistry.cpp +++ b/android/app/src/main/jni/ComponentsRegistry.cpp @@ -8,6 +8,8 @@ #include #endif +#include + #include #include #include @@ -25,6 +27,12 @@ using ReactTestApp::ComponentsRegistry; void ComponentsRegistry::registerNatives() { registerHybrid({makeNativeMethod("initHybrid", ComponentsRegistry::initHybrid)}); + + facebook::react::DefaultComponentsRegistry::registerComponentDescriptorsFromEntryPoint = + [](std::shared_ptr registry) { + // Register providers generated by `@react-native-community/cli` + rncli_registerProviders(registry); + }; } ComponentsRegistry::ComponentsRegistry(ComponentFactory *) @@ -39,9 +47,6 @@ ComponentsRegistry::initHybrid(facebook::jni::alias_ref, ComponentFactor -> ComponentDescriptorRegistry::Shared { auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry(); - // Register providers generated by `@react-native-community/cli` - rncli_registerProviders(providerRegistry); - auto registry = providerRegistry->createComponentDescriptorRegistry( {eventDispatcher, contextContainer}); diff --git a/android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt b/android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt deleted file mode 100644 index f8894101f..000000000 --- a/android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.microsoft.reacttestapp.compat - -import android.app.Application -import com.facebook.react.JSEngineResolutionAlgorithm -import com.facebook.react.ReactNativeHost -import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.UIManagerProvider -import com.facebook.react.fabric.ComponentFactory -import com.facebook.react.fabric.FabricUIManagerProviderImpl -import com.facebook.react.fabric.ReactNativeConfig -import com.facebook.react.uimanager.ViewManagerRegistry -import com.microsoft.reacttestapp.BuildConfig -import com.microsoft.reacttestapp.fabric.ComponentsRegistry -import com.microsoft.reacttestapp.turbomodule.TurboModuleManagerDelegate - -abstract class ReactNativeHostCompat(application: Application) : ReactNativeHost(application) { - override fun getReactPackageTurboModuleManagerDelegateBuilder() = - TurboModuleManagerDelegate.Builder() - - override fun getUIManagerProvider(): UIManagerProvider? = - if (BuildConfig.ReactTestApp_useFabric) { - UIManagerProvider { reactApplicationContext: ReactApplicationContext -> - val componentFactory = ComponentFactory() - - ComponentsRegistry.register(componentFactory) - - val viewManagers = reactInstanceManager.getOrCreateViewManagers( - reactApplicationContext - ) - val viewManagerRegistry = ViewManagerRegistry(viewManagers) - FabricUIManagerProviderImpl( - componentFactory, - ReactNativeConfig.DEFAULT_CONFIG, - viewManagerRegistry - ) - .createUIManager(reactApplicationContext) - } - } else { - null - } - - override fun getJSEngineResolutionAlgorithm(): JSEngineResolutionAlgorithm? = - JSEngineResolutionAlgorithm.HERMES -} diff --git a/android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/fabric/ComponentsRegistry.kt b/android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/fabric/ComponentsRegistry.kt deleted file mode 100644 index b467fe846..000000000 --- a/android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/fabric/ComponentsRegistry.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.microsoft.reacttestapp.fabric - -import com.facebook.jni.HybridData -import com.facebook.proguard.annotations.DoNotStrip -import com.facebook.react.fabric.ComponentFactory -import com.facebook.soloader.SoLoader - -/** - * The corresponding C++ implementation is in `android/app/src/main/jni/ComponentsRegistry.cpp` - */ -@DoNotStrip -class ComponentsRegistry @DoNotStrip private constructor( - componentFactory: ComponentFactory -) { - companion object { - @DoNotStrip - fun register(componentFactory: ComponentFactory): ComponentsRegistry { - return ComponentsRegistry(componentFactory) - } - - init { - SoLoader.loadLibrary("fabricjni") - SoLoader.loadLibrary("reacttestapp_appmodules") - } - } - - @DoNotStrip - private val mHybridData: HybridData - - @DoNotStrip - private external fun initHybrid(componentFactory: ComponentFactory): HybridData - - init { - mHybridData = initHybrid(componentFactory) - } -} diff --git a/android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/turbomodule/TurboModuleManagerDelegate.kt b/android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/turbomodule/TurboModuleManagerDelegate.kt deleted file mode 100644 index 0c843ce3d..000000000 --- a/android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/turbomodule/TurboModuleManagerDelegate.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.microsoft.reacttestapp.turbomodule - -import com.facebook.jni.HybridData -import com.facebook.react.ReactPackage -import com.facebook.react.ReactPackageTurboModuleManagerDelegate -import com.facebook.react.bridge.ReactApplicationContext - -/** - * These type aliases are here to prevent `@react-native-community/cli` from - * marking them as native modules to autolink. - * - * See also `matchClassName` in - * https://github.com/react-native-community/cli/blob/8.x/packages/platform-android/src/config/findPackageClassName.ts#L25 - */ -typealias PackagesList = List -typealias ReactTurboModuleManagerDelegate = ReactPackageTurboModuleManagerDelegate -typealias ReactTurboModuleManagerDelegateBuilder = ReactPackageTurboModuleManagerDelegate.Builder - -/** - * The corresponding C++ implementation is in `android/app/src/main/jni/TurboModuleManagerDelegate.cpp` - */ -class TurboModuleManagerDelegate protected constructor( - reactApplicationContext: ReactApplicationContext?, - packages: PackagesList? -) : ReactTurboModuleManagerDelegate(reactApplicationContext, packages) { - - external override fun initHybrid(): HybridData? - - external fun canCreateTurboModule(moduleName: String?): Boolean - - class Builder : ReactTurboModuleManagerDelegateBuilder() { - override fun build( - context: ReactApplicationContext?, - packages: PackagesList? - ): TurboModuleManagerDelegate { - return TurboModuleManagerDelegate(context, packages) - } - } -} diff --git a/android/app/src/new-arch/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt b/android/app/src/new-arch/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt index 2e1bcf4ca..9d6829ec6 100644 --- a/android/app/src/new-arch/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt +++ b/android/app/src/new-arch/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt @@ -1,68 +1,31 @@ package com.microsoft.reacttestapp.compat import android.app.Application -import com.facebook.react.ReactInstanceManager -import com.facebook.react.ReactNativeHost -import com.facebook.react.bridge.JSIModulePackage -import com.facebook.react.bridge.JSIModuleProvider -import com.facebook.react.bridge.JSIModuleSpec -import com.facebook.react.bridge.JSIModuleType -import com.facebook.react.bridge.JavaScriptContextHolder -import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.UIManager -import com.facebook.react.fabric.ComponentFactory -import com.facebook.react.fabric.CoreComponentsRegistry -import com.facebook.react.fabric.EmptyReactNativeConfig -import com.facebook.react.fabric.FabricJSIModuleProvider -import com.facebook.react.uimanager.ViewManagerRegistry +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.soloader.SoLoader import com.microsoft.reacttestapp.BuildConfig -import com.microsoft.reacttestapp.fabric.ComponentsRegistry -import com.microsoft.reacttestapp.turbomodule.TurboModuleManagerDelegate -import java.lang.ref.WeakReference -abstract class ReactNativeHostCompat(application: Application) : ReactNativeHost(application) { - override fun getReactPackageTurboModuleManagerDelegateBuilder() = - TurboModuleManagerDelegate.Builder() - - override fun getJSIModulePackage(): JSIModulePackage? { - return if (BuildConfig.ReactTestApp_useFabric) { - object : JSIModulePackage { - - private val reactInstanceManager: ReactInstanceManager? - get() = reactNativeHost.get()?.reactInstanceManager - - private val reactNativeHost: WeakReference = - WeakReference(this@ReactNativeHostCompat) - - override fun getJSIModules( - reactApplicationContext: ReactApplicationContext, - jsContext: JavaScriptContextHolder? - ): ArrayList> { - return arrayListOf(object : JSIModuleSpec { - override fun getJSIModuleType(): JSIModuleType = JSIModuleType.UIManager - - override fun getJSIModuleProvider(): JSIModuleProvider { - val componentFactory = ComponentFactory() - CoreComponentsRegistry.register(componentFactory) - - ComponentsRegistry.register(componentFactory) - - return FabricJSIModuleProvider( - reactApplicationContext, - componentFactory, - EmptyReactNativeConfig(), - ViewManagerRegistry( - reactInstanceManager?.getOrCreateViewManagers( - reactApplicationContext - ) - ) - ) - } - }) - } +abstract class ReactNativeHostCompat(application: Application) : DefaultReactNativeHost( + application +) { + companion object { + init { + try { + DefaultNewArchitectureEntryPoint.load( + /* turboModulesEnabled */ + BuildConfig.ReactTestApp_useFabric, + /* fabricEnabled */ + BuildConfig.ReactTestApp_useFabric + ) + } catch (e: UnsatisfiedLinkError) { + // Older versions of `DefaultNewArchitectureEntryPoint` is + // hard coded to load `libappmodules.so` } - } else { - null + SoLoader.loadLibrary("reacttestapp_appmodules") } } + + override val isNewArchEnabled: Boolean = BuildConfig.ReactTestApp_useFabric + override val isHermesEnabled: Boolean? = true } diff --git a/android/app/src/reactapplication-0.73/java/com/microsoft/reacttestapp/TestApp.kt b/android/app/src/reactapplication-0.73/java/com/microsoft/reacttestapp/TestApp.kt index 608aebb7b..8c22cbd52 100644 --- a/android/app/src/reactapplication-0.73/java/com/microsoft/reacttestapp/TestApp.kt +++ b/android/app/src/reactapplication-0.73/java/com/microsoft/reacttestapp/TestApp.kt @@ -5,6 +5,8 @@ import android.app.Application import android.content.Context import com.facebook.react.PackageList import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost import com.facebook.soloader.SoLoader import com.microsoft.reacttestapp.manifest.ManifestProvider import com.microsoft.reacttestapp.react.ReactBundleNameProvider @@ -21,6 +23,9 @@ class TestApp : Application(), ReactApplication { override val reactNativeHost: TestAppReactNativeHost get() = reactNativeHostInternal + override val reactHost: ReactHost + get() = getDefaultReactHost(this.applicationContext, reactNativeHost) + private lateinit var manifestProviderInternal: ManifestProvider private lateinit var reactNativeBundleNameProvider: ReactBundleNameProvider private lateinit var reactNativeHostInternal: TestAppReactNativeHost diff --git a/android/dependencies.gradle b/android/dependencies.gradle index 06792823c..7a26618ad 100644 --- a/android/dependencies.gradle +++ b/android/dependencies.gradle @@ -83,6 +83,9 @@ ext { // We need only set `ndkVersion` when building react-native from source. if (rootProject.hasProperty("ANDROID_NDK_VERSION")) { ndkVersion = rootProject.properties["ANDROID_NDK_VERSION"] + } else if (reactNativeVersion >= v(0, 74, 0)) { + // https://github.com/facebook/react-native/commit/9ce7b564131c5b2075489c09ff05325ddc28014a + ndkVersion = "26.1.10909125" } else if (System.properties["os.arch"] == "aarch64" && androidPluginVersion == "7.2.2") { // NDK r23c has been patched to support Apple M1 and is default in AGP // 7.3.0. Prior to 0.71, we still need to set `ndkVersion` because we'll @@ -91,9 +94,6 @@ ext { // default. See also // https://developer.android.com/studio/releases/gradle-plugin#compatibility-7-3-0 ndkVersion = "23.1.7779620" - } else if (reactNativeVersion >= v(0, 74, 0)) { - // https://github.com/facebook/react-native/commit/9ce7b564131c5b2075489c09ff05325ddc28014a - ndkVersion = "26.1.10909125" } def kotlinVersionNumber = toVersionNumber(kotlinVersion) diff --git a/example/android/gradle.properties b/example/android/gradle.properties index a2b58de91..c65407b6c 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -43,7 +43,7 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 #newArchEnabled=true # Uncomment the line below if building react-native from source -#ANDROID_NDK_VERSION=23.1.7779620 +#ANDROID_NDK_VERSION=26.1.10909125 # Version of Kotlin to build against. -#KOTLIN_VERSION=1.7.22 +#KOTLIN_VERSION=1.8.22 diff --git a/test/pack.test.mjs b/test/pack.test.mjs index e730f3276..13cc33938 100644 --- a/test/pack.test.mjs +++ b/test/pack.test.mjs @@ -77,9 +77,6 @@ describe("npm pack", () => { "android/app/src/main/res/values/colors.xml", "android/app/src/main/res/values/strings.xml", "android/app/src/main/res/values/styles.xml", - "android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt", - "android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/fabric/ComponentsRegistry.kt", - "android/app/src/new-arch-0.74/java/com/microsoft/reacttestapp/turbomodule/TurboModuleManagerDelegate.kt", "android/app/src/new-arch/java/com/microsoft/reacttestapp/compat/ReactNativeHostCompat.kt", "android/app/src/new-arch/java/com/microsoft/reacttestapp/fabric/ComponentsRegistry.kt", "android/app/src/new-arch/java/com/microsoft/reacttestapp/turbomodule/TurboModuleManagerDelegate.kt",