From 33bd2f6eaed3c583f5df852535a8789f8caadbaa Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Thu, 18 Aug 2022 03:35:23 -0700 Subject: [PATCH] Simplify the template for New Architecture using the .defaults package (#34445) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/34445 This commit simplifies the new app template by encapsulating a lot of configuration by using the `DefaultReactNativeHost` from the .defaults package. This should work for most of the users while still allowing advanced use cases by using the good old ReactNativeHost. Changelog: [Android] [Changed] - Simplify the template for New Architecture using the .defaults package Reviewed By: cipolleschi Differential Revision: D38820111 fbshipit-source-id: 4e9529a92e1681610e3a1a89fdf82e6d10a18809 --- template/android/app/build.gradle | 9 ++ .../java/com/helloworld/MainApplication.java | 33 +++-- .../MainApplicationReactNativeHost.java | 116 ------------------ .../components/MainComponentsRegistry.java | 36 ------ ...ApplicationTurboModuleManagerDelegate.java | 48 -------- .../android/app/src/main/jni/CMakeLists.txt | 2 +- ...nApplicationTurboModuleManagerDelegate.cpp | 9 -- ...ainApplicationTurboModuleManagerDelegate.h | 8 +- .../app/src/main/jni/MainComponentsRegistry.h | 2 +- 9 files changed, 33 insertions(+), 230 deletions(-) delete mode 100644 template/android/app/src/main/java/com/helloworld/newarchitecture/MainApplicationReactNativeHost.java delete mode 100644 template/android/app/src/main/java/com/helloworld/newarchitecture/components/MainComponentsRegistry.java delete mode 100644 template/android/app/src/main/java/com/helloworld/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java diff --git a/template/android/app/build.gradle b/template/android/app/build.gradle index 0914473b223e40..92fd20361b617f 100644 --- a/template/android/app/build.gradle +++ b/template/android/app/build.gradle @@ -129,6 +129,13 @@ def reactNativeArchitectures() { return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } +/** + * The name of the dynamic library for this application. This will contain all the + * compiled C++ code and will be loaded at runtime. + * The default is "appmodules" so that we'll have a `libappmodules.so` to load. + */ +def dynamicLibraryName = "appmodules" + android { ndkVersion rootProject.ext.ndkVersion @@ -141,6 +148,7 @@ android { versionCode 1 versionName "1.0" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + buildConfigField "String", "DYNAMIC_LIBRARY_NAME", "\"$dynamicLibraryName\"" if (isNewArchitectureEnabled()) { // We configure the CMake build only if you decide to opt-in for the New Architecture. @@ -150,6 +158,7 @@ android { "-DREACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid", "-DREACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build", "-DNODE_MODULES_DIR=$rootDir/../node_modules", + "-DTARGET_NAME=$dynamicLibraryName", "-DANDROID_STL=c++_shared" } } diff --git a/template/android/app/src/main/java/com/helloworld/MainApplication.java b/template/android/app/src/main/java/com/helloworld/MainApplication.java index 8c15d22c596318..3f1a59b34bb979 100644 --- a/template/android/app/src/main/java/com/helloworld/MainApplication.java +++ b/template/android/app/src/main/java/com/helloworld/MainApplication.java @@ -6,14 +6,14 @@ import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.config.ReactFeatureFlags; +import com.facebook.react.defaults.DefaultReactNativeHost; import com.facebook.soloader.SoLoader; -import com.helloworld.newarchitecture.MainApplicationReactNativeHost; import java.util.List; public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = - new ReactNativeHost(this) { + new DefaultReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; @@ -32,26 +32,35 @@ protected List getPackages() { protected String getJSMainModuleName() { return "index"; } - }; - private final ReactNativeHost mNewArchitectureNativeHost = - new MainApplicationReactNativeHost(this); + @Override + public String getDynamicLibraryName() { + // If you enabled the New Architecture, you need to return the name of the + // dynamic library to load (usually 'appmodule'). This is configured + // in your build.gradle file. + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + return BuildConfig.DYNAMIC_LIBRARY_NAME; + } else { + return null; + } + } + }; @Override public ReactNativeHost getReactNativeHost() { - if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { - return mNewArchitectureNativeHost; - } else { - return mReactNativeHost; - } + return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); - // If you opted-in for the New Architecture, we enable the TurboModule system - ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; SoLoader.init(this, /* native exopackage */ false); + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we enable the TurboModule system + // and load the native dynamic library for this app. + ReactFeatureFlags.useTurboModules = true; + SoLoader.loadLibrary(BuildConfig.DYNAMIC_LIBRARY_NAME); + } ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); } } diff --git a/template/android/app/src/main/java/com/helloworld/newarchitecture/MainApplicationReactNativeHost.java b/template/android/app/src/main/java/com/helloworld/newarchitecture/MainApplicationReactNativeHost.java deleted file mode 100644 index 55473c3f439377..00000000000000 --- a/template/android/app/src/main/java/com/helloworld/newarchitecture/MainApplicationReactNativeHost.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.helloworld.newarchitecture; - -import android.app.Application; -import androidx.annotation.NonNull; -import com.facebook.react.PackageList; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.ReactNativeHost; -import com.facebook.react.ReactPackage; -import com.facebook.react.ReactPackageTurboModuleManagerDelegate; -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.FabricJSIModuleProvider; -import com.facebook.react.fabric.ReactNativeConfig; -import com.facebook.react.uimanager.ViewManagerRegistry; -import com.helloworld.BuildConfig; -import com.helloworld.newarchitecture.components.MainComponentsRegistry; -import com.helloworld.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate; -import java.util.ArrayList; -import java.util.List; - -/** - * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both - * TurboModule delegates and the Fabric Renderer. - * - *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the - * `newArchEnabled` property). Is ignored otherwise. - */ -public class MainApplicationReactNativeHost extends ReactNativeHost { - public MainApplicationReactNativeHost(Application application) { - super(application); - } - - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - - @Override - protected List getPackages() { - List packages = new PackageList(this).getPackages(); - // Packages that cannot be autolinked yet can be added manually here, for example: - // packages.add(new MyReactNativePackage()); - // TurboModules must also be loaded here providing a valid TurboReactPackage implementation: - // packages.add(new TurboReactPackage() { ... }); - // If you have custom Fabric Components, their ViewManagers should also be loaded here - // inside a ReactPackage. - return packages; - } - - @Override - protected String getJSMainModuleName() { - return "index"; - } - - @NonNull - @Override - protected ReactPackageTurboModuleManagerDelegate.Builder - getReactPackageTurboModuleManagerDelegateBuilder() { - // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary - // for the new architecture and to use TurboModules correctly. - return new MainApplicationTurboModuleManagerDelegate.Builder(); - } - - @Override - protected JSIModulePackage getJSIModulePackage() { - return new JSIModulePackage() { - @Override - public List getJSIModules( - final ReactApplicationContext reactApplicationContext, - final JavaScriptContextHolder jsContext) { - final List specs = new ArrayList<>(); - - // Here we provide a new JSIModuleSpec that will be responsible of providing the - // custom Fabric Components. - specs.add( - new JSIModuleSpec() { - @Override - public JSIModuleType getJSIModuleType() { - return JSIModuleType.UIManager; - } - - @Override - public JSIModuleProvider getJSIModuleProvider() { - final ComponentFactory componentFactory = new ComponentFactory(); - CoreComponentsRegistry.register(componentFactory); - - // Here we register a Components Registry. - // The one that is generated with the template contains no components - // and just provides you the one from React Native core. - MainComponentsRegistry.register(componentFactory); - - final ReactInstanceManager reactInstanceManager = getReactInstanceManager(); - - ViewManagerRegistry viewManagerRegistry = - new ViewManagerRegistry( - reactInstanceManager.getOrCreateViewManagers(reactApplicationContext)); - - return new FabricJSIModuleProvider( - reactApplicationContext, - componentFactory, - ReactNativeConfig.DEFAULT_CONFIG, - viewManagerRegistry); - } - }); - return specs; - } - }; - } -} diff --git a/template/android/app/src/main/java/com/helloworld/newarchitecture/components/MainComponentsRegistry.java b/template/android/app/src/main/java/com/helloworld/newarchitecture/components/MainComponentsRegistry.java deleted file mode 100644 index c74d0ccadb6b8d..00000000000000 --- a/template/android/app/src/main/java/com/helloworld/newarchitecture/components/MainComponentsRegistry.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.helloworld.newarchitecture.components; - -import com.facebook.jni.HybridData; -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.react.fabric.ComponentFactory; -import com.facebook.soloader.SoLoader; - -/** - * Class responsible to load the custom Fabric Components. This class has native methods and needs a - * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ - * folder for you). - * - *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the - * `newArchEnabled` property). Is ignored otherwise. - */ -@DoNotStrip -public class MainComponentsRegistry { - static { - SoLoader.loadLibrary("fabricjni"); - } - - @DoNotStrip private final HybridData mHybridData; - - @DoNotStrip - private native HybridData initHybrid(ComponentFactory componentFactory); - - @DoNotStrip - private MainComponentsRegistry(ComponentFactory componentFactory) { - mHybridData = initHybrid(componentFactory); - } - - @DoNotStrip - public static MainComponentsRegistry register(ComponentFactory componentFactory) { - return new MainComponentsRegistry(componentFactory); - } -} diff --git a/template/android/app/src/main/java/com/helloworld/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java b/template/android/app/src/main/java/com/helloworld/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java deleted file mode 100644 index 8593b3bb850cd8..00000000000000 --- a/template/android/app/src/main/java/com/helloworld/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.helloworld.newarchitecture.modules; - -import com.facebook.jni.HybridData; -import com.facebook.react.ReactPackage; -import com.facebook.react.ReactPackageTurboModuleManagerDelegate; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.soloader.SoLoader; -import java.util.List; - -/** - * Class responsible to load the TurboModules. This class has native methods and needs a - * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ - * folder for you). - * - *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the - * `newArchEnabled` property). Is ignored otherwise. - */ -public class MainApplicationTurboModuleManagerDelegate - extends ReactPackageTurboModuleManagerDelegate { - - private static volatile boolean sIsSoLibraryLoaded; - - protected MainApplicationTurboModuleManagerDelegate( - ReactApplicationContext reactApplicationContext, List packages) { - super(reactApplicationContext, packages); - } - - protected native HybridData initHybrid(); - - native boolean canCreateTurboModule(String moduleName); - - public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder { - protected MainApplicationTurboModuleManagerDelegate build( - ReactApplicationContext context, List packages) { - return new MainApplicationTurboModuleManagerDelegate(context, packages); - } - } - - @Override - protected synchronized void maybeLoadOtherSoLibraries() { - if (!sIsSoLibraryLoaded) { - // If you change the name of your application .so file in the Android.mk file, - // make sure you update the name here as well. - SoLoader.loadLibrary("helloworld_appmodules"); - sIsSoLibraryLoaded = true; - } - } -} diff --git a/template/android/app/src/main/jni/CMakeLists.txt b/template/android/app/src/main/jni/CMakeLists.txt index d2cad3a3268dfa..ab770ef3412da9 100644 --- a/template/android/app/src/main/jni/CMakeLists.txt +++ b/template/android/app/src/main/jni/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.13) # Define the library name here. -project(helloworld_appmodules) +project(${TARGET_NAME}) # This file includes all the necessary to let you build your application with the New Architecture. include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake) diff --git a/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp b/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp index 5fd688c509d177..f459d6b53966a6 100644 --- a/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp +++ b/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp @@ -14,9 +14,6 @@ void MainApplicationTurboModuleManagerDelegate::registerNatives() { registerHybrid({ makeNativeMethod( "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid), - makeNativeMethod( - "canCreateTurboModule", - MainApplicationTurboModuleManagerDelegate::canCreateTurboModule), }); } @@ -35,11 +32,5 @@ MainApplicationTurboModuleManagerDelegate::getTurboModule( return MainApplicationModuleProvider(name, params); } -bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule( - const std::string &name) { - return getTurboModule(name, nullptr) != nullptr || - getTurboModule(name, {.moduleName = name}) != nullptr; -} - } // namespace react } // namespace facebook diff --git a/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h b/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h index 9ee38a81f6d8fc..712e6c4333b6aa 100644 --- a/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h +++ b/template/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h @@ -14,7 +14,7 @@ class MainApplicationTurboModuleManagerDelegate public: // Adapt it to the package you used for your Java class. static constexpr auto kJavaDescriptor = - "Lcom/helloworld/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;"; + "Lcom/facebook/react/defaults/DefaultTurboModuleManagerDelegate;"; static jni::local_ref initHybrid(jni::alias_ref); @@ -26,12 +26,6 @@ class MainApplicationTurboModuleManagerDelegate std::shared_ptr getTurboModule( const std::string &name, const JavaTurboModule::InitParams ¶ms) override; - - /** - * Test-only method. Allows user to verify whether a TurboModule can be - * created by instances of this class. - */ - bool canCreateTurboModule(const std::string &name); }; } // namespace react diff --git a/template/android/app/src/main/jni/MainComponentsRegistry.h b/template/android/app/src/main/jni/MainComponentsRegistry.h index d61cbffaae4a6c..527affbafd11c4 100644 --- a/template/android/app/src/main/jni/MainComponentsRegistry.h +++ b/template/android/app/src/main/jni/MainComponentsRegistry.h @@ -13,7 +13,7 @@ class MainComponentsRegistry public: // Adapt it to the package you used for your Java class. constexpr static auto kJavaDescriptor = - "Lcom/helloworld/newarchitecture/components/MainComponentsRegistry;"; + "Lcom/facebook/react/defaults/DefaultComponentsRegistry;"; static void registerNatives();